Merge branch 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 03:13:49 +0000 (19:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 03:13:49 +0000 (19:13 -0800)
Pull x86 cleanup patches from Ingo Molnar:
 "Misc smaller cleanups"

* 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86: ptrace.c only needs export.h and not the full module.h
  x86, apb_timer: remove unused variable percpu_timer
  um: don't compare a pointer to 0
  arch/x86/platform/uv: use ARRAY_SIZE where possible

3172 files changed:
Documentation/ABI/testing/sysfs-bus-event_source-devices-events [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-rbd
Documentation/ABI/testing/sysfs-devices-node [deleted file]
Documentation/DocBook/media/v4l/driver.xml
Documentation/PCI/MSI-HOWTO.txt
Documentation/PCI/pci-iov-howto.txt
Documentation/PCI/pci.txt
Documentation/acpi/enumeration.txt
Documentation/atomic_ops.txt
Documentation/device-mapper/dm-raid.txt
Documentation/devicetree/bindings/clock/imx23-clock.txt
Documentation/devicetree/bindings/clock/imx25-clock.txt
Documentation/devicetree/bindings/clock/imx28-clock.txt
Documentation/devicetree/bindings/clock/imx6q-clock.txt
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-sirf.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/davinci-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt [new file with mode: 0644]
Documentation/filesystems/00-INDEX
Documentation/filesystems/Locking
Documentation/filesystems/caching/backend-api.txt
Documentation/filesystems/caching/netfs-api.txt
Documentation/filesystems/caching/object.txt
Documentation/filesystems/caching/operations.txt
Documentation/filesystems/f2fs.txt [new file with mode: 0644]
Documentation/filesystems/nfs/nfs41-server.txt
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
Documentation/hid/hid-sensor.txt [changed mode: 0755->0644]
Documentation/i2c/instantiating-devices
Documentation/kernel-parameters.txt
Documentation/memory-barriers.txt
Documentation/networking/ip-sysctl.txt
Documentation/power/runtime_pm.txt
Documentation/rpmsg.txt
Documentation/spi/spi-summary
Documentation/sysctl/kernel.txt
Documentation/trace/ftrace.txt
Documentation/video4linux/v4l2-framework.txt
Documentation/x86/boot.txt
Documentation/x86/zero-page.txt
Documentation/zh_CN/video4linux/v4l2-framework.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/include/asm/parport.h
arch/alpha/include/asm/ptrace.h
arch/alpha/include/asm/unistd.h
arch/alpha/include/uapi/asm/signal.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/sys_titan.c
arch/arm/Kconfig
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/armada-xp-mv78460.dtsi
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/cros5250-common.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove-cubox.dts
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/ecx-2000.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5440-ssdk5440.dts
arch/arm/boot/dts/highbank.dts
arch/arm/boot/dts/imx23-olinuxino.dts
arch/arm/boot/dts/imx31-bug.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/kirkwood-6282.dtsi
arch/arm/boot/dts/kirkwood-ns2-common.dtsi
arch/arm/boot/dts/kirkwood-topkick.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/kizbox.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts [new file with mode: 0644]
arch/arm/boot/dts/sun4i-a10.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sun4i-cubieboard.dts [deleted file]
arch/arm/boot/dts/sun4i.dtsi [deleted file]
arch/arm/boot/dts/sun5i-a13-olinuxino.dts [new file with mode: 0644]
arch/arm/boot/dts/sun5i-a13.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sun5i-olinuxino.dts [deleted file]
arch/arm/boot/dts/sun5i.dtsi [deleted file]
arch/arm/boot/dts/sunxi.dtsi
arch/arm/boot/dts/twl4030.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/common/gic.c
arch/arm/common/sa1111.c
arch/arm/common/scoop.c
arch/arm/common/vic.c
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/memory.h
arch/arm/include/asm/smp_scu.h
arch/arm/include/asm/unistd.h
arch/arm/include/uapi/asm/signal.h
arch/arm/kernel/bios32.c
arch/arm/kernel/debug.S
arch/arm/kernel/etm.c
arch/arm/kernel/head.S
arch/arm/kernel/hyp-stub.S
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/perf_event_v6.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/perf_event_xscale.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp_scu.c
arch/arm/kernel/swp_emulate.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/cdce949.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/dev-audio.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-highbank/hotplug.c
arch/arm/mach-highbank/platsmp.c
arch/arm/mach-highbank/pm.c
arch/arm/mach-highbank/sysregs.h
arch/arm/mach-highbank/system.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/cpufreq.c
arch/arm/mach-imx/devices/devices-common.h
arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
arch/arm/mach-imx/devices/platform-imx-fb.c
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/iram.h [deleted file]
arch/arm/mach-imx/iram_alloc.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-imx/platsmp.c
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/board-ns2.c
arch/arm/mach-kirkwood/board-usi_topkick.c
arch/arm/mach-kirkwood/pcie.c
arch/arm/mach-ks8695/board-acs5k.c
arch/arm/mach-mmp/sram.c
arch/arm/mach-msm/proc_comm.c
arch/arm/mach-msm/smd.c
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-mvebu/Makefile
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nomadik/include/mach/irqs.h
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/fb.c [new file with mode: 0644]
arch/arm/mach-omap1/mailbox.c
arch/arm/mach-omap1/usb.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/cclock2420_data.c
arch/arm/mach-omap2/cclock2430_data.c
arch/arm/mach-omap2/cclock3xxx_data.c
arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/drm.c
arch/arm/mach-omap2/dss-common.c
arch/arm/mach-omap2/fb.c [new file with mode: 0644]
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_twl.c
arch/arm/mach-omap2/pmu.c
arch/arm/mach-omap2/prm2xxx.c
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm3xxx.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/timer.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-prima2/pm.c
arch/arm/mach-prima2/rtciobrg.c
arch/arm/mach-pxa/corgi_pm.c
arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-pxa/tosa-bt.c
arch/arm/mach-realview/include/mach/board-eb.h
arch/arm/mach-realview/include/mach/irqs-eb.h
arch/arm/mach-s3c24xx/h1940-bluetooth.c
arch/arm/mach-s3c24xx/mach-osiris-dvs.c
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/dev-audio.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mach-s5p64x0/clock-s5p6440.c
arch/arm/mach-s5p64x0/clock-s5p6450.c
arch/arm/mach-s5p64x0/dev-audio.c
arch/arm/mach-s5pc100/clock.c
arch/arm/mach-s5pc100/dev-audio.c
arch/arm/mach-s5pv210/dev-audio.c
arch/arm/mach-sa1100/jornada720_ssp.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sunxi/sunxi.c
arch/arm/mach-tegra/pcie.c
arch/arm/mach-tegra/tegra2_emc.c
arch/arm/mach-u300/dummyspichip.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-versatile/include/mach/irqs.h
arch/arm/mach-vexpress/Kconfig
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-v7.S
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v7.S
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/fb.c [deleted file]
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/sram.c
arch/arm/plat-pxa/ssp.c
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/gpio-core.h
arch/arm/plat-versatile/headsmp.S
arch/arm/vfp/entry.S
arch/arm/vfp/vfphw.S
arch/arm64/Kconfig
arch/arm64/boot/dts/Makefile
arch/arm64/include/asm/compat.h
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/vdso.c
arch/arm64/kernel/vdso/gettimeofday.S
arch/avr32/Kconfig
arch/avr32/include/asm/dma-mapping.h
arch/avr32/include/asm/ptrace.h
arch/avr32/include/asm/unistd.h
arch/avr32/include/uapi/asm/signal.h
arch/avr32/lib/delay.c
arch/blackfin/Kconfig
arch/blackfin/include/asm/dma-mapping.h
arch/blackfin/include/asm/ptrace.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/mach-common/dpmc.c
arch/c6x/Kconfig
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/dma-mapping.h
arch/c6x/include/asm/mmu.h [deleted file]
arch/c6x/include/uapi/asm/unistd.h
arch/cris/Kconfig
arch/cris/arch-v32/drivers/pci/bios.c
arch/cris/arch-v32/kernel/smp.c
arch/cris/include/asm/dma-mapping.h
arch/cris/include/asm/ptrace.h
arch/cris/include/asm/unistd.h
arch/cris/include/uapi/asm/signal.h
arch/frv/Kconfig
arch/frv/include/asm/dma-mapping.h
arch/frv/include/asm/unistd.h
arch/frv/kernel/setup.c
arch/frv/mb93090-mb00/pci-vdk.c
arch/h8300/Kconfig
arch/h8300/include/asm/Kbuild
arch/h8300/include/asm/mmu.h [deleted file]
arch/h8300/include/asm/ptrace.h
arch/h8300/include/asm/unistd.h
arch/h8300/include/uapi/asm/signal.h
arch/hexagon/Kconfig
arch/hexagon/include/uapi/asm/unistd.h
arch/ia64/Kconfig
arch/ia64/include/asm/acpi.h
arch/ia64/include/asm/cputime.h
arch/ia64/include/asm/iosapic.h
arch/ia64/include/asm/parport.h
arch/ia64/include/asm/ptrace.h
arch/ia64/include/asm/smp.h
arch/ia64/include/asm/thread_info.h
arch/ia64/include/asm/unistd.h
arch/ia64/include/asm/xen/minstate.h
arch/ia64/include/uapi/asm/signal.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/fsys.S
arch/ia64/kernel/head.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/ivt.S
arch/ia64/kernel/minstate.h
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/mm/init.c
arch/ia64/mm/tlb.c
arch/ia64/pci/fixup.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/io_common.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/ia64/xen/irq_xen.c
arch/m32r/Kconfig
arch/m32r/include/asm/ptrace.h
arch/m32r/include/asm/unistd.h
arch/m32r/include/uapi/asm/signal.h
arch/m32r/kernel/smpboot.c
arch/m68k/Kconfig
arch/m68k/emu/nfeth.c
arch/m68k/include/asm/dma-mapping.h
arch/m68k/include/asm/parport.h
arch/m68k/include/asm/pgtable_no.h
arch/m68k/include/asm/processor.h
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/signal.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/pcibios.c
arch/m68k/kernel/syscalltable.S
arch/m68k/mm/init.c
arch/microblaze/Kconfig
arch/microblaze/configs/mmu_defconfig
arch/microblaze/configs/nommu_defconfig
arch/microblaze/include/asm/highmem.h
arch/microblaze/include/asm/ptrace.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/include/uapi/asm/unistd.h
arch/microblaze/kernel/syscall_table.S
arch/microblaze/pci/pci-common.c
arch/mips/Kconfig
arch/mips/alchemy/common/time.c
arch/mips/bcm47xx/Kconfig
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/cavium-octeon/serial.c
arch/mips/include/asm/break.h [deleted file]
arch/mips/include/asm/dsp.h
arch/mips/include/asm/inst.h
arch/mips/include/asm/mach-pnx833x/war.h
arch/mips/include/asm/page.h
arch/mips/include/asm/pci.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/unistd.h
arch/mips/include/uapi/asm/Kbuild
arch/mips/include/uapi/asm/break.h [new file with mode: 0644]
arch/mips/include/uapi/asm/signal.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/ftrace.c
arch/mips/kernel/genex.S
arch/mips/kernel/head.S
arch/mips/kernel/mcount.S
arch/mips/kernel/octeon_switch.S
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/relocate_kernel.S
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smp.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kernel/vpe.c
arch/mips/lantiq/irq.c
arch/mips/lantiq/xway/dma.c
arch/mips/lantiq/xway/gptu.c
arch/mips/lantiq/xway/xrx200_phy_fw.c
arch/mips/lib/delay.c
arch/mips/mm/mmap.c
arch/mips/mm/tlbex-fault.S
arch/mips/mm/tlbex.c
arch/mips/mti-sead3/sead3-i2c-drv.c
arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
arch/mips/netlogic/xlr/setup.c
arch/mips/pci/fixup-cobalt.c
arch/mips/pci/fixup-emma2rh.c
arch/mips/pci/fixup-fuloong2e.c
arch/mips/pci/fixup-lemote2f.c
arch/mips/pci/fixup-malta.c
arch/mips/pci/fixup-rc32434.c
arch/mips/pci/fixup-sb1250.c
arch/mips/pci/ops-bcm63xx.c
arch/mips/pci/ops-tx4927.c
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci-ar71xx.c
arch/mips/pci/pci-ar724x.c
arch/mips/pci/pci-ip27.c
arch/mips/pci/pci-lantiq.c
arch/mips/pci/pci.c
arch/mips/power/hibernate.S
arch/mips/sni/setup.c
arch/mips/txx9/generic/pci.c
arch/mn10300/Kconfig
arch/mn10300/include/asm/dma-mapping.h
arch/mn10300/include/asm/unistd.h
arch/mn10300/include/uapi/asm/signal.h
arch/mn10300/kernel/smp.c
arch/mn10300/unit-asb2305/pci.c
arch/openrisc/Kconfig
arch/openrisc/include/asm/io.h
arch/openrisc/include/uapi/asm/unistd.h
arch/openrisc/lib/delay.c
arch/parisc/Kconfig
arch/parisc/include/asm/dma-mapping.h
arch/parisc/include/asm/parport.h
arch/parisc/include/asm/unistd.h
arch/parisc/include/uapi/asm/signal.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/hardware.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/signal.c
arch/parisc/math-emu/cnv_float.h
arch/powerpc/Kconfig
arch/powerpc/configs/chroma_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/include/asm/cputime.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/io-workarounds.h
arch/powerpc/include/asm/lppaca.h
arch/powerpc/include/asm/parport.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/asm/vio.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/include/uapi/asm/signal.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/io-workarounds.c
arch/powerpc/kernel/isa-bridge.c
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/pci_of_scan.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/smp-tbsync.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/book3s_hv_ras.c
arch/powerpc/kvm/emulate.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/tlb_hash64.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power7-pmu.c
arch/powerpc/platforms/40x/ppc40x_simple.c
arch/powerpc/platforms/44x/currituck.c
arch/powerpc/platforms/44x/virtex_ml510.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
arch/powerpc/platforms/82xx/ep8248e.c
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/tqm85xx.c
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/syscalls.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/fsl_uli1575.c
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/pasemi/cpufreq.c
arch/powerpc/platforms/pasemi/gpio_mdio.c
arch/powerpc/platforms/pasemi/pasemi.h
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci-p5ioc2.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/ps3/repository.c
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/eeh_dev.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/wsp/scom_smp.c
arch/powerpc/platforms/wsp/smp.c
arch/powerpc/platforms/wsp/wsp.h
arch/powerpc/platforms/wsp/wsp_pci.c
arch/powerpc/sysdev/bestcomm/bestcomm.c
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
arch/powerpc/sysdev/fsl_ifc.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_msgr.c
arch/powerpc/sysdev/mv64x60_pci.c
arch/powerpc/sysdev/ppc4xx_msi.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/include/asm/compat.h
arch/s390/include/asm/dma.h
arch/s390/include/asm/io.h
arch/s390/include/asm/irq.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/timex.h
arch/s390/include/asm/unistd.h
arch/s390/include/uapi/asm/signal.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/debug.c
arch/s390/kernel/irq.c
arch/s390/kernel/nmi.c
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/runtime_instr.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/vtime.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/fault.c
arch/s390/oprofile/hwsampler.c
arch/s390/pci/pci.c
arch/s390/pci/pci_dma.c
arch/score/Kconfig
arch/score/include/asm/ptrace.h
arch/score/include/uapi/asm/unistd.h
arch/score/mm/cache.c
arch/sh/Kconfig
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/pci.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/include/asm/elf.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/sh/include/asm/unistd.h
arch/sh/include/uapi/asm/unistd_32.h
arch/sh/include/uapi/asm/unistd_64.h
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/lib/mcount.S
arch/sparc/Kconfig
arch/sparc/include/asm/parport.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/timer_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/include/uapi/asm/signal.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/apc.c
arch/sparc/kernel/auxio_64.c
arch/sparc/kernel/central.c
arch/sparc/kernel/chmc.c
arch/sparc/kernel/ds.c
arch/sparc/kernel/ldc.c
arch/sparc/kernel/leon_pci.c
arch/sparc/kernel/leon_pci_grpci2.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/pci_fire.c
arch/sparc/kernel/pci_psycho.c
arch/sparc/kernel/pci_sabre.c
arch/sparc/kernel/pci_schizo.c
arch/sparc/kernel/pci_sun4v.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/pmc.c
arch/sparc/kernel/power.c
arch/sparc/kernel/sbus.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/time_32.c
arch/sparc/kernel/time_64.c
arch/sparc/mm/gup.c
arch/sparc/mm/init_64.c
arch/tile/Kconfig
arch/tile/include/asm/io.h
arch/tile/include/asm/irqflags.h
arch/tile/include/asm/pci.h
arch/tile/include/asm/ptrace.h
arch/tile/include/asm/unistd.h
arch/tile/include/uapi/arch/interrupts_32.h
arch/tile/include/uapi/arch/interrupts_64.h
arch/tile/kernel/intvec_64.S
arch/tile/kernel/pci.c
arch/tile/kernel/pci_gx.c
arch/tile/kernel/process.c
arch/tile/kernel/reboot.c
arch/tile/kernel/setup.c
arch/tile/kernel/stack.c
arch/tile/lib/cacheflush.c
arch/tile/lib/cpumask.c
arch/tile/lib/exports.c
arch/tile/mm/homecache.c
arch/um/kernel/signal.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/ptrace.h
arch/unicore32/include/uapi/asm/unistd.h
arch/unicore32/kernel/pci.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/boot/header.S
arch/x86/boot/setup.ld
arch/x86/boot/tools/build.c
arch/x86/configs/i386_defconfig
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/bootparam_utils.h [new file with mode: 0644]
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/ftrace.h
arch/x86/include/asm/hpet.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/hypervisor.h
arch/x86/include/asm/ia32.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/irq_remapping.h
arch/x86/include/asm/kvm_para.h
arch/x86/include/asm/linkage.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/parport.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_32.h
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/required-features.h
arch/x86/include/asm/sys_ia32.h
arch/x86/include/asm/syscalls.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/uv/uv.h
arch/x86/include/asm/x86_init.h
arch/x86/include/asm/xor.h
arch/x86/include/asm/xor_32.h
arch/x86/include/asm/xor_64.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/include/uapi/asm/mce.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/include/uapi/asm/signal.h
arch/x86/kernel/Makefile
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/ipi.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/cpu/vmware.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/hpet.c
arch/x86/kernel/kprobes-common.h [deleted file]
arch/x86/kernel/kprobes-opt.c [deleted file]
arch/x86/kernel/kprobes.c [deleted file]
arch/x86/kernel/kprobes/Makefile [new file with mode: 0644]
arch/x86/kernel/kprobes/common.h [new file with mode: 0644]
arch/x86/kernel/kprobes/core.c [new file with mode: 0644]
arch/x86/kernel/kprobes/ftrace.c [new file with mode: 0644]
arch/x86/kernel/kprobes/opt.c [new file with mode: 0644]
arch/x86/kernel/kvm.c
arch/x86/kernel/msr.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/quirks.c
arch/x86/kernel/reboot.c
arch/x86/kernel/rtc.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/step.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uprobes.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/x86.c
arch/x86/lib/delay.c
arch/x86/mm/fault.c
arch/x86/mm/init_64.c
arch/x86/pci/acpi.c
arch/x86/pci/bus_numa.c
arch/x86/pci/common.c
arch/x86/pci/fixup.c
arch/x86/pci/legacy.c
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/pci/mrst.c
arch/x86/pci/numaq_32.c
arch/x86/pci/pcbios.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/mrst/mrst.c
arch/x86/platform/olpc/olpc-xo1-pm.c
arch/x86/platform/olpc/olpc-xo1-sci.c
arch/x86/platform/scx200/scx200_32.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
arch/x86/tools/insn_sanity.c
arch/x86/tools/relocs.c
arch/x86/um/Kconfig
arch/x86/um/asm/ptrace.h
arch/x86/um/signal.c
arch/x86/um/sys_call_table_32.c
arch/x86/um/sys_call_table_64.c
arch/x86/vdso/vclock_gettime.c
arch/x86/xen/enlighten.c
arch/x86/xen/smp.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-asm_32.S
arch/x86/xen/xen-ops.h
arch/xtensa/Kconfig
arch/xtensa/include/asm/dma-mapping.h
arch/xtensa/include/asm/mmu.h
arch/xtensa/include/asm/nommu.h [deleted file]
arch/xtensa/include/asm/ptrace.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/include/uapi/asm/signal.h
block/blk-exec.c
block/genhd.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/utclib.c [deleted file]
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/cper.c
drivers/acpi/apei/erst-dbg.c
drivers/acpi/device_pm.c
drivers/acpi/glue.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/scan.c
drivers/amba/bus.c
drivers/amba/tegra-ahb.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_platform.c
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_arasan_cf.c
drivers/ata/pata_at91.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_ep93xx.c
drivers/ata/pata_icside.c
drivers/ata/pata_imx.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_macio.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_octeon_cf.c
drivers/ata/pata_of_platform.c
drivers/ata/pata_palmld.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_platform.c
drivers/ata/pata_pxa.c
drivers/ata/pata_rb532_cf.c
drivers/ata/pata_rdc.c
drivers/ata/pata_sch.c
drivers/ata/pata_sil680.c
drivers/ata/sata_highbank.c
drivers/ata/sata_mv.c
drivers/ata/sata_vsc.c
drivers/atm/ambassador.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/horizon.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/iphase.h
drivers/atm/lanai.c
drivers/atm/nicstar.c
drivers/atm/solos-pci.c
drivers/atm/zatm.c
drivers/auxdisplay/cfag12864bfb.c
drivers/base/cpu.c
drivers/base/devtmpfs.c
drivers/base/firmware_class.c
drivers/base/power/main.c
drivers/base/power/qos.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/bcma/Kconfig
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon_nflash.c
drivers/bcma/driver_chipcommon_sflash.c
drivers/bcma/driver_gmac_cmn.c
drivers/bcma/driver_gpio.c
drivers/bcma/driver_pci.c
drivers/bcma/driver_pci_host.c
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_state.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/nvme.c
drivers/block/ps3disk.c
drivers/block/ps3vram.c
drivers/block/rbd.c
drivers/block/rbd_types.h
drivers/block/sunvdc.c
drivers/block/swim.c
drivers/block/swim3.c
drivers/block/umem.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkfront.c
drivers/block/xsysace.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/omap-ocp2scp.c
drivers/bus/omap_l3_noc.c
drivers/cdrom/gdrom.c
drivers/char/agp/ali-agp.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/efficeon-agp.c
drivers/char/agp/i460-agp.c
drivers/char/agp/intel-agp.c
drivers/char/agp/nvidia-agp.c
drivers/char/agp/sgi-agp.c
drivers/char/agp/sis-agp.c
drivers/char/agp/sworks-agp.c
drivers/char/agp/uninorth-agp.c
drivers/char/agp/via-agp.c
drivers/char/hw_random/atmel-rng.c
drivers/char/hw_random/bcm63xx-rng.c
drivers/char/hw_random/exynos-rng.c
drivers/char/hw_random/n2-drv.c
drivers/char/hw_random/octeon-rng.c
drivers/char/hw_random/omap-rng.c
drivers/char/hw_random/pasemi-rng.c
drivers/char/hw_random/picoxcell-rng.c
drivers/char/hw_random/ppc4xx-rng.c
drivers/char/hw_random/timeriomem-rng.c
drivers/char/hw_random/virtio-rng.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/virtio_console.c
drivers/clk/clk-twl6040.c
drivers/clk/mvebu/clk-cpu.c
drivers/clk/mvebu/clk-gating-ctrl.c
drivers/clk/ux500/abx500-clk.c
drivers/clocksource/acpi_pm.c
drivers/clocksource/em_sti.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
drivers/connector/connector.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/Makefile
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpuidle/coupled.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/atmel-aes.c
drivers/crypto/atmel-sha.c
drivers/crypto/atmel-tdes.c
drivers/crypto/bfin_crc.c
drivers/crypto/caam/ctrl.c
drivers/crypto/geode-aes.c
drivers/crypto/hifn_795x.c
drivers/crypto/mv_cesa.c
drivers/crypto/n2_core.c
drivers/crypto/nx/nx.c
drivers/crypto/omap-sham.c
drivers/crypto/picoxcell_crypto.c
drivers/crypto/tegra-aes.c
drivers/devfreq/devfreq.c
drivers/devfreq/exynos4_bus.c
drivers/dma/dw_dmac.c
drivers/dma/edma.c
drivers/dma/imx-dma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/dca.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/dma_v3.c
drivers/dma/ioat/pci.c
drivers/dma/iop-adma.c
drivers/dma/mmp_pdma.c
drivers/dma/mmp_tdma.c
drivers/dma/mpc512x_dma.c
drivers/dma/mv_xor.c
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/sa11x0-dma.c
drivers/dma/sh/shdma.c
drivers/dma/sirf-dma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/timb_dma.c
drivers/edac/Kconfig
drivers/edac/amd64_edac.c
drivers/edac/amd76x_edac.c
drivers/edac/cell_edac.c
drivers/edac/cpc925_edac.c
drivers/edac/e752x_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_pci_sysfs.c
drivers/edac/highbank_l2_edac.c
drivers/edac/highbank_mc_edac.c
drivers/edac/i3000_edac.c
drivers/edac/i3200_edac.c
drivers/edac/i5000_edac.c
drivers/edac/i5100_edac.c
drivers/edac/i5400_edac.c
drivers/edac/i7300_edac.c
drivers/edac/i7core_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/i82875p_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/mpc85xx_edac.c
drivers/edac/mv64x60_edac.c
drivers/edac/octeon_edac-l2c.c
drivers/edac/octeon_edac-lmc.c
drivers/edac/octeon_edac-pc.c
drivers/edac/octeon_edac-pci.c
drivers/edac/pasemi_edac.c
drivers/edac/ppc4xx_edac.c
drivers/edac/r82600_edac.c
drivers/edac/sb_edac.c
drivers/edac/tile_edac.c
drivers/edac/x38_edac.c
drivers/firmware/dcdbas.c
drivers/firmware/dmi_scan.c
drivers/firmware/efivars.c
drivers/firmware/iscsi_ibft_find.c
drivers/gpio/gpio-da9055.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-ts5500.c
drivers/gpio/gpio-viperboard.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_ddc.c
drivers/gpu/drm/exynos/exynos_drm_buf.c
drivers/gpu/drm/exynos/exynos_drm_buf.h
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_connector.h
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/exynos/exynos_drm_dmabuf.h
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_encoder.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fb.h
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.h
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimc.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_gsc.h
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
drivers/gpu/drm/exynos/exynos_drm_iommu.c
drivers/gpu/drm/exynos/exynos_drm_iommu.h
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_ipp.h
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_rotator.h
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_drm_vidi.h
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_hdmi.h
drivers/gpu/drm/exynos/exynos_hdmiphy.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
drivers/gpu/drm/i915/i915_debugfs.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_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
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_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/nouveau/core/core/client.c
drivers/gpu/drm/nouveau/core/core/falcon.c
drivers/gpu/drm/nouveau/core/core/handle.c
drivers/gpu/drm/nouveau/core/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
drivers/gpu/drm/nouveau/core/include/core/client.h
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/include/subdev/bios.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
drivers/gpu/drm/nouveau/core/subdev/fb/base.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
drivers/gpu/drm/nouveau/core/subdev/vm/base.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_fence.h
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nouveau_prime.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv10_fence.c
drivers/gpu/drm/nouveau/nv50_fence.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/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_prime.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_semaphore.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/rv515
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/host1x.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/udl/udl_connector.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hsi/clients/hsi_char.c
drivers/hv/hv_balloon.c
drivers/hwmon/emc6w201.c
drivers/hwmon/lm73.c
drivers/hwmon/vexpress.c
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-highlander.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-intel-mid.c
drivers/i2c/busses/i2c-isch.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-nuc900.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-octeon.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-puv3.c
drivers/i2c/busses/i2c-pxa-pci.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-s6000.c
drivers/i2c/busses/i2c-sh7760.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-sirf.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-viperboard.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/busses/i2c-xlr.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/ide/aec62xx.c
drivers/ide/alim15x3.c
drivers/ide/amd74xx.c
drivers/ide/atiixp.c
drivers/ide/cmd64x.c
drivers/ide/cs5520.c
drivers/ide/cs5530.c
drivers/ide/cs5535.c
drivers/ide/cy82c693.c
drivers/ide/delkin_cb.c
drivers/ide/hpt366.c
drivers/ide/icside.c
drivers/ide/ide-pci-generic.c
drivers/ide/ide_platform.c
drivers/ide/it8172.c
drivers/ide/it8213.c
drivers/ide/it821x.c
drivers/ide/jmicron.c
drivers/ide/ns87415.c
drivers/ide/opti621.c
drivers/ide/palm_bk3710.c
drivers/ide/pdc202xx_new.c
drivers/ide/pdc202xx_old.c
drivers/ide/piix.c
drivers/ide/pmac.c
drivers/ide/rapide.c
drivers/ide/rz1000.c
drivers/ide/sc1200.c
drivers/ide/scc_pata.c
drivers/ide/serverworks.c
drivers/ide/sgiioc4.c
drivers/ide/siimage.c
drivers/ide/sis5513.c
drivers/ide/sl82c105.c
drivers/ide/slc90e66.c
drivers/ide/tc86c001.c
drivers/ide/triflex.c
drivers/ide/trm290.c
drivers/ide/via82cxxx.c
drivers/idle/intel_idle.c
drivers/iio/accel/Kconfig
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/adc/ad7266.c
drivers/iio/adc/ad7298.c
drivers/iio/adc/ad7476.c
drivers/iio/adc/ad7791.c
drivers/iio/adc/ad7887.c
drivers/iio/adc/at91_adc.c
drivers/iio/adc/lp8788_adc.c
drivers/iio/adc/max1363.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/adc/viperboard_adc.c
drivers/iio/amplifiers/ad8366.c
drivers/iio/common/hid-sensors/Kconfig
drivers/iio/common/hid-sensors/Makefile
drivers/iio/dac/ad5064.c
drivers/iio/dac/ad5360.c
drivers/iio/dac/ad5380.c
drivers/iio/dac/ad5421.c
drivers/iio/dac/ad5446.c
drivers/iio/dac/ad5449.c
drivers/iio/dac/ad5504.c
drivers/iio/dac/ad5624r_spi.c
drivers/iio/dac/ad5686.c
drivers/iio/dac/ad5755.c
drivers/iio/dac/ad5764.c
drivers/iio/dac/ad5791.c
drivers/iio/dac/max517.c
drivers/iio/dac/mcp4725.c
drivers/iio/frequency/ad9523.c
drivers/iio/frequency/adf4350.c
drivers/iio/gyro/Kconfig
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/light/Kconfig
drivers/iio/light/adjd_s311.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/light/lm3533-als.c
drivers/iio/light/vcnl4000.c
drivers/iio/magnetometer/Kconfig
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/infiniband/hw/amso1100/c2.c
drivers/infiniband/hw/amso1100/c2.h
drivers/infiniband/hw/amso1100/c2_pd.c
drivers/infiniband/hw/amso1100/c2_qp.c
drivers/infiniband/hw/amso1100/c2_rnic.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/qib/qib_init.c
drivers/infiniband/hw/qib/qib_qp.c
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/input/input.c
drivers/input/joystick/analog.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys_polled.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/tca8418_keypad.c
drivers/input/mouse/sentelic.c
drivers/input/tablet/wacom_sys.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/dmar.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/irq_remapping.c
drivers/iommu/irq_remapping.h
drivers/iommu/omap-iommu.c
drivers/iommu/tegra-gart.c
drivers/iommu/tegra-smmu.c
drivers/isdn/gigaset/capi.c
drivers/isdn/hardware/avm/b1pci.c
drivers/isdn/hardware/avm/c4.c
drivers/isdn/hardware/avm/t1pci.c
drivers/isdn/hardware/eicon/divasmain.c
drivers/isdn/hardware/mISDN/avmfritz.c
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/mISDNinfineon.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hardware/mISDN/speedfax.c
drivers/isdn/hardware/mISDN/w6692.c
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/asuscom.c
drivers/isdn/hisax/avm_a1.c
drivers/isdn/hisax/avm_a1p.c
drivers/isdn/hisax/avm_pci.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/bkm_a4t.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/enternow_pci.c
drivers/isdn/hisax/gazel.c
drivers/isdn/hisax/hfc4s8s_l1.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/hisax/hfcscard.c
drivers/isdn/hisax/hisax_fcpcipnp.c
drivers/isdn/hisax/icc.c
drivers/isdn/hisax/isac.c
drivers/isdn/hisax/isurf.c
drivers/isdn/hisax/ix1_micro.c
drivers/isdn/hisax/mic.c
drivers/isdn/hisax/niccy.c
drivers/isdn/hisax/nj_s.c
drivers/isdn/hisax/nj_u.c
drivers/isdn/hisax/s0box.c
drivers/isdn/hisax/saphir.c
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/sportster.c
drivers/isdn/hisax/teleint.c
drivers/isdn/hisax/teles0.c
drivers/isdn/hisax/teles3.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/hisax/telespci.c
drivers/isdn/hisax/w6692.c
drivers/isdn/hysdn/hysdn_init.c
drivers/isdn/mISDN/core.c
drivers/isdn/mISDN/stack.c
drivers/leds/leds-gpio.c
drivers/macintosh/macio_asic.c
drivers/macintosh/mediabay.c
drivers/macintosh/rack-meter.c
drivers/macintosh/windfarm_ad7417_sensor.c
drivers/macintosh/windfarm_fcu_controls.c
drivers/macintosh/windfarm_pm112.c
drivers/macintosh/windfarm_pm121.c
drivers/macintosh/windfarm_pm72.c
drivers/macintosh/windfarm_pm81.c
drivers/macintosh/windfarm_pm91.c
drivers/macintosh/windfarm_rm31.c
drivers/md/dm-bio-prison.c
drivers/md/dm-bio-prison.h
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-flakey.c
drivers/md/dm-io.c
drivers/md/dm-ioctl.c
drivers/md/dm-kcopyd.c
drivers/md/dm-linear.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm-target.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/dm-zero.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree-spine.c
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-common.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/i2c/adv7180.c
drivers/media/i2c/adv7183.c
drivers/media/i2c/as3645a.c
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/i2c/vs6624.c
drivers/media/mmc/siano/smssdio.c
drivers/media/pci/bt8xx/bt878.c
drivers/media/pci/bt8xx/bttv-cards.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/bt8xx/bttv-i2c.c
drivers/media/pci/bt8xx/bttv-input.c
drivers/media/pci/bt8xx/dvb-bt8xx.c
drivers/media/pci/cx18/cx18-driver.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx25821/cx25821-core.c
drivers/media/pci/cx88/cx88-alsa.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/ddbridge/ddbridge-core.c
drivers/media/pci/dm1105/dm1105.c
drivers/media/pci/ivtv/ivtv-driver.c
drivers/media/pci/mantis/hopper_cards.c
drivers/media/pci/mantis/mantis_cards.c
drivers/media/pci/mantis/mantis_dvb.c
drivers/media/pci/mantis/mantis_i2c.c
drivers/media/pci/mantis/mantis_pci.c
drivers/media/pci/meye/meye.c
drivers/media/pci/ngene/ngene-cards.c
drivers/media/pci/ngene/ngene-core.c
drivers/media/pci/ngene/ngene.h
drivers/media/pci/pluto2/pluto2.c
drivers/media/pci/pt1/pt1.c
drivers/media/pci/saa7134/saa7134-core.c
drivers/media/pci/saa7134/saa7134.h
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/pci/ttpci/av7110.c
drivers/media/pci/ttpci/av7110_ir.c
drivers/media/pci/zoran/zoran_card.c
drivers/media/pci/zoran/zoran_driver.c
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/coda.c
drivers/media/platform/davinci/dm355_ccdc.c
drivers/media/platform/davinci/dm644x_ccdc.c
drivers/media/platform/davinci/isif.c
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpfe_capture.c
drivers/media/platform/davinci/vpif.c
drivers/media/platform/davinci/vpss.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/omap24xxcam.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s3c-camif/camif-core.c
drivers/media/platform/s5p-fimc/fimc-core.c
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-fimc/mipi-csis.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-tv/hdmi_drv.c
drivers/media/platform/s5p-tv/hdmiphy_drv.c
drivers/media/platform/s5p-tv/mixer.h
drivers/media/platform/s5p-tv/mixer_drv.c
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/s5p-tv/sdo_drv.c
drivers/media/platform/s5p-tv/sii9234_drv.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/atmel-isi.c
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/platform/soc_camera/pxa_camera.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/platform/soc_camera/sh_mobile_csi2.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/platform/timblogiw.c
drivers/media/platform/via-camera.c
drivers/media/radio/radio-keene.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/saa7706h.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/tef6862.c
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/media/rc/ene_ir.c
drivers/media/rc/fintek-cir.c
drivers/media/rc/gpio-ir-recv.c
drivers/media/rc/iguanair.c
drivers/media/rc/imon.c
drivers/media/rc/ir-rx51.c
drivers/media/rc/ite-cir.c
drivers/media/rc/mceusb.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/redrat3.c
drivers/media/rc/streamzap.c
drivers/media/rc/ttusbir.c
drivers/media/rc/winbond-cir.c
drivers/media/usb/gspca/kinect.c
drivers/media/usb/gspca/sonixb.c
drivers/media/usb/gspca/sonixj.c
drivers/media/usb/gspca/spca506.c
drivers/media/usb/siano/smsusb.c
drivers/media/usb/usbvision/usbvision-video.c
drivers/media/usb/uvc/uvc_ctrl.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/memory/tegra20-mc.c
drivers/memory/tegra30-mc.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptspi.c
drivers/message/i2o/pci.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/arizona-core.c
drivers/mfd/arizona-irq.c
drivers/mfd/da9052-i2c.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/max77686.c
drivers/mfd/max77693.c
drivers/mfd/max8997.c
drivers/mfd/pcf50633-core.c
drivers/mfd/retu-mfd.c
drivers/mfd/rtl8411.c
drivers/mfd/rts5209.c
drivers/mfd/rts5229.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/sta2x11-mfd.c
drivers/mfd/stmpe.c
drivers/mfd/tc3589x.c
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/tps80031.c
drivers/mfd/twl4030-power.c
drivers/mfd/twl6040.c
drivers/mfd/vexpress-config.c
drivers/mfd/vexpress-sysreg.c
drivers/mfd/wm5102-tables.c
drivers/misc/atmel-ssc.c
drivers/misc/mei/amthif.c
drivers/misc/mei/wd.c
drivers/misc/sgi-xp/xpc_main.c
drivers/misc/ti-st/st_kim.c
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/mvsdio.c
drivers/mmc/host/rtsx_pci_sdmmc.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/wmt-sdmmc.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/spear_smi.c
drivers/mtd/maps/esb2rom.c
drivers/mtd/maps/intel_vr_nor.c
drivers/mtd/maps/pci.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/maps/pismo.c
drivers/mtd/maps/scb2_flash.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/bcm47xxnflash/main.c
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/nand_base.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/c_can/c_can.c
drivers/net/can/pch_can.c
drivers/net/can/ti_hecc.c
drivers/net/ethernet/3com/3c574_cs.c
drivers/net/ethernet/adi/Kconfig
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/calxeda/xgmac.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/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/ixgbe/Makefile
drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/fw.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/ti/cpts.c
drivers/net/ethernet/ti/cpts.h
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/xilinx/Kconfig
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c
drivers/net/loopback.c
drivers/net/macvlan.c
drivers/net/phy/icplus.c
drivers/net/phy/marvell.c
drivers/net/tun.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/dm9601.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wireless/ath/Kconfig
drivers/net/wireless/ath/Makefile
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/htc_hst.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/wil6210/Kconfig [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/Makefile [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/cfg80211.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/dbg_hexdump.h [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/debugfs.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/interrupt.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/main.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/netdev.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/pcie_bus.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/txrx.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/txrx.h [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/wil6210.h [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/wmi.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/wmi.h [new file with mode: 0644]
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/main.h
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/debug.h
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rtlwifi/Kconfig
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
drivers/net/wireless/rtlwifi/rtl8192de/trx.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netfront.c
drivers/nfc/pn544/i2c.c
drivers/parisc/dino.c
drivers/parisc/lba_pci.c
drivers/parport/parport_gsc.c
drivers/parport/parport_pc.c
drivers/parport/parport_serial.c
drivers/parport/parport_sunbpp.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/iov.c
drivers/pci/msi.c
drivers/pci/pci-sysfs.c
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/core.c
drivers/pinctrl/mvebu/pinctrl-armada-370.c
drivers/pinctrl/mvebu/pinctrl-armada-xp.c
drivers/pinctrl/mvebu/pinctrl-dove.c
drivers/pinctrl/mvebu/pinctrl-kirkwood.c
drivers/pinctrl/mvebu/pinctrl-mvebu.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-bcm2835.c
drivers/pinctrl/pinctrl-exynos5440.c
drivers/pinctrl/pinctrl-imx.c
drivers/pinctrl/pinctrl-imx23.c
drivers/pinctrl/pinctrl-imx28.c
drivers/pinctrl/pinctrl-imx35.c
drivers/pinctrl/pinctrl-imx51.c
drivers/pinctrl/pinctrl-imx53.c
drivers/pinctrl/pinctrl-imx6q.c
drivers/pinctrl/pinctrl-mmp2.c
drivers/pinctrl/pinctrl-mxs.c
drivers/pinctrl/pinctrl-nomadik-db8500.c
drivers/pinctrl/pinctrl-nomadik-db8540.c
drivers/pinctrl/pinctrl-nomadik-stn8815.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-pxa168.c
drivers/pinctrl/pinctrl-pxa910.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-sirf.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra20.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/pinctrl-u300.c
drivers/pinctrl/pinctrl-xway.c
drivers/pinctrl/spear/pinctrl-plgpio.c
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/platform/x86/acer-wmi.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/amilo-rfkill.c
drivers/platform/x86/apple-gmux.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-tablet.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ibm_rtl.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/intel_pmic_gpio.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/samsung-q10.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/tc1100-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/xo1-rfkill.c
drivers/pnp/interface.c
drivers/pnp/manager.c
drivers/power/ab8500_bmdata.c
drivers/power/avs/smartreflex.c
drivers/power/olpc_battery.c
drivers/power/reset/gpio-poweroff.c
drivers/power/rx51_battery.c
drivers/pps/clients/pps-gpio.c
drivers/ps3/ps3-lpm.c
drivers/ps3/ps3-sys-manager.c
drivers/ps3/ps3av.c
drivers/regulator/anatop-regulator.c
drivers/regulator/core.c
drivers/regulator/da9055-regulator.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/max77686.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8973-regulator.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps80031-regulator.c
drivers/regulator/twl-regulator.c
drivers/remoteproc/omap_remoteproc.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/rtc-88pm80x.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-au1xxx.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-bq4802.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-da9052.c
drivers/rtc/rtc-da9055.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-dm355evm.c
drivers/rtc/rtc-ds1286.c
drivers/rtc/rtc-ds1302.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1390.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-ds3234.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-fm3130.c
drivers/rtc/rtc-imxdi.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-jz4740.c
drivers/rtc/rtc-lpc32xx.c
drivers/rtc/rtc-ls1x.c
drivers/rtc/rtc-m41t93.c
drivers/rtc/rtc-m41t94.c
drivers/rtc/rtc-m48t35.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6902.c
drivers/rtc/rtc-max8907.c
drivers/rtc/rtc-max8925.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-mv.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-nuc900.c
drivers/rtc/rtc-pcap.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pcf50633.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-pm8xxx.c
drivers/rtc/rtc-puv3.c
drivers/rtc/rtc-r9701.c
drivers/rtc/rtc-rc5t583.c
drivers/rtc/rtc-rs5c313.c
drivers/rtc/rtc-rs5c348.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-rx8581.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-stk17ta8.c
drivers/rtc/rtc-tegra.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-tile.c
drivers/rtc/rtc-tps6586x.c [new file with mode: 0644]
drivers/rtc/rtc-tps65910.c
drivers/rtc/rtc-twl.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-vt8500.c
drivers/rtc/rtc-wm831x.c
drivers/rtc/rtc-wm8350.c
drivers/rtc/systohc.c [new file with mode: 0644]
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/char/con3215.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp.c
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/vmur.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc_sch.c
drivers/s390/cio/cio.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/eadm_sch.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/ap_bus.c
drivers/s390/kvm/kvm_virtio.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/lcs.c
drivers/sbus/char/bbc_i2c.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/envctrl.c
drivers/sbus/char/flash.c
drivers/sbus/char/uctrl.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/BusLogic.c
drivers/scsi/NCR5380.c
drivers/scsi/NCR_D700.c
drivers/scsi/NCR_Q720.c
drivers/scsi/a100u2w.c
drivers/scsi/a2091.c
drivers/scsi/aacraid/linit.c
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aha1740.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/arxescsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/cumana_2.c
drivers/scsi/arm/eesox.c
drivers/scsi/arm/oak.c
drivers/scsi/arm/powertec.c
drivers/scsi/atp870u.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/bfa/bfad.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bvme6000_scsi.c
drivers/scsi/csiostor/csio_init.c
drivers/scsi/csiostor/t4fw_api_stor.h
drivers/scsi/dc395x.c
drivers/scsi/dmx3191d.c
drivers/scsi/fdomain.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/gvp11.c
drivers/scsi/hpsa.c
drivers/scsi/hptiop.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/initio.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/isci/init.c
drivers/scsi/jazz_esp.c
drivers/scsi/lasi700.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/mac_esp.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/mvme16x_scsi.c
drivers/scsi/mvsas/mv_64xx.c
drivers/scsi/mvsas/mv_94xx.c
drivers/scsi/mvsas/mv_chips.h
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/mvumi.c
drivers/scsi/nsp32.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pmcraid.c
drivers/scsi/ps3rom.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qlogicfas.c
drivers/scsi/qlogicpti.c
drivers/scsi/sgiwd93.c
drivers/scsi/sim710.c
drivers/scsi/sni_53c710.c
drivers/scsi/stex.c
drivers/scsi/sun3x_esp.c
drivers/scsi/sun_esp.c
drivers/scsi/sym53c416.c
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/scsi/tmscsim.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/virtio_scsi.c
drivers/scsi/vmw_pvscsi.c
drivers/scsi/zalon.c
drivers/scsi/zorro7xx.c
drivers/sh/clk/cpg.c
drivers/sh/pfc/gpio.c
drivers/sh/pfc/pinctrl.c
drivers/sn/ioc3.c
drivers/spi/spi.c
drivers/ssb/Kconfig
drivers/ssb/driver_gige.c
drivers/ssb/driver_gpio.c
drivers/ssb/driver_pcicore.c
drivers/ssb/main.c
drivers/ssb/pcihost_wrapper.c
drivers/ssb/ssb_private.h
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/comedi_test.c
drivers/staging/comedi/drivers/ni_pcimio.c
drivers/staging/csr/bh.c
drivers/staging/csr/unifi_sme.c
drivers/staging/fwserial/Kconfig
drivers/staging/fwserial/TODO
drivers/staging/fwserial/fwserial.c
drivers/staging/fwserial/fwserial.h
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/gyro/Kconfig
drivers/staging/iio/gyro/adis16080_core.c
drivers/staging/iio/trigger/Kconfig
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/ipu-v3/ipu-common.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/omapdrm/Kconfig
drivers/staging/omapdrm/Makefile
drivers/staging/omapdrm/TODO
drivers/staging/omapdrm/omap_connector.c
drivers/staging/omapdrm/omap_crtc.c
drivers/staging/omapdrm/omap_drv.c
drivers/staging/omapdrm/omap_drv.h
drivers/staging/omapdrm/omap_encoder.c
drivers/staging/omapdrm/omap_gem_dmabuf.c
drivers/staging/omapdrm/omap_irq.c [new file with mode: 0644]
drivers/staging/omapdrm/omap_plane.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
drivers/staging/rtl8192e/rtl8192e/rtl_core.c
drivers/staging/rtl8712/usb_intf.c
drivers/staging/sb105x/Kconfig
drivers/staging/sb105x/sb_pci_mp.c
drivers/staging/speakup/synth.c
drivers/staging/tidspbridge/core/_tiomap.h
drivers/staging/tidspbridge/core/dsp-clock.c
drivers/staging/tidspbridge/core/wdt.c
drivers/staging/vme/devices/vme_pio2_core.c
drivers/staging/vt6656/bssdb.h
drivers/staging/vt6656/int.h
drivers/staging/vt6656/iocmd.h
drivers/staging/vt6656/iowpa.h
drivers/staging/wlan-ng/cfg80211.c
drivers/staging/wlan-ng/prism2mgmt.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target_erl2.c
drivers/target/target_core_alua.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_pr.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_sess.c
drivers/thermal/exynos_thermal.c
drivers/tty/pty.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/sysrq.c
drivers/usb/Kconfig
drivers/usb/chipidea/host.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/debugfs.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/fsl_mxc_udc.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/gadget/mv_udc_core.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/gadget/u_serial.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mv.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-timer.c
drivers/usb/host/ehci.h
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/imx21-hcd.c
drivers/usb/host/ohci-tmio.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/usbtest.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_dsps.c
drivers/usb/otg/Kconfig
drivers/usb/otg/mv_otg.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/storage/usual-tables.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_rdwr.c
drivers/vfio/vfio.c
drivers/vhost/net.c
drivers/vhost/tcm_vhost.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/acornfb.c
drivers/video/arcfb.c
drivers/video/arkfb.c
drivers/video/asiliantfb.c
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/mach64_ct.c
drivers/video/aty/mach64_cursor.c
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_monitor.c
drivers/video/au1100fb.c
drivers/video/au1200fb.c
drivers/video/auo_k1900fb.c
drivers/video/auo_k1901fb.c
drivers/video/auo_k190x.c
drivers/video/bf537-lq035.c
drivers/video/bf54x-lq043fb.c
drivers/video/bfin-lq035q1-fb.c
drivers/video/bfin-t350mcqb-fb.c
drivers/video/bfin_adv7393fb.c
drivers/video/broadsheetfb.c
drivers/video/bw2.c
drivers/video/carminefb.c
drivers/video/cg14.c
drivers/video/cg3.c
drivers/video/cg6.c
drivers/video/chipsfb.c
drivers/video/cirrusfb.c
drivers/video/clps711xfb.c
drivers/video/cobalt_lcdfb.c
drivers/video/console/sticore.c
drivers/video/cyber2000fb.c
drivers/video/da8xx-fb.c
drivers/video/dnfb.c
drivers/video/efifb.c
drivers/video/ep93xx-fb.c
drivers/video/exynos/exynos_dp_core.c
drivers/video/exynos/exynos_mipi_dsi.c
drivers/video/ffb.c
drivers/video/fm2fb.c
drivers/video/fsl-diu-fb.c
drivers/video/gbefb.c
drivers/video/geode/gx1fb_core.c
drivers/video/geode/gxfb_core.c
drivers/video/geode/lxfb_core.c
drivers/video/grvga.c
drivers/video/gxt4500.c
drivers/video/hecubafb.c
drivers/video/hgafb.c
drivers/video/hitfb.c
drivers/video/hpfb.c
drivers/video/i740fb.c
drivers/video/i810/i810_main.c
drivers/video/i810/i810_main.h
drivers/video/igafb.c
drivers/video/imsttfb.c
drivers/video/imxfb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/jz4740_fb.c
drivers/video/kyro/fbdev.c
drivers/video/leo.c
drivers/video/mb862xx/mb862xxfbdrv.c
drivers/video/mbx/mbxdebugfs.c
drivers/video/mbx/mbxfb.c
drivers/video/metronomefb.c
drivers/video/msm/mddi.c
drivers/video/mxsfb.c
drivers/video/neofb.c
drivers/video/nuc900fb.c
drivers/video/nvidia/nvidia.c
drivers/video/omap/lcd_mipid.c
drivers/video/omap2/displays/panel-acx565akm.c
drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
drivers/video/omap2/displays/panel-n8x0.c
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/dss_features.c
drivers/video/p9100.c
drivers/video/platinumfb.c
drivers/video/pm2fb.c
drivers/video/pm3fb.c
drivers/video/pmag-ba-fb.c
drivers/video/pmagb-b-fb.c
drivers/video/ps3fb.c
drivers/video/pvr2fb.c
drivers/video/pxa168fb.c
drivers/video/pxa3xx-gcu.c
drivers/video/pxafb.c
drivers/video/q40fb.c
drivers/video/riva/fbdev.c
drivers/video/riva/rivafb-i2c.c
drivers/video/s1d13xxxfb.c
drivers/video/s3c-fb.c
drivers/video/s3c2410fb.c
drivers/video/s3fb.c
drivers/video/sa1100fb.c
drivers/video/savage/savagefb_driver.c
drivers/video/sgivwfb.c
drivers/video/sh7760fb.c
drivers/video/sh_mipi_dsi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_meram.c
drivers/video/sis/sis_main.c
drivers/video/sis/sis_main.h
drivers/video/skeletonfb.c
drivers/video/sm501fb.c
drivers/video/ssd1307fb.c
drivers/video/sstfb.c
drivers/video/sunxvr1000.c
drivers/video/sunxvr2500.c
drivers/video/sunxvr500.c
drivers/video/tcx.c
drivers/video/tdfxfb.c
drivers/video/tgafb.c
drivers/video/tmiofb.c
drivers/video/tridentfb.c
drivers/video/uvesafb.c
drivers/video/vermilion/vermilion.c
drivers/video/vfb.c
drivers/video/vga16fb.c
drivers/video/via/dvi.c
drivers/video/via/dvi.h
drivers/video/via/hw.c
drivers/video/via/hw.h
drivers/video/via/lcd.c
drivers/video/via/lcd.h
drivers/video/via/via-core.c
drivers/video/via/via-gpio.c
drivers/video/via/viafbdev.c
drivers/video/vt8500lcdfb.c
drivers/video/vt8623fb.c
drivers/video/w100fb.c
drivers/video/wm8505fb.c
drivers/video/wmt_ge_rops.c
drivers/video/xen-fbfront.c
drivers/video/xilinxfb.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/vlynq/vlynq.c
drivers/w1/masters/mxc_w1.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/ath79_wdt.c
drivers/watchdog/cpu5wdt.c
drivers/watchdog/da9052_wdt.c
drivers/watchdog/da9055_wdt.c [new file with mode: 0644]
drivers/watchdog/davinci_wdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/sp5100_tco.h
drivers/watchdog/sp805_wdt.c
drivers/watchdog/twl4030_wdt.c
drivers/xen/cpu_hotplug.c
drivers/xen/events.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/pcpu.c
drivers/xen/platform-pci.c
drivers/xen/privcmd.c
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xen-pciback/pciback.h
drivers/xen/xen-pciback/pciback_ops.c
drivers/zorro/zorro-driver.c
fs/Kconfig
fs/Makefile
fs/adfs/inode.c
fs/affs/file.c
fs/affs/inode.c
fs/bfs/file.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/btrfs/ctree.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_map.c
fs/btrfs/extent_map.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/buffer.c
fs/cachefiles/interface.c
fs/cachefiles/internal.h
fs/cachefiles/key.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/cachefiles/xattr.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/super.c
fs/cifs/cifs_debug.h
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/readdir.c
fs/cifs/smb1ops.c
fs/cifs/smb2ops.c
fs/cifs/transport.c
fs/dcache.c
fs/debugfs/inode.c
fs/dlm/user.c
fs/ecryptfs/crypto.c
fs/ecryptfs/kthread.c
fs/ecryptfs/mmap.c
fs/eventpoll.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext4/Kconfig
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/f2fs/Kconfig [new file with mode: 0644]
fs/f2fs/Makefile [new file with mode: 0644]
fs/f2fs/acl.c [new file with mode: 0644]
fs/f2fs/acl.h [new file with mode: 0644]
fs/f2fs/checkpoint.c [new file with mode: 0644]
fs/f2fs/data.c [new file with mode: 0644]
fs/f2fs/debug.c [new file with mode: 0644]
fs/f2fs/dir.c [new file with mode: 0644]
fs/f2fs/f2fs.h [new file with mode: 0644]
fs/f2fs/file.c [new file with mode: 0644]
fs/f2fs/gc.c [new file with mode: 0644]
fs/f2fs/gc.h [new file with mode: 0644]
fs/f2fs/hash.c [new file with mode: 0644]
fs/f2fs/inode.c [new file with mode: 0644]
fs/f2fs/namei.c [new file with mode: 0644]
fs/f2fs/node.c [new file with mode: 0644]
fs/f2fs/node.h [new file with mode: 0644]
fs/f2fs/recovery.c [new file with mode: 0644]
fs/f2fs/segment.c [new file with mode: 0644]
fs/f2fs/segment.h [new file with mode: 0644]
fs/f2fs/super.c [new file with mode: 0644]
fs/f2fs/xattr.c [new file with mode: 0644]
fs/f2fs/xattr.h [new file with mode: 0644]
fs/fat/dir.c
fs/fat/inode.c
fs/fat/misc.c
fs/fhandle.c
fs/file.c
fs/file_table.c
fs/fscache/cache.c
fs/fscache/cookie.c
fs/fscache/internal.h
fs/fscache/object-list.c
fs/fscache/object.c
fs/fscache/operation.c
fs/fscache/page.c
fs/fscache/stats.c
fs/fuse/Kconfig
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/gfs2/lock_dlm.c
fs/gfs2/rgrp.c
fs/hfs/inode.c
fs/hfsplus/bitmap.c
fs/hfsplus/btree.c
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hpfs/file.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/jbd/journal.c
fs/jbd2/transaction.c
fs/jfs/file.c
fs/jfs/inode.c
fs/libfs.c
fs/logfs/readwrite.c
fs/minix/file.c
fs/minix/inode.c
fs/namei.c
fs/namespace.c
fs/ncpfs/inode.c
fs/nfs/callback_proc.c
fs/nfs/dir.c
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/nfs/inode.c
fs/nfs/namespace.c
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pnfs.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/fault_inject.c
fs/nfsd/fault_inject.h [deleted file]
fs/nfsd/netns.h
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3acl.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfsfh.c
fs/nfsd/nfssvc.c
fs/nfsd/nfsxdr.c
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/nfsd/xdr4.h
fs/nilfs2/file.c
fs/nilfs2/inode.c
fs/nilfs2/ioctl.c
fs/nilfs2/nilfs.h
fs/nilfs2/recovery.c
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fdinfo.c
fs/notify/group.c
fs/notify/inode_mark.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/mark.c
fs/notify/notification.c
fs/notify/vfsmount_mark.c
fs/ntfs/file.c
fs/ntfs/inode.c
fs/ntfs/inode.h
fs/ocfs2/file.c
fs/omfs/file.c
fs/open.c
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/proc_sysctl.c
fs/proc/task_mmu.c
fs/pstore/ram.c
fs/pstore/ram_core.c
fs/read_write.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/reiserfs.h
fs/select.c
fs/seq_file.c
fs/splice.c
fs/stat.c
fs/statfs.c
fs/sysv/file.c
fs/sysv/itree.c
fs/udf/super.c
fs/ufs/inode.c
fs/utimes.c
fs/xattr.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_buf_item.h
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2_block.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_trans_buf.c
include/Kbuild
include/asm-generic/cputime.h
include/asm-generic/cputime_jiffies.h [new file with mode: 0644]
include/asm-generic/cputime_nsecs.h [new file with mode: 0644]
include/asm-generic/dma-mapping-broken.h
include/asm-generic/io.h
include/asm-generic/mmu.h
include/asm-generic/parport.h
include/asm-generic/pgtable.h
include/asm-generic/syscalls.h
include/asm-generic/tlb.h
include/drm/drm_mm.h
include/drm/exynos_drm.h
include/linux/Kbuild [deleted file]
include/linux/aer.h
include/linux/ata.h
include/linux/ata_platform.h
include/linux/audit.h
include/linux/backing-dev.h
include/linux/bcma/bcma_driver_gmac_cmn.h
include/linux/bcma/bcma_driver_pci.h
include/linux/binfmts.h
include/linux/ceph/libceph.h
include/linux/ceph/osdmap.h
include/linux/ceph/rados.h
include/linux/clockchips.h
include/linux/compaction.h
include/linux/compat.h
include/linux/context_tracking.h
include/linux/cpu_rmap.h
include/linux/cpuidle.h
include/linux/cred.h
include/linux/dcache.h
include/linux/device-mapper.h
include/linux/efi.h
include/linux/exportfs.h
include/linux/f2fs_fs.h [new file with mode: 0644]
include/linux/fs.h
include/linux/fscache-cache.h
include/linux/fscache.h
include/linux/fsnotify_backend.h
include/linux/ftrace.h
include/linux/ftrace_event.h
include/linux/hardirq.h
include/linux/hdlc/Kbuild [deleted file]
include/linux/hsi/Kbuild [deleted file]
include/linux/init.h
include/linux/init_task.h
include/linux/interrupt.h
include/linux/ipc_namespace.h
include/linux/irq.h
include/linux/irq_work.h
include/linux/jbd2.h
include/linux/kernel.h
include/linux/kernel_stat.h
include/linux/kprobes.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/llist.h
include/linux/lockdep.h
include/linux/memcontrol.h
include/linux/mempolicy.h
include/linux/mfd/abx500.h
include/linux/mfd/abx500/ab8500-bm.h
include/linux/mfd/da9052/da9052.h
include/linux/mfd/da9052/reg.h
include/linux/mfd/rtsx_common.h
include/linux/mfd/rtsx_pci.h
include/linux/mlx4/device.h
include/linux/mm.h
include/linux/mmu_notifier.h
include/linux/mmzone.h
include/linux/module.h
include/linux/msg.h
include/linux/namei.h
include/linux/netdevice.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/pid.h
include/linux/pid_namespace.h
include/linux/platform_data/imx-iram.h [new file with mode: 0644]
include/linux/printk.h
include/linux/profile.h
include/linux/pstore_ram.h
include/linux/ptrace.h
include/linux/raid/Kbuild [deleted file]
include/linux/rbtree_augmented.h
include/linux/rcupdate.h
include/linux/ring_buffer.h
include/linux/rtc.h
include/linux/rwsem.h
include/linux/sched.h
include/linux/sched/rt.h [new file with mode: 0644]
include/linux/sched/sysctl.h [new file with mode: 0644]
include/linux/security.h
include/linux/signal.h
include/linux/smpboot.h
include/linux/srcu.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcsock.h
include/linux/syscalls.h
include/linux/tick.h
include/linux/time.h
include/linux/tsacct_kern.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/Kbuild [deleted file]
include/linux/usb/hcd.h
include/linux/usb/usbnet.h
include/linux/vtime.h
include/linux/watchdog.h
include/net/ip.h
include/net/netfilter/nf_conntrack_core.h
include/net/netns/conntrack.h
include/net/netns/x_tables.h
include/net/sock.h
include/net/transp_v6.h
include/rdma/Kbuild [deleted file]
include/sound/Kbuild [deleted file]
include/sound/cs4271.h
include/sound/soc.h
include/target/target_core_base.h
include/trace/events/ext4.h
include/trace/events/ras.h [new file with mode: 0644]
include/trace/events/rcu.h
include/uapi/asm-generic/signal.h
include/uapi/drm/exynos_drm.h
include/uapi/drm/i915_drm.h
include/uapi/linux/audit.h
include/uapi/linux/auto_fs.h
include/uapi/linux/dm-ioctl.h
include/uapi/linux/magic.h
include/uapi/linux/msg.h
include/uapi/linux/pci_regs.h
include/uapi/linux/perf_event.h
include/uapi/linux/serial_core.h
include/uapi/linux/signal.h
include/uapi/linux/usb/ch9.h
init/Kconfig
init/do_mounts_initrd.c
init/init_task.c
init/main.c
ipc/compat.c
ipc/ipc_sysctl.c
ipc/msg.c
ipc/msgutil.c
ipc/util.c
ipc/util.h
kernel/acct.c
kernel/async.c
kernel/audit.c
kernel/audit_tree.c
kernel/audit_watch.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/compat.c
kernel/context_tracking.c
kernel/cpu.c
kernel/debug/kdb/kdb_main.c
kernel/delayacct.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/irq/spurious.c
kernel/irq_work.c
kernel/kcmp.c
kernel/kmod.c
kernel/kprobes.c
kernel/modsign_pubkey.c
kernel/module.c
kernel/mutex.c
kernel/pid.c
kernel/pid_namespace.c
kernel/posix-cpu-timers.c
kernel/posix-timers.c
kernel/printk.c
kernel/profile.c
kernel/ptrace.c
kernel/rcu.h
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rtmutex-debug.c
kernel/rtmutex-tester.c
kernel/rtmutex.c
kernel/rwsem.c
kernel/sched/core.c
kernel/sched/cpupri.c
kernel/sched/cputime.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/signal.c
kernel/smp.c
kernel/smpboot.c
kernel/softirq.c
kernel/srcu.c
kernel/stop_machine.c
kernel/sysctl.c
kernel/time.c
kernel/time/Kconfig
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timeconst.pl
kernel/timer.c
kernel/trace/Kconfig
kernel/trace/blktrace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_clock.c
kernel/trace/trace_events.c
kernel/trace/trace_functions.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_probe.h
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_selftest.c
kernel/trace/trace_syscalls.c
kernel/trace/trace_uprobe.c
kernel/tsacct.c
kernel/watchdog.c
lib/Kconfig.debug
lib/atomic64.c
lib/bug.c
lib/cpu_rmap.c
lib/digsig.c
lib/rbtree.c
mm/bootmem.c
mm/compaction.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_isolation.c
mm/shmem.c
mm/truncate.c
mm/vmscan.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/sco.c
net/bluetooth/smp.c
net/bridge/br_if.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/ceph/ceph_common.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/ceph/osdmap.c
net/core/datagram.c
net/core/dev.c
net/core/net-sysfs.c
net/core/pktgen.c
net/core/request_sock.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/ah4.c
net/ipv4/arp.c
net/ipv4/datagram.c
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/ip_gre.c
net/ipv4/ip_sockglue.c
net/ipv4/ipcomp.c
net/ipv4/ipconfig.c
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/ah6.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/icmp.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6mr.c
net/ipv6/ipv6_sockglue.c
net/ipv6/netfilter/ip6t_NPT.c
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/iucv/iucv.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip6.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac802154/wpan.c
net/netfilter/Kconfig
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nfnetlink_log.c
net/netfilter/x_tables.c
net/netfilter/xt_CT.c
net/netfilter/xt_hashlimit.c
net/netfilter/xt_recent.c
net/openvswitch/vport-netdev.c
net/packet/af_packet.c
net/rds/ib_cm.c
net/rds/ib_recv.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sctp/Kconfig
net/sctp/auth.c
net/sctp/endpointola.c
net/sctp/ipv6.c
net/sctp/outqueue.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/wireless/core.c
net/wireless/reg.c
net/wireless/scan.c
net/wireless/sysfs.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
samples/Kconfig
samples/Makefile
samples/rpmsg/rpmsg_client_sample.c
samples/seccomp/Makefile
samples/tracepoints/Makefile [deleted file]
samples/tracepoints/tp-samples-trace.h [deleted file]
samples/tracepoints/tracepoint-probe-sample.c [deleted file]
samples/tracepoints/tracepoint-probe-sample2.c [deleted file]
samples/tracepoints/tracepoint-sample.c [deleted file]
scripts/checkpatch.pl
scripts/coccinelle/misc/warn.cocci [new file with mode: 0644]
scripts/config
scripts/headers_install.pl
scripts/kernel-doc
scripts/pnmtologo.c
scripts/tags.sh
security/capability.c
security/device_cgroup.c
security/integrity/evm/evm_crypto.c
security/integrity/ima/ima.h
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/keys/process_keys.c
security/security.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/selinux/include/objsec.h
sound/arm/pxa2xx-ac97-lib.c
sound/oss/pas2_card.c
sound/pci/au88x0/au88x0_synth.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/rme9652/hdspm.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/lm49453.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sta529.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm.c
sound/soc/fsl/imx-pcm.h
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usbaudio.h
tools/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/event-utils.h
tools/lib/traceevent/parse-filter.c
tools/lib/traceevent/parse-utils.c
tools/lib/traceevent/trace-seq.c
tools/perf/Documentation/Makefile
tools/perf/Documentation/perf-annotate.txt
tools/perf/Documentation/perf-buildid-cache.txt
tools/perf/Documentation/perf-diff.txt
tools/perf/Documentation/perf-evlist.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-script-python.txt
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-test.txt
tools/perf/Documentation/perf-top.txt
tools/perf/MANIFEST
tools/perf/Makefile
tools/perf/arch/common.c
tools/perf/bench/bench.h
tools/perf/bench/numa.c [new file with mode: 0644]
tools/perf/builtin-annotate.c
tools/perf/builtin-bench.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/feature-tests.mak
tools/perf/config/utilities.mak
tools/perf/perf.c
tools/perf/perf.h
tools/perf/scripts/perl/bin/workqueue-stats-record [deleted file]
tools/perf/scripts/perl/bin/workqueue-stats-report [deleted file]
tools/perf/scripts/perl/rwtop.pl
tools/perf/scripts/perl/workqueue-stats.pl [deleted file]
tools/perf/tests/attr.c
tools/perf/tests/attr.py
tools/perf/tests/attr/base-record
tools/perf/tests/attr/test-record-group
tools/perf/tests/attr/test-record-group1
tools/perf/tests/builtin-test.c
tools/perf/tests/evsel-roundtrip-name.c
tools/perf/tests/hists_link.c [new file with mode: 0644]
tools/perf/tests/mmap-basic.c
tools/perf/tests/open-syscall-all-cpus.c
tools/perf/tests/open-syscall.c
tools/perf/tests/parse-events.c
tools/perf/tests/perf-record.c
tools/perf/tests/pmu.c
tools/perf/tests/python-use.c [new file with mode: 0644]
tools/perf/tests/tests.h
tools/perf/tests/util.c [deleted file]
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/ui/browser.c
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/annotate.c [new file with mode: 0644]
tools/perf/ui/gtk/browser.c
tools/perf/ui/gtk/gtk.h
tools/perf/ui/gtk/helpline.c
tools/perf/ui/gtk/hists.c [new file with mode: 0644]
tools/perf/ui/helpline.c
tools/perf/ui/helpline.h
tools/perf/ui/hist.c
tools/perf/ui/keysyms.h
tools/perf/ui/setup.c
tools/perf/ui/stdio/hist.c
tools/perf/ui/tui/helpline.c
tools/perf/ui/util.c
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/cpumap.c
tools/perf/util/cpumap.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/event.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/include/linux/bitops.h
tools/perf/util/intlist.c
tools/perf/util/intlist.h
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/pmu.y
tools/perf/util/probe-finder.c
tools/perf/util/python-ext-sources
tools/perf/util/python.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/string.c
tools/perf/util/strlist.c
tools/perf/util/strlist.h
tools/perf/util/symbol-elf.c
tools/perf/util/symbol-minimal.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/sysfs.c
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/top.c
tools/perf/util/top.h
tools/perf/util/util.c
tools/perf/util/util.h
tools/testing/selftests/ipc/Makefile [new file with mode: 0644]
tools/testing/selftests/ipc/msgque.c [new file with mode: 0644]
tools/vm/.gitignore [new file with mode: 0644]

diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
new file mode 100644 (file)
index 0000000..0adeb52
--- /dev/null
@@ -0,0 +1,62 @@
+What:          /sys/devices/cpu/events/
+               /sys/devices/cpu/events/branch-misses
+               /sys/devices/cpu/events/cache-references
+               /sys/devices/cpu/events/cache-misses
+               /sys/devices/cpu/events/stalled-cycles-frontend
+               /sys/devices/cpu/events/branch-instructions
+               /sys/devices/cpu/events/stalled-cycles-backend
+               /sys/devices/cpu/events/instructions
+               /sys/devices/cpu/events/cpu-cycles
+
+Date:          2013/01/08
+
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+
+Description:   Generic performance monitoring events
+
+               A collection of performance monitoring events that may be
+               supported by many/most CPUs. These events can be monitored
+               using the 'perf(1)' tool.
+
+               The contents of each file would look like:
+
+                       event=0xNNNN
+
+               where 'N' is a hex digit and the number '0xNNNN' shows the
+               "raw code" for the perf event identified by the file's
+               "basename".
+
+
+What:          /sys/devices/cpu/events/PM_LD_MISS_L1
+               /sys/devices/cpu/events/PM_LD_REF_L1
+               /sys/devices/cpu/events/PM_CYC
+               /sys/devices/cpu/events/PM_BRU_FIN
+               /sys/devices/cpu/events/PM_GCT_NOSLOT_CYC
+               /sys/devices/cpu/events/PM_BRU_MPRED
+               /sys/devices/cpu/events/PM_INST_CMPL
+               /sys/devices/cpu/events/PM_CMPLU_STALL
+
+Date:          2013/01/08
+
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+               Linux Powerpc mailing list <linuxppc-dev@ozlabs.org>
+
+Description:   POWER-systems specific performance monitoring events
+
+               A collection of performance monitoring events that may be
+               supported by the POWER CPU. These events can be monitored
+               using the 'perf(1)' tool.
+
+               These events may not be supported by other CPUs.
+
+               The contents of each file would look like:
+
+                       event=0xNNNN
+
+               where 'N' is a hex digit and the number '0xNNNN' shows the
+               "raw code" for the perf event identified by the file's
+               "basename".
+
+               Further, multiple terms like 'event=0xNNNN' can be specified
+               and separated with comma. All available terms are defined in
+               the /sys/bus/event_source/devices/<dev>/format file.
index 1cf2adf46b118cd4b2f7bc2449a1065d764a2bd6..cd9213ccf3dc263ba2e87ff2ecc660ef370c1f1a 100644 (file)
@@ -70,6 +70,10 @@ snap_*
 
        A directory per each snapshot
 
+parent
+
+       Information identifying the pool, image, and snapshot id for
+       the parent image in a layered rbd image (format 2 only).
 
 Entries under /sys/bus/rbd/devices/<dev-id>/snap_<snap-name>
 -------------------------------------------------------------
diff --git a/Documentation/ABI/testing/sysfs-devices-node b/Documentation/ABI/testing/sysfs-devices-node
deleted file mode 100644 (file)
index 453a210..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-What:          /sys/devices/system/node/nodeX/compact
-Date:          February 2010
-Contact:       Mel Gorman <mel@csn.ul.ie>
-Description:
-               When this file is written to, all memory within that node
-               will be compacted. When it completes, memory will be freed
-               into blocks which have as many contiguous pages as possible
index eacafe312cd26e4cad3bcdbcc9bb398d50546f66..7c6638bacedb9290a0fba78e10335b401a5706d7 100644 (file)
@@ -116,7 +116,7 @@ my_suspend              (struct pci_dev *               pci_dev,
        return 0; /* a negative value on error, 0 on success. */
 }
 
-static void __devexit
+static void
 my_remove               (struct pci_dev *               pci_dev)
 {
        my_device *my = pci_get_drvdata (pci_dev);
@@ -124,7 +124,7 @@ my_remove               (struct pci_dev *               pci_dev)
        /* Describe me. */
 }
 
-static int __devinit
+static int
 my_probe                (struct pci_dev *               pci_dev,
                         const struct pci_device_id *   pci_id)
 {
@@ -157,7 +157,7 @@ my_pci_driver = {
        .id_table = my_pci_device_ids,
 
        .probe    = my_probe,
-       .remove   = __devexit_p (my_remove),
+       .remove   = my_remove,
 
        /* Power management functions. */
        .suspend  = my_suspend,
index 53e6fca146d73919e9b7dbc4fd32631a18141795..a09178086c309fc4457104f2515884573d46af94 100644 (file)
@@ -127,15 +127,42 @@ on the number of vectors that can be allocated; pci_enable_msi_block()
 returns as soon as it finds any constraint that doesn't allow the
 call to succeed.
 
-4.2.3 pci_disable_msi
+4.2.3 pci_enable_msi_block_auto
+
+int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *count)
+
+This variation on pci_enable_msi() call allows a device driver to request
+the maximum possible number of MSIs.  The MSI specification only allows
+interrupts to be allocated in powers of two, up to a maximum of 2^5 (32).
+
+If this function returns a positive number, it indicates that it has
+succeeded and the returned value is the number of allocated interrupts. In
+this case, the function enables MSI on this device and updates dev->irq to
+be the lowest of the new interrupts assigned to it.  The other interrupts
+assigned to the device are in the range dev->irq to dev->irq + returned
+value - 1.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to request any more MSI interrupts for
+this device.
+
+If the device driver needs to know the number of interrupts the device
+supports it can pass the pointer count where that number is stored. The
+device driver must decide what action to take if pci_enable_msi_block_auto()
+succeeds, but returns a value less than the number of interrupts supported.
+If the device driver does not need to know the number of interrupts
+supported, it can set the pointer count to NULL.
+
+4.2.4 pci_disable_msi
 
 void pci_disable_msi(struct pci_dev *dev)
 
 This function should be used to undo the effect of pci_enable_msi() or
-pci_enable_msi_block().  Calling it restores dev->irq to the pin-based
-interrupt number and frees the previously allocated message signaled
-interrupt(s).  The interrupt may subsequently be assigned to another
-device, so drivers should not cache the value of dev->irq.
+pci_enable_msi_block() or pci_enable_msi_block_auto().  Calling it restores
+dev->irq to the pin-based interrupt number and frees the previously
+allocated message signaled interrupt(s).  The interrupt may subsequently be
+assigned to another device, so drivers should not cache the value of
+dev->irq.
 
 Before calling this function, a device driver must always call free_irq()
 on any interrupt for which it previously called request_irq().
index cfaca7e6989346246e3205c52a353ea960b50ce5..86551cc72e034fc48e63c54c6e662954ca857372 100644 (file)
@@ -76,7 +76,7 @@ To notify SR-IOV core of Virtual Function Migration:
 
 Following piece of code illustrates the usage of the SR-IOV API.
 
-static int __devinit dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        pci_enable_sriov(dev, NR_VIRTFN);
 
@@ -85,7 +85,7 @@ static int __devinit dev_probe(struct pci_dev *dev, const struct pci_device_id *
        return 0;
 }
 
-static void __devexit dev_remove(struct pci_dev *dev)
+static void dev_remove(struct pci_dev *dev)
 {
        pci_disable_sriov(dev);
 
@@ -131,7 +131,7 @@ static struct pci_driver dev_driver = {
        .name =         "SR-IOV Physical Function driver",
        .id_table =     dev_id_table,
        .probe =        dev_probe,
-       .remove =       __devexit_p(dev_remove),
+       .remove =       dev_remove,
        .suspend =      dev_suspend,
        .resume =       dev_resume,
        .shutdown =     dev_shutdown,
index aa09e5476bba2c1a6ff53223312bc8d11ed23aea..bccf602a87f5c2054b146c826725ac183863a8ad 100644 (file)
@@ -183,12 +183,6 @@ Please mark the initialization and cleanup functions where appropriate
                        initializes.
        __exit          Exit code. Ignored for non-modular drivers.
 
-
-       __devinit       Device initialization code.
-                       Identical to __init if the kernel is not compiled
-                       with CONFIG_HOTPLUG, normal function otherwise.
-       __devexit       The same for __exit.
-
 Tips on when/where to use the above attributes:
        o The module_init()/module_exit() functions (and all
          initialization functions called _only_ from these)
@@ -196,20 +190,6 @@ Tips on when/where to use the above attributes:
 
        o Do not mark the struct pci_driver.
 
-       o The ID table array should be marked __devinitconst; this is done
-         automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
-
-       o The probe() and remove() functions should be marked __devinit
-         and __devexit respectively.  All initialization functions
-         exclusively called by the probe() routine, can be marked __devinit.
-         Ditto for remove() and __devexit.
-
-       o If mydriver_remove() is marked with __devexit(), then all address
-         references to mydriver_remove must use __devexit_p(mydriver_remove)
-         (in the struct pci_driver declaration for example).
-         __devexit_p() will generate the function name _or_ NULL if the
-         function will be discarded.  For an example, see drivers/net/tg3.c.
-
        o Do NOT mark a function if you are not sure which mark to use.
          Better to not mark the function than mark the function wrong.
 
index 4f27785ca0c87f8cf0ab4c28c9566595b032ed64..54469bc81b1cbac644e482bd09ebb6c28b77db43 100644 (file)
@@ -185,7 +185,7 @@ input driver:
                        .acpi_match_table  ACPI_PTR(mpu3050_acpi_match),
                },
                .probe          = mpu3050_probe,
-               .remove         = __devexit_p(mpu3050_remove),
+               .remove         = mpu3050_remove,
                .id_table       = mpu3050_ids,
        };
 
index 27f2b21a9d5cd5e040da0ab0e9cb9abbb69296a6..d9ca5be9b471d18d7c2640625d4845f9da8ff23a 100644 (file)
@@ -253,6 +253,8 @@ This performs an atomic exchange operation on the atomic variable v, setting
 the given new value.  It returns the old value that the atomic variable v had
 just before the operation.
 
+atomic_xchg requires explicit memory barriers around the operation.
+
        int atomic_cmpxchg(atomic_t *v, int old, int new);
 
 This performs an atomic compare exchange operation on the atomic value v,
index 728c38c242d631b88117958360c6f8441a72be4b..56fb62b09fc59ad757fc81de6ad6e478b3b0184b 100644 (file)
@@ -141,3 +141,4 @@ Version History
 1.2.0  Handle creation of arrays that contain failed devices.
 1.3.0  Added support for RAID 10
 1.3.1  Allow device replacement/rebuild for RAID 10
+1.3.2   Fix/improve redundancy checking for RAID10
index baadbb11fe98c226a269bd374edf43ae6f9de828..5083c0b834b25094fe7d5159cc51238cc37ef921 100644 (file)
@@ -60,11 +60,6 @@ clks: clkctrl@80040000 {
        compatible = "fsl,imx23-clkctrl";
        reg = <0x80040000 0x2000>;
        #clock-cells = <1>;
-       clock-output-names =
-               ...
-               "uart",         /* 32 */
-               ...
-               "end_of_list";
 };
 
 auart0: serial@8006c000 {
index c2a3525ecb4e59e0b781b95e42d173a1a1e29c2d..db4f2f05c4d0f15b32f354a7629e7a0c5a0556b4 100644 (file)
@@ -146,10 +146,6 @@ clks: ccm@53f80000 {
        compatible = "fsl,imx25-ccm";
        reg = <0x53f80000 0x4000>;
        interrupts = <31>;
-       clock-output-names = ...
-                       "uart_ipg",
-                       "uart_serial",
-                       ...;
 };
 
 uart1: serial@43f90000 {
index 52a49a4a50b33e0add4586516b880685da728cb3..e6587af62ff0fe6e740ee8bdeb3f4b32d851c5de 100644 (file)
@@ -83,11 +83,6 @@ clks: clkctrl@80040000 {
        compatible = "fsl,imx28-clkctrl";
        reg = <0x80040000 0x2000>;
        #clock-cells = <1>;
-       clock-output-names =
-               ...
-               "uart",         /* 45 */
-               ...
-               "end_of_list";
 };
 
 auart0: serial@8006a000 {
index d77b4e68dc42b306f22a472c5216623be0ed9a3d..f73fdf595568e30d9e79f0c0ee60d2799b8a5c0d 100644 (file)
@@ -211,10 +211,6 @@ clks: ccm@020c4000 {
        reg = <0x020c4000 0x4000>;
        interrupts = <0 87 0x04 0 88 0x04>;
        #clock-cells = <1>;
-       clock-output-names = ...
-                            "uart_ipg",
-                            "uart_serial",
-                            ...;
 };
 
 uart1: serial@02020000 {
index 558cdf3c9abc8e10539c894a4387fc72c1b32ff3..d4eab9227ea4451bb0eefbd511c22288d5fe336b 100644 (file)
@@ -1,4 +1,19 @@
-GPIO line that should be set high/low to power off a device
+Driver a GPIO line that can be used to turn the power off.
+
+The driver supports both level triggered and edge triggered power off.
+At driver load time, the driver will request the given gpio line and
+install a pm_power_off handler. If the optional properties 'input' is
+not found, the GPIO line will be driven in the inactive
+state. Otherwise its configured as an input.
+
+When the pm_power_off is called, the gpio is configured as an output,
+and drive active, so triggering a level triggered power off
+condition. This will also cause an inactive->active edge condition, so
+triggering positive edge triggered power off. After a delay of 100ms,
+the GPIO is set to inactive, thus causing an active->inactive edge,
+triggering negative edge triggered power off. After another 100ms
+delay the GPIO is driver active again. If the power is still on and
+the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
 
 Required properties:
 - compatible : should be "gpio-poweroff".
@@ -13,10 +28,9 @@ Optional properties:
   property is not specified, the GPIO is initialized as an output in its
   inactive state.
 
-
 Examples:
 
 gpio-poweroff {
        compatible = "gpio-poweroff";
-       gpios = <&gpio 4 0>; /* GPIO 4 Active Low */
+       gpios = <&gpio 4 0>;
 };
index 3a268127b0547e08f167635d2b14a4a04e9a3ac8..bc50899e0c81f8afcd7888f5200bcb7ef5dc32d2 100644 (file)
@@ -81,7 +81,8 @@ PA31  TXD4
 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.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
 
 Bits used for CONFIG:
 PULL_UP                (1 << 0): indicate this pin need a pull up.
@@ -126,7 +127,7 @@ pinctrl@fffff400 {
                pinctrl_dbgu: dbgu-0 {
                        atmel,pins =
                                <1 14 0x1 0x0   /* PB14 periph A */
-                                1 15 0x1 0x1>; /* PB15 periph with pullup */
+                                1 15 0x1 0x1>; /* PB15 periph with pullup */
                };
        };
 };
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sirf.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sirf.txt
new file mode 100644 (file)
index 0000000..c596a6a
--- /dev/null
@@ -0,0 +1,47 @@
+CSR SiRFprimaII pinmux controller
+
+Required properties:
+- compatible   : "sirf,prima2-pinctrl"
+- reg          : Address range of the pinctrl registers
+- interrupts    : Interrupts used by every GPIO group
+- gpio-controller : Indicates this device is a GPIO controller
+- interrupt-controller  : Marks the device node as an interrupt controller
+Optional properties:
+- sirf,pullups : if n-th bit of m-th bank is set, set a pullup on GPIO-n of bank m
+- sirf,pulldowns : if n-th bit of m-th bank is set, set a pulldown on GPIO-n of bank m
+
+Please refer to pinctrl-bindings.txt in this directory for details of the common
+pinctrl bindings used by client devices.
+
+SiRFprimaII's pinmux nodes act as a container for an abitrary number of subnodes.
+Each of these subnodes represents some desired configuration for a group of pins.
+
+Required subnode-properties:
+- sirf,pins : An array of strings. Each string contains the name of a group.
+- sirf,function: A string containing the name of the function to mux to the
+  group.
+
+  Valid values for group and function names can be found from looking at the
+  group and function arrays in driver files:
+  drivers/pinctrl/pinctrl-sirf.c
+
+For example, pinctrl might have subnodes like the following:
+ uart2_pins_a: uart2@0 {
+         uart {
+                 sirf,pins = "uart2grp";
+                 sirf,function = "uart2";
+         };
+ };
+ uart2_noflow_pins_a: uart2@1 {
+         uart {
+                 sirf,pins = "uart2_nostreamctrlgrp";
+                 sirf,function = "uart2_nostreamctrl";
+         };
+ };
+
+For a specific board, if it wants to use uart2 without hardware flow control,
+it can add the following to its board-specific .dts file.
+uart2: uart@0xb0070000 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_noflow_pins_a>;
+}
diff --git a/Documentation/devicetree/bindings/watchdog/davinci-wdt.txt b/Documentation/devicetree/bindings/watchdog/davinci-wdt.txt
new file mode 100644 (file)
index 0000000..75558cc
--- /dev/null
@@ -0,0 +1,12 @@
+DaVinci Watchdog Timer (WDT) Controller
+
+Required properties:
+- compatible : Should be "ti,davinci-wdt"
+- reg : Should contain WDT registers location and length
+
+Examples:
+
+wdt: wdt@2320000 {
+       compatible = "ti,davinci-wdt";
+       reg = <0x02320000 0x80>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt b/Documentation/devicetree/bindings/watchdog/twl4030-wdt.txt
new file mode 100644 (file)
index 0000000..80a3719
--- /dev/null
@@ -0,0 +1,10 @@
+Device tree bindings for twl4030-wdt driver (TWL4030 watchdog)
+
+Required properties:
+       compatible = "ti,twl4030-wdt";
+
+Example:
+
+watchdog {
+       compatible = "ti,twl4030-wdt";
+};
index 7b52ba7bf32aaf255c0bc7c584609834f6748c0b..8042050eb265b34cbb367e51df2805258667ae8d 100644 (file)
@@ -50,6 +50,8 @@ ext4.txt
        - info, mount options and specifications for the Ext4 filesystem.
 files.txt
        - info on file management in the Linux kernel.
+f2fs.txt
+       - info and mount options for the F2FS filesystem.
 fuse.txt
        - info on the Filesystem in User SpacE including mount options.
 gfs2.txt
index e540a24e5d069d4f6372adaabfa792ff11897ca9..f48e0c6b4c4295deeda9358cfe8f706b8feea2c0 100644 (file)
@@ -80,7 +80,6 @@ rename:               yes (all)       (see below)
 readlink:      no
 follow_link:   no
 put_link:      no
-truncate:      yes             (see below)
 setattr:       yes
 permission:    no (may not block if called in rcu-walk mode)
 get_acl:       no
@@ -96,11 +95,6 @@ atomic_open: yes
        Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
        cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
-       ->truncate() is never called directly - it's a callback, not a
-method. It's called by vmtruncate() - deprecated library function used by
-->setattr(). Locking information above applies to that call (i.e. is
-inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
-passed).
 
 See Documentation/filesystems/directory-locking for more detailed discussion
 of the locking scheme for directory operations.
index 382d52cdaf2da374061764865fa04db2c73fa072..d78bab9622c63d8ff1b21f9886523f1b90d57ee8 100644 (file)
@@ -308,6 +308,18 @@ performed on the denizens of the cache.  These are held in a structure of type:
      obtained by calling object->cookie->def->get_aux()/get_attr().
 
 
+ (*) Invalidate data object [mandatory]:
+
+       int (*invalidate_object)(struct fscache_operation *op)
+
+     This is called to invalidate a data object (as pointed to by op->object).
+     All the data stored for this object should be discarded and an
+     attr_changed operation should be performed.  The caller will follow up
+     with an object update operation.
+
+     fscache_op_complete() must be called on op before returning.
+
+
  (*) Discard object [mandatory]:
 
        void (*drop_object)(struct fscache_object *object)
@@ -419,7 +431,10 @@ performed on the denizens of the cache.  These are held in a structure of type:
 
      If an I/O error occurs, fscache_io_error() should be called and -ENOBUFS
      returned if possible or fscache_end_io() called with a suitable error
-     code..
+     code.
+
+     fscache_put_retrieval() should be called after a page or pages are dealt
+     with.  This will complete the operation when all pages are dealt with.
 
 
  (*) Request pages be read from cache [mandatory]:
@@ -526,6 +541,27 @@ FS-Cache provides some utilities that a cache backend may make use of:
      error value should be 0 if successful and an error otherwise.
 
 
+ (*) Record that one or more pages being retrieved or allocated have been dealt
+     with:
+
+       void fscache_retrieval_complete(struct fscache_retrieval *op,
+                                       int n_pages);
+
+     This is called to record the fact that one or more pages have been dealt
+     with and are no longer the concern of this operation.  When the number of
+     pages remaining in the operation reaches 0, the operation will be
+     completed.
+
+
+ (*) Record operation completion:
+
+       void fscache_op_complete(struct fscache_operation *op);
+
+     This is called to record the completion of an operation.  This deducts
+     this operation from the parent object's run state, potentially permitting
+     one or more pending operations to start running.
+
+
  (*) Set highest store limit:
 
        void fscache_set_store_limit(struct fscache_object *object,
index 7cc6bf2871ebfbae736436959a3d8a2e5153334d..97e6c0ecc5efc0ad763b1d2d3e376c38e057ae07 100644 (file)
@@ -35,8 +35,9 @@ This document contains the following sections:
        (12) Index and data file update
        (13) Miscellaneous cookie operations
        (14) Cookie unregistration
-       (15) Index and data file invalidation
-       (16) FS-Cache specific page flags.
+       (15) Index invalidation
+       (16) Data file invalidation
+       (17) FS-Cache specific page flags.
 
 
 =============================
@@ -767,13 +768,42 @@ the cookies for "child" indices, objects and pages have been relinquished
 first.
 
 
-================================
-INDEX AND DATA FILE INVALIDATION
-================================
+==================
+INDEX INVALIDATION
+==================
+
+There is no direct way to invalidate an index subtree.  To do this, the caller
+should relinquish and retire the cookie they have, and then acquire a new one.
+
+
+======================
+DATA FILE INVALIDATION
+======================
+
+Sometimes it will be necessary to invalidate an object that contains data.
+Typically this will be necessary when the server tells the netfs of a foreign
+change - at which point the netfs has to throw away all the state it had for an
+inode and reload from the server.
+
+To indicate that a cache object should be invalidated, the following function
+can be called:
+
+       void fscache_invalidate(struct fscache_cookie *cookie);
+
+This can be called with spinlocks held as it defers the work to a thread pool.
+All extant storage, retrieval and attribute change ops at this point are
+cancelled and discarded.  Some future operations will be rejected until the
+cache has had a chance to insert a barrier in the operations queue.  After
+that, operations will be queued again behind the invalidation operation.
+
+The invalidation operation will perform an attribute change operation and an
+auxiliary data update operation as it is very likely these will have changed.
+
+Using the following function, the netfs can wait for the invalidation operation
+to have reached a point at which it can start submitting ordinary operations
+once again:
 
-There is no direct way to invalidate an index subtree or a data file.  To do
-this, the caller should relinquish and retire the cookie they have, and then
-acquire a new one.
+       void fscache_wait_on_invalidate(struct fscache_cookie *cookie);
 
 
 ===========================
index 58313348da870ec0a0dda2c6190354593352f7fc..100ff41127e436ac8614c6c095a4e56dff2ccb62 100644 (file)
@@ -216,7 +216,14 @@ servicing netfs requests:
      The normal running state.  In this state, requests the netfs makes will be
      passed on to the cache.
 
- (6) State FSCACHE_OBJECT_UPDATING.
+ (6) State FSCACHE_OBJECT_INVALIDATING.
+
+     The object is undergoing invalidation.  When the state comes here, it
+     discards all pending read, write and attribute change operations as it is
+     going to clear out the cache entirely and reinitialise it.  It will then
+     continue to the FSCACHE_OBJECT_UPDATING state.
+
+ (7) State FSCACHE_OBJECT_UPDATING.
 
      The state machine comes here to update the object in the cache from the
      netfs's records.  This involves updating the auxiliary data that is used
@@ -225,13 +232,13 @@ servicing netfs requests:
 And there are terminal states in which an object cleans itself up, deallocates
 memory and potentially deletes stuff from disk:
 
- (7) State FSCACHE_OBJECT_LC_DYING.
+ (8) State FSCACHE_OBJECT_LC_DYING.
 
      The object comes here if it is dying because of a lookup or creation
      error.  This would be due to a disk error or system error of some sort.
      Temporary data is cleaned up, and the parent is released.
 
- (8) State FSCACHE_OBJECT_DYING.
+ (9) State FSCACHE_OBJECT_DYING.
 
      The object comes here if it is dying due to an error, because its parent
      cookie has been relinquished by the netfs or because the cache is being
@@ -241,27 +248,27 @@ memory and potentially deletes stuff from disk:
      can destroy themselves.  This object waits for all its children to go away
      before advancing to the next state.
 
- (9) State FSCACHE_OBJECT_ABORT_INIT.
+(10) State FSCACHE_OBJECT_ABORT_INIT.
 
      The object comes to this state if it was waiting on its parent in
      FSCACHE_OBJECT_INIT, but its parent died.  The object will destroy itself
      so that the parent may proceed from the FSCACHE_OBJECT_DYING state.
 
-(10) State FSCACHE_OBJECT_RELEASING.
-(11) State FSCACHE_OBJECT_RECYCLING.
+(11) State FSCACHE_OBJECT_RELEASING.
+(12) State FSCACHE_OBJECT_RECYCLING.
 
      The object comes to one of these two states when dying once it is rid of
      all its children, if it is dying because the netfs relinquished its
      cookie.  In the first state, the cached data is expected to persist, and
      in the second it will be deleted.
 
-(12) State FSCACHE_OBJECT_WITHDRAWING.
+(13) State FSCACHE_OBJECT_WITHDRAWING.
 
      The object transits to this state if the cache decides it wants to
      withdraw the object from service, perhaps to make space, but also due to
      error or just because the whole cache is being withdrawn.
 
-(13) State FSCACHE_OBJECT_DEAD.
+(14) State FSCACHE_OBJECT_DEAD.
 
      The object transits to this state when the in-memory object record is
      ready to be deleted.  The object processor shouldn't ever see an object in
index b6b070c57cbf5861d425451ccd3505ec9a86e5bf..bee2a5f93d6059da8621afc1854526b088242c5b 100644 (file)
@@ -174,7 +174,7 @@ Operations are used through the following procedure:
      necessary (the object might have died whilst the thread was waiting).
 
      When it has finished doing its processing, it should call
-     fscache_put_operation() on it.
+     fscache_op_complete() and fscache_put_operation() on it.
 
  (4) The operation holds an effective lock upon the object, preventing other
      exclusive ops conflicting until it is released.  The operation can be
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
new file mode 100644 (file)
index 0000000..dcf338e
--- /dev/null
@@ -0,0 +1,421 @@
+================================================================================
+WHAT IS Flash-Friendly File System (F2FS)?
+================================================================================
+
+NAND flash memory-based storage devices, such as SSD, eMMC, and SD cards, have
+been equipped on a variety systems ranging from mobile to server systems. Since
+they are known to have different characteristics from the conventional rotating
+disks, a file system, an upper layer to the storage device, should adapt to the
+changes from the sketch in the design level.
+
+F2FS is a file system exploiting NAND flash memory-based storage devices, which
+is based on Log-structured File System (LFS). The design has been focused on
+addressing the fundamental issues in LFS, which are snowball effect of wandering
+tree and high cleaning overhead.
+
+Since a NAND flash memory-based storage device shows different characteristic
+according to its internal geometry or flash memory management scheme, namely FTL,
+F2FS and its tools support various parameters not only for configuring on-disk
+layout, but also for selecting allocation and cleaning algorithms.
+
+The file system formatting tool, "mkfs.f2fs", is available from the following
+git tree:
+>> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
+
+For reporting bugs and sending patches, please use the following mailing list:
+>> linux-f2fs-devel@lists.sourceforge.net
+
+================================================================================
+BACKGROUND AND DESIGN ISSUES
+================================================================================
+
+Log-structured File System (LFS)
+--------------------------------
+"A log-structured file system writes all modifications to disk sequentially in
+a log-like structure, thereby speeding up  both file writing and crash recovery.
+The log is the only structure on disk; it contains indexing information so that
+files can be read back from the log efficiently. In order to maintain large free
+areas on disk for fast writing, we divide  the log into segments and use a
+segment cleaner to compress the live information from heavily fragmented
+segments." from Rosenblum, M. and Ousterhout, J. K., 1992, "The design and
+implementation of a log-structured file system", ACM Trans. Computer Systems
+10, 1, 26–52.
+
+Wandering Tree Problem
+----------------------
+In LFS, when a file data is updated and written to the end of log, its direct
+pointer block is updated due to the changed location. Then the indirect pointer
+block is also updated due to the direct pointer block update. In this manner,
+the upper index structures such as inode, inode map, and checkpoint block are
+also updated recursively. This problem is called as wandering tree problem [1],
+and in order to enhance the performance, it should eliminate or relax the update
+propagation as much as possible.
+
+[1] Bityutskiy, A. 2005. JFFS3 design issues. http://www.linux-mtd.infradead.org/
+
+Cleaning Overhead
+-----------------
+Since LFS is based on out-of-place writes, it produces so many obsolete blocks
+scattered across the whole storage. In order to serve new empty log space, it
+needs to reclaim these obsolete blocks seamlessly to users. This job is called
+as a cleaning process.
+
+The process consists of three operations as follows.
+1. A victim segment is selected through referencing segment usage table.
+2. It loads parent index structures of all the data in the victim identified by
+   segment summary blocks.
+3. It checks the cross-reference between the data and its parent index structure.
+4. It moves valid data selectively.
+
+This cleaning job may cause unexpected long delays, so the most important goal
+is to hide the latencies to users. And also definitely, it should reduce the
+amount of valid data to be moved, and move them quickly as well.
+
+================================================================================
+KEY FEATURES
+================================================================================
+
+Flash Awareness
+---------------
+- Enlarge the random write area for better performance, but provide the high
+  spatial locality
+- Align FS data structures to the operational units in FTL as best efforts
+
+Wandering Tree Problem
+----------------------
+- Use a term, “node”, that represents inodes as well as various pointer blocks
+- Introduce Node Address Table (NAT) containing the locations of all the “node”
+  blocks; this will cut off the update propagation.
+
+Cleaning Overhead
+-----------------
+- Support a background cleaning process
+- Support greedy and cost-benefit algorithms for victim selection policies
+- Support multi-head logs for static/dynamic hot and cold data separation
+- Introduce adaptive logging for efficient block allocation
+
+================================================================================
+MOUNT OPTIONS
+================================================================================
+
+background_gc_off      Turn off cleaning operations, namely garbage collection,
+                      triggered in background when I/O subsystem is idle.
+disable_roll_forward   Disable the roll-forward recovery routine
+discard                Issue discard/TRIM commands when a segment is cleaned.
+no_heap                Disable heap-style segment allocation which finds free
+                       segments for data from the beginning of main area, while
+                      for node from the end of main area.
+nouser_xattr           Disable Extended User Attributes. Note: xattr is enabled
+                       by default if CONFIG_F2FS_FS_XATTR is selected.
+noacl                  Disable POSIX Access Control List. Note: acl is enabled
+                       by default if CONFIG_F2FS_FS_POSIX_ACL is selected.
+active_logs=%u         Support configuring the number of active logs. In the
+                       current design, f2fs supports only 2, 4, and 6 logs.
+                       Default number is 6.
+disable_ext_identify   Disable the extension list configured by mkfs, so f2fs
+                       does not aware of cold files such as media files.
+
+================================================================================
+DEBUGFS ENTRIES
+================================================================================
+
+/sys/kernel/debug/f2fs/ contains information about all the partitions mounted as
+f2fs. Each file shows the whole f2fs information.
+
+/sys/kernel/debug/f2fs/status includes:
+ - major file system information managed by f2fs currently
+ - average SIT information about whole segments
+ - current memory footprint consumed by f2fs.
+
+================================================================================
+USAGE
+================================================================================
+
+1. Download userland tools and compile them.
+
+2. Skip, if f2fs was compiled statically inside kernel.
+   Otherwise, insert the f2fs.ko module.
+ # insmod f2fs.ko
+
+3. Create a directory trying to mount
+ # mkdir /mnt/f2fs
+
+4. Format the block device, and then mount as f2fs
+ # mkfs.f2fs -l label /dev/block_device
+ # mount -t f2fs /dev/block_device /mnt/f2fs
+
+Format options
+--------------
+-l [label]   : Give a volume label, up to 256 unicode name.
+-a [0 or 1]  : Split start location of each area for heap-based allocation.
+               1 is set by default, which performs this.
+-o [int]     : Set overprovision ratio in percent over volume size.
+               5 is set by default.
+-s [int]     : Set the number of segments per section.
+               1 is set by default.
+-z [int]     : Set the number of sections per zone.
+               1 is set by default.
+-e [str]     : Set basic extension list. e.g. "mp3,gif,mov"
+
+================================================================================
+DESIGN
+================================================================================
+
+On-disk Layout
+--------------
+
+F2FS divides the whole volume into a number of segments, each of which is fixed
+to 2MB in size. A section is composed of consecutive segments, and a zone
+consists of a set of sections. By default, section and zone sizes are set to one
+segment size identically, but users can easily modify the sizes by mkfs.
+
+F2FS splits the entire volume into six areas, and all the areas except superblock
+consists of multiple segments as described below.
+
+                                            align with the zone size <-|
+                 |-> align with the segment size
+     _________________________________________________________________________
+    |            |            |   Segment   |    Node     |   Segment  |      |
+    | Superblock | Checkpoint |    Info.    |   Address   |   Summary  | Main |
+    |    (SB)    |   (CP)     | Table (SIT) | Table (NAT) | Area (SSA) |      |
+    |____________|_____2______|______N______|______N______|______N_____|__N___|
+                                                                       .      .
+                                                             .                .
+                                                 .                            .
+                                    ._________________________________________.
+                                    |_Segment_|_..._|_Segment_|_..._|_Segment_|
+                                    .           .
+                                    ._________._________
+                                    |_section_|__...__|_
+                                    .            .
+                                   .________.
+                                   |__zone__|
+
+- Superblock (SB)
+ : It is located at the beginning of the partition, and there exist two copies
+   to avoid file system crash. It contains basic partition information and some
+   default parameters of f2fs.
+
+- Checkpoint (CP)
+ : It contains file system information, bitmaps for valid NAT/SIT sets, orphan
+   inode lists, and summary entries of current active segments.
+
+- Segment Information Table (SIT)
+ : It contains segment information such as valid block count and bitmap for the
+   validity of all the blocks.
+
+- Node Address Table (NAT)
+ : It is composed of a block address table for all the node blocks stored in
+   Main area.
+
+- Segment Summary Area (SSA)
+ : It contains summary entries which contains the owner information of all the
+   data and node blocks stored in Main area.
+
+- Main Area
+ : It contains file and directory data including their indices.
+
+In order to avoid misalignment between file system and flash-based storage, F2FS
+aligns the start block address of CP with the segment size. Also, it aligns the
+start block address of Main area with the zone size by reserving some segments
+in SSA area.
+
+Reference the following survey for additional technical details.
+https://wiki.linaro.org/WorkingGroups/Kernel/Projects/FlashCardSurvey
+
+File System Metadata Structure
+------------------------------
+
+F2FS adopts the checkpointing scheme to maintain file system consistency. At
+mount time, F2FS first tries to find the last valid checkpoint data by scanning
+CP area. In order to reduce the scanning time, F2FS uses only two copies of CP.
+One of them always indicates the last valid data, which is called as shadow copy
+mechanism. In addition to CP, NAT and SIT also adopt the shadow copy mechanism.
+
+For file system consistency, each CP points to which NAT and SIT copies are
+valid, as shown as below.
+
+  +--------+----------+---------+
+  |   CP   |    SIT   |   NAT   |
+  +--------+----------+---------+
+  .         .          .          .
+  .            .              .              .
+  .               .                 .                 .
+  +-------+-------+--------+--------+--------+--------+
+  | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 |
+  +-------+-------+--------+--------+--------+--------+
+     |             ^                          ^
+     |             |                          |
+     `----------------------------------------'
+
+Index Structure
+---------------
+
+The key data structure to manage the data locations is a "node". Similar to
+traditional file structures, F2FS has three types of node: inode, direct node,
+indirect node. F2FS assigns 4KB to an inode block which contains 923 data block
+indices, two direct node pointers, two indirect node pointers, and one double
+indirect node pointer as described below. One direct node block contains 1018
+data blocks, and one indirect node block contains also 1018 node blocks. Thus,
+one inode block (i.e., a file) covers:
+
+  4KB * (923 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
+
+   Inode block (4KB)
+     |- data (923)
+     |- direct node (2)
+     |          `- data (1018)
+     |- indirect node (2)
+     |            `- direct node (1018)
+     |                       `- data (1018)
+     `- double indirect node (1)
+                         `- indirect node (1018)
+                                     `- direct node (1018)
+                                                `- data (1018)
+
+Note that, all the node blocks are mapped by NAT which means the location of
+each node is translated by the NAT table. In the consideration of the wandering
+tree problem, F2FS is able to cut off the propagation of node updates caused by
+leaf data writes.
+
+Directory Structure
+-------------------
+
+A directory entry occupies 11 bytes, which consists of the following attributes.
+
+- hash         hash value of the file name
+- ino          inode number
+- len          the length of file name
+- type         file type such as directory, symlink, etc
+
+A dentry block consists of 214 dentry slots and file names. Therein a bitmap is
+used to represent whether each dentry is valid or not. A dentry block occupies
+4KB with the following composition.
+
+  Dentry Block(4 K) = bitmap (27 bytes) + reserved (3 bytes) +
+                     dentries(11 * 214 bytes) + file name (8 * 214 bytes)
+
+                         [Bucket]
+             +--------------------------------+
+             |dentry block 1 | dentry block 2 |
+             +--------------------------------+
+             .               .
+       .                             .
+  .       [Dentry Block Structure: 4KB]       .
+  +--------+----------+----------+------------+
+  | bitmap | reserved | dentries | file names |
+  +--------+----------+----------+------------+
+  [Dentry Block: 4KB] .   .
+                .               .
+            .                          .
+            +------+------+-----+------+
+            | hash | ino  | len | type |
+            +------+------+-----+------+
+            [Dentry Structure: 11 bytes]
+
+F2FS implements multi-level hash tables for directory structure. Each level has
+a hash table with dedicated number of hash buckets as shown below. Note that
+"A(2B)" means a bucket includes 2 data blocks.
+
+----------------------
+A : bucket
+B : block
+N : MAX_DIR_HASH_DEPTH
+----------------------
+
+level #0   | A(2B)
+           |
+level #1   | A(2B) - A(2B)
+           |
+level #2   | A(2B) - A(2B) - A(2B) - A(2B)
+     .     |   .       .       .       .
+level #N/2 | A(2B) - A(2B) - A(2B) - A(2B) - A(2B) - ... - A(2B)
+     .     |   .       .       .       .
+level #N   | A(4B) - A(4B) - A(4B) - A(4B) - A(4B) - ... - A(4B)
+
+The number of blocks and buckets are determined by,
+
+                            ,- 2, if n < MAX_DIR_HASH_DEPTH / 2,
+  # of blocks in level #n = |
+                            `- 4, Otherwise
+
+                             ,- 2^n, if n < MAX_DIR_HASH_DEPTH / 2,
+  # of buckets in level #n = |
+                             `- 2^((MAX_DIR_HASH_DEPTH / 2) - 1), Otherwise
+
+When F2FS finds a file name in a directory, at first a hash value of the file
+name is calculated. Then, F2FS scans the hash table in level #0 to find the
+dentry consisting of the file name and its inode number. If not found, F2FS
+scans the next hash table in level #1. In this way, F2FS scans hash tables in
+each levels incrementally from 1 to N. In each levels F2FS needs to scan only
+one bucket determined by the following equation, which shows O(log(# of files))
+complexity.
+
+  bucket number to scan in level #n = (hash value) % (# of buckets in level #n)
+
+In the case of file creation, F2FS finds empty consecutive slots that cover the
+file name. F2FS searches the empty slots in the hash tables of whole levels from
+1 to N in the same way as the lookup operation.
+
+The following figure shows an example of two cases holding children.
+       --------------> Dir <--------------
+       |                                 |
+    child                             child
+
+    child - child                     [hole] - child
+
+    child - child - child             [hole] - [hole] - child
+
+   Case 1:                           Case 2:
+   Number of children = 6,           Number of children = 3,
+   File size = 7                     File size = 7
+
+Default Block Allocation
+------------------------
+
+At runtime, F2FS manages six active logs inside "Main" area: Hot/Warm/Cold node
+and Hot/Warm/Cold data.
+
+- Hot node     contains direct node blocks of directories.
+- Warm node    contains direct node blocks except hot node blocks.
+- Cold node    contains indirect node blocks
+- Hot data     contains dentry blocks
+- Warm data    contains data blocks except hot and cold data blocks
+- Cold data    contains multimedia data or migrated data blocks
+
+LFS has two schemes for free space management: threaded log and copy-and-compac-
+tion. The copy-and-compaction scheme which is known as cleaning, is well-suited
+for devices showing very good sequential write performance, since free segments
+are served all the time for writing new data. However, it suffers from cleaning
+overhead under high utilization. Contrarily, the threaded log scheme suffers
+from random writes, but no cleaning process is needed. F2FS adopts a hybrid
+scheme where the copy-and-compaction scheme is adopted by default, but the
+policy is dynamically changed to the threaded log scheme according to the file
+system status.
+
+In order to align F2FS with underlying flash-based storage, F2FS allocates a
+segment in a unit of section. F2FS expects that the section size would be the
+same as the unit size of garbage collection in FTL. Furthermore, with respect
+to the mapping granularity in FTL, F2FS allocates each section of the active
+logs from different zones as much as possible, since FTL can write the data in
+the active logs into one allocation unit according to its mapping granularity.
+
+Cleaning process
+----------------
+
+F2FS does cleaning both on demand and in the background. On-demand cleaning is
+triggered when there are not enough free segments to serve VFS calls. Background
+cleaner is operated by a kernel thread, and triggers the cleaning job when the
+system is idle.
+
+F2FS supports two victim selection policies: greedy and cost-benefit algorithms.
+In the greedy algorithm, F2FS selects a victim segment having the smallest number
+of valid blocks. In the cost-benefit algorithm, F2FS selects a victim segment
+according to the segment age and the number of valid blocks in order to address
+log block thrashing problem in the greedy algorithm. F2FS adopts the greedy
+algorithm for on-demand cleaner, while background cleaner adopts cost-benefit
+algorithm.
+
+In order to identify whether the data in the victim segment are valid or not,
+F2FS manages a bitmap. Each bit represents the validity of a block, and the
+bitmap is composed of a bit stream covering whole blocks in main area.
index 092fad92a3f0e9bcc164b40595c19055e398d9ba..01c2db769791832b989b738d413cea2ecefcba68 100644 (file)
@@ -39,21 +39,10 @@ interoperability problems with future clients.  Known issues:
          from a linux client are possible, but we aren't really
          conformant with the spec (for example, we don't use kerberos
          on the backchannel correctly).
-       - Incomplete backchannel support: incomplete backchannel gss
-         support and no support for BACKCHANNEL_CTL mean that
-         callbacks (hence delegations and layouts) may not be
-         available and clients confused by the incomplete
-         implementation may fail.
        - We do not support SSV, which provides security for shared
          client-server state (thus preventing unauthorized tampering
          with locks and opens, for example).  It is mandatory for
          servers to support this, though no clients use it yet.
-       - Mandatory operations which we do not support, such as
-         DESTROY_CLIENTID, are not currently used by clients, but will be
-         (and the spec recommends their uses in common cases), and
-         clients should not be expected to know how to recover from the
-         case where they are not supported.  This will eventually cause
-         interoperability failures.
 
 In addition, some limitations are inherited from the current NFSv4
 implementation:
@@ -89,7 +78,7 @@ Operations
    |                      | MNI        | or OPT)      |                |
    +----------------------+------------+--------------+----------------+
    | ACCESS               | REQ        |              | Section 18.1   |
-NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
+ | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
 I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
    | CLOSE                | REQ        |              | Section 18.2   |
    | COMMIT               | REQ        |              | Section 18.3   |
@@ -99,7 +88,7 @@ NS*| DELEGPURGE           | OPT        | FDELG (REQ)  | Section 18.5   |
    | DELEGRETURN          | OPT        | FDELG,       | Section 18.6   |
    |                      |            | DDELG, pNFS  |                |
    |                      |            | (REQ)        |                |
-NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
+ | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
 I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
 I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
 I  | FREE_STATEID         | REQ        |              | Section 18.38  |
@@ -192,7 +181,6 @@ EXCHANGE_ID:
 
 CREATE_SESSION:
 * backchannel attributes are ignored
-* backchannel security parameters are ignored
 
 SEQUENCE:
 * no support for dynamic slot table renegotiation (optional)
@@ -202,7 +190,7 @@ Nonstandard compound limitations:
   ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
   fail to live up to the promise we made in CREATE_SESSION fore channel
   negotiation.
-* No more than one IO operation (read, write, readdir) allowed per
-  compound.
+* No more than one read-like operation allowed per compound; encoding
+  replies that cross page boundaries (except for read data) not handled.
 
 See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
index 0742feebc6e221f9d79e400adab5feaba23098de..0472c31c163b4de67d73a52d8aa1953597df8ca1 100644 (file)
@@ -281,7 +281,7 @@ ext2_write_failed and callers for an example.
 
 [mandatory]
 
-       ->truncate is going away.  The whole truncate sequence needs to be
+       ->truncate is gone.  The whole truncate sequence needs to be
 implemented in ->setattr, which is now mandatory for filesystems
 implementing on-disk size changes.  Start with a copy of the old inode_setattr
 and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to
index 2ee133e030c3f51521321afd62d5dd3b1d1650fb..e3869098163e1bdb347236e0dcede6bb2b8d80ca 100644 (file)
@@ -350,7 +350,6 @@ struct inode_operations {
        int (*readlink) (struct dentry *, char __user *,int);
         void * (*follow_link) (struct dentry *, struct nameidata *);
         void (*put_link) (struct dentry *, struct nameidata *, void *);
-       void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int);
        int (*get_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
@@ -431,16 +430,6 @@ otherwise noted.
        started might not be in the page cache at the end of the
        walk).
 
-  truncate: Deprecated. This will not be called if ->setsize is defined.
-       Called by the VFS to change the size of a file.  The
-       i_size field of the inode is set to the desired size by the
-       VFS before this method is called.  This method is called by
-       the truncate(2) system call and related functionality.
-
-       Note: ->truncate and vmtruncate are deprecated. Do not add new
-       instances/calls of these. Filesystems should be converted to do their
-       truncate sequence via ->setattr().
-
   permission: called by the VFS to check for access rights on a POSIX-like
        filesystem.
 
old mode 100755 (executable)
new mode 100644 (file)
index abf63615ee055393132b738a8a05b600e9aed750..22182660dda762816ad4663588f9e50cb7076622 100644 (file)
@@ -91,7 +91,7 @@ Example (from the nxp OHCI driver):
 
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
 
-static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
+static int usb_hcd_nxp_probe(struct platform_device *pdev)
 {
        (...)
        struct i2c_adapter *i2c_adap;
index ddd84d627185f4b83fcd27fff46054ad6f94ff69..6c723811c0a09f3ad5b2b18fa32ef12aa55cd82a 100644 (file)
@@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        possible to determine what the correct size should be.
                        This option provides an override for these situations.
 
-       capability.disable=
-                       [SECURITY] Disable capabilities.  This would normally
-                       be used only if an alternative security model is to be
-                       configured.  Potentially dangerous and should only be
-                       used if you are entirely sure of the consequences.
-
        ccw_timeout_log [S390]
                        See Documentation/s390/CommonIO for details.
 
@@ -2444,7 +2438,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        real-time workloads.  It can also improve energy
                        efficiency for asymmetric multiprocessors.
 
-       rcu_nocbs_poll  [KNL,BOOT]
+       rcu_nocb_poll   [KNL,BOOT]
                        Rather than requiring that offloaded CPUs
                        (specified by rcu_nocbs= above) explicitly
                        awaken the corresponding "rcuoN" kthreads,
index 3c4e1b3b80a1f8036a8b220ddcd0210d167c62b6..fa5d8a9ae2051184ddba6ce3d1dd769414d2e59f 100644 (file)
@@ -1685,6 +1685,7 @@ explicit lock operations, described later).  These include:
 
        xchg();
        cmpxchg();
+       atomic_xchg();
        atomic_cmpxchg();
        atomic_inc_return();
        atomic_dec_return();
index dd52d516cb8902da098bbb21a5006cea81b66a74..dbca6618208935505c00d193abccbe8e63962eee 100644 (file)
@@ -36,7 +36,7 @@ neigh/default/unres_qlen_bytes - INTEGER
        The maximum number of bytes which may be used by packets
        queued for each unresolved address by other network layers.
        (added in linux 3.3)
-       Seting negative value is meaningless and will retrun error.
+       Setting negative value is meaningless and will return error.
        Default: 65536 Bytes(64KB)
 
 neigh/default/unres_qlen - INTEGER
@@ -215,7 +215,7 @@ tcp_ecn - INTEGER
        Possible values are:
                0 Disable ECN.  Neither initiate nor accept ECN.
                1 Always request ECN on outgoing connection attempts.
-               2 Enable ECN when requested by incomming connections
+               2 Enable ECN when requested by incoming connections
                  but do not request ECN on outgoing connections.
        Default: 2
 
@@ -503,7 +503,7 @@ tcp_fastopen - INTEGER
 tcp_syn_retries - INTEGER
        Number of times initial SYNs for an active TCP connection attempt
        will be retransmitted. Should not be higher than 255. Default value
-       is 6, which corresponds to 63seconds till the last restransmission
+       is 6, which corresponds to 63seconds till the last retransmission
        with the current initial RTO of 1second. With this the final timeout
        for an active TCP connection attempt will happen after 127seconds.
 
@@ -1331,6 +1331,12 @@ force_tllao - BOOLEAN
        race condition where the sender deletes the cached link-layer address
        prior to receiving a response to a previous solicitation."
 
+ndisc_notify - BOOLEAN
+       Define mode for notification of address and device changes.
+       0 - (default): do nothing
+       1 - Generate unsolicited neighbour advertisements when device is brought
+           up or hardware address changes.
+
 icmp/*:
 ratelimit - INTEGER
        Limit the maximal rates for sending ICMPv6 packets.
@@ -1530,7 +1536,7 @@ cookie_hmac_alg - STRING
        * sha1
        * none
        Ability to assign md5 or sha1 as the selected alg is predicated on the
-       configuarion of those algorithms at build time (CONFIG_CRYPTO_MD5 and
+       configuration of those algorithms at build time (CONFIG_CRYPTO_MD5 and
        CONFIG_CRYPTO_SHA1).
 
        Default: Dependent on configuration.  MD5 if available, else SHA1 if
@@ -1548,7 +1554,7 @@ rcvbuf_policy - INTEGER
        blocking.
 
        1: rcvbuf space is per association
-       0: recbuf space is per socket
+       0: rcvbuf space is per socket
 
        Default: 0
 
index 4abe83e1045a4b38e85b05ebfeb3e8e62841a7f6..03591a750f99eea57fa63a5b610cf70793c716c6 100644 (file)
@@ -642,12 +642,13 @@ out the following operations:
   * During system suspend it calls pm_runtime_get_noresume() and
     pm_runtime_barrier() for every device right before executing the
     subsystem-level .suspend() callback for it.  In addition to that it calls
-    pm_runtime_disable() for every device right after executing the
-    subsystem-level .suspend() callback for it.
+    __pm_runtime_disable() with 'false' as the second argument for every device
+    right before executing the subsystem-level .suspend_late() callback for it.
 
   * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
-    for every device right before and right after executing the subsystem-level
-    .resume() callback for it, respectively.
+    for every device right after executing the subsystem-level .resume_early()
+    callback and right after executing the subsystem-level .resume() callback
+    for it, respectively.
 
 7. Generic subsystem callbacks
 
index 409d9f964c5b547b9e3f09d76c662aebf1216536..f7edc3aa1e92d4e2eac9ed143212f9757577f041 100644 (file)
@@ -236,7 +236,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
        return 0;
 }
 
-static void __devexit rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
 {
        dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
 }
@@ -253,7 +253,7 @@ static struct rpmsg_driver rpmsg_sample_client = {
        .id_table       = rpmsg_driver_sample_id_table,
        .probe          = rpmsg_sample_probe,
        .callback       = rpmsg_sample_cb,
-       .remove         = __devexit_p(rpmsg_sample_remove),
+       .remove         = rpmsg_sample_remove,
 };
 
 static int __init init(void)
index 7312ec14dd89802c7b3093a5bdfa65b63ece8f1b..2331eb2141466f9c5038cfa8c6f4157c570ff96a 100644 (file)
@@ -345,7 +345,7 @@ SPI protocol drivers somewhat resemble platform device drivers:
                },
 
                .probe          = CHIP_probe,
-               .remove         = __devexit_p(CHIP_remove),
+               .remove         = CHIP_remove,
                .suspend        = CHIP_suspend,
                .resume         = CHIP_resume,
        };
@@ -355,7 +355,7 @@ device whose board_info gave a modalias of "CHIP".  Your probe() code
 might look like this unless you're creating a device which is managing
 a bus (appearing under /sys/class/spi_master).
 
-       static int __devinit CHIP_probe(struct spi_device *spi)
+       static int CHIP_probe(struct spi_device *spi)
        {
                struct CHIP                     *chip;
                struct CHIP_platform_data       *pdata;
index 2907ba6c3607dfd557e3e4533413b0bea8518a60..ccd42589e124c0d7233bbba41bcf154e7ae7d87f 100644 (file)
@@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
 - modules_disabled
+- msg_next_id                [ sysv ipc ]
 - msgmax
 - msgmnb
 - msgmni
@@ -62,7 +63,9 @@ show up in /proc/sys/kernel:
 - rtsig-max
 - rtsig-nr
 - sem
+- sem_next_id                [ sysv ipc ]
 - sg-big-buff                 [ generic SCSI device (sg) ]
+- shm_next_id                [ sysv ipc ]
 - shm_rmid_forced
 - shmall
 - shmmax                      [ sysv ipc ]
@@ -320,6 +323,22 @@ to false.
 
 ==============================================================
 
+msg_next_id, sem_next_id, and shm_next_id:
+
+These three toggles allows to specify desired id for next allocated IPC
+object: message, semaphore or shared memory respectively.
+
+By default they are equal to -1, which means generic allocation logic.
+Possible values to set are in range {0..INT_MAX}.
+
+Notes:
+1) kernel doesn't guarantee, that new object will have desired id. So,
+it's up to userspace, how to handle an object with "wrong" id.
+2) Toggle with non-default value will be set back to -1 by kernel after
+successful IPC object allocation.
+
+==============================================================
+
 nmi_watchdog:
 
 Enables/Disables the NMI watchdog on x86 systems. When the value is
@@ -542,6 +561,19 @@ are doing anyway :)
 
 ==============================================================
 
+shmall:
+
+This parameter sets the total amount of shared memory pages that
+can be used system wide. Hence, SHMALL should always be at least
+ceil(shmmax/PAGE_SIZE).
+
+If you are not sure what the default PAGE_SIZE is on your Linux
+system, you can run the following command:
+
+# getconf PAGE_SIZE
+
+==============================================================
+
 shmmax:
 
 This value can be used to query and set the run time limit
index 6f51fed45f2d2f83ca6fcaaeb83dc1e5ee64fb6c..53d6a3c51d875771fc2966c9917aec13b17f53c6 100644 (file)
@@ -1842,6 +1842,89 @@ an error.
  # cat buffer_size_kb
 85
 
+Snapshot
+--------
+CONFIG_TRACER_SNAPSHOT makes a generic snapshot feature
+available to all non latency tracers. (Latency tracers which
+record max latency, such as "irqsoff" or "wakeup", can't use
+this feature, since those are already using the snapshot
+mechanism internally.)
+
+Snapshot preserves a current trace buffer at a particular point
+in time without stopping tracing. Ftrace swaps the current
+buffer with a spare buffer, and tracing continues in the new
+current (=previous spare) buffer.
+
+The following debugfs files in "tracing" are related to this
+feature:
+
+  snapshot:
+
+       This is used to take a snapshot and to read the output
+       of the snapshot. Echo 1 into this file to allocate a
+       spare buffer and to take a snapshot (swap), then read
+       the snapshot from this file in the same format as
+       "trace" (described above in the section "The File
+       System"). Both reads snapshot and tracing are executable
+       in parallel. When the spare buffer is allocated, echoing
+       0 frees it, and echoing else (positive) values clear the
+       snapshot contents.
+       More details are shown in the table below.
+
+       status\input  |     0      |     1      |    else    |
+       --------------+------------+------------+------------+
+       not allocated |(do nothing)| alloc+swap |   EINVAL   |
+       --------------+------------+------------+------------+
+       allocated     |    free    |    swap    |   clear    |
+       --------------+------------+------------+------------+
+
+Here is an example of using the snapshot feature.
+
+ # echo 1 > events/sched/enable
+ # echo 1 > snapshot
+ # cat snapshot
+# tracer: nop
+#
+# entries-in-buffer/entries-written: 71/71   #P:8
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+          <idle>-0     [005] d...  2440.603828: sched_switch: prev_comm=swapper/5 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=snapshot-test-2 next_pid=2242 next_prio=120
+           sleep-2242  [005] d...  2440.603846: sched_switch: prev_comm=snapshot-test-2 prev_pid=2242 prev_prio=120 prev_state=R ==> next_comm=kworker/5:1 next_pid=60 next_prio=120
+[...]
+          <idle>-0     [002] d...  2440.707230: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=snapshot-test-2 next_pid=2229 next_prio=120
+
+ # cat trace
+# tracer: nop
+#
+# entries-in-buffer/entries-written: 77/77   #P:8
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+          <idle>-0     [007] d...  2440.707395: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=snapshot-test-2 next_pid=2243 next_prio=120
+ snapshot-test-2-2229  [002] d...  2440.707438: sched_switch: prev_comm=snapshot-test-2 prev_pid=2229 prev_prio=120 prev_state=S ==> next_comm=swapper/2 next_pid=0 next_prio=120
+[...]
+
+
+If you try to use this snapshot feature when current tracer is
+one of the latency tracers, you will get the following results.
+
+ # echo wakeup > current_tracer
+ # echo 1 > snapshot
+bash: echo: write error: Device or resource busy
+ # cat snapshot
+cat: snapshot: Device or resource busy
+
 -----------
 
 More details can be found in the source code, in the
index 32bfe926e8d77717e67a9e485ca89b398f5c26a8..b89567ad04b7f587d527da4ebb44c365240c8082 100644 (file)
@@ -174,8 +174,7 @@ The recommended approach is as follows:
 
 static atomic_t drv_instance = ATOMIC_INIT(0);
 
-static int __devinit drv_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *pci_id)
+static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
        ...
        state->instance = atomic_inc_return(&drv_instance) - 1;
index 406d82d5d2bb1e08a8cb9e4c548ce937f448b376..b443f1de0e5af37987b4be6282d57e09e285d42e 100644 (file)
@@ -57,6 +57,10 @@ Protocol 2.10:       (Kernel 2.6.31) Added a protocol for relaxed alignment
 Protocol 2.11: (Kernel 3.6) Added a field for offset of EFI handover
                protocol entry point.
 
+Protocol 2.12: (Kernel 3.8) Added the xloadflags field and extension fields
+               to struct boot_params for for loading bzImage and ramdisk
+               above 4G in 64bit.
+
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -182,7 +186,7 @@ Offset      Proto   Name            Meaning
 0230/4 2.05+   kernel_alignment Physical addr alignment required for kernel
 0234/1 2.05+   relocatable_kernel Whether kernel is relocatable or not
 0235/1 2.10+   min_alignment   Minimum alignment, as a power of two
-0236/2 N/A     pad3            Unused
+0236/2 2.12+   xloadflags      Boot protocol option flags
 0238/4 2.06+   cmdline_size    Maximum size of the kernel command line
 023C/4 2.07+   hardware_subarch Hardware subarchitecture
 0240/8 2.07+   hardware_subarch_data Subarchitecture-specific data
@@ -386,6 +390,7 @@ Protocol:   2.00+
        F  Special              (0xFF = undefined)
        10  Reserved
        11  Minimal Linux Bootloader <http://sebastian-plotz.blogspot.de>
+       12  OVMF UEFI virtualization stack
 
   Please contact <hpa@zytor.com> if you need a bootloader ID
   value assigned.
@@ -582,6 +587,27 @@ Protocol:  2.10+
   misaligned kernel.  Therefore, a loader should typically try each
   power-of-two alignment from kernel_alignment down to this alignment.
 
+Field name:     xloadflags
+Type:           read
+Offset/size:    0x236/2
+Protocol:       2.12+
+
+  This field is a bitmask.
+
+  Bit 0 (read):        XLF_KERNEL_64
+       - If 1, this kernel has the legacy 64-bit entry point at 0x200.
+
+  Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G
+        - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G.
+
+  Bit 2 (read):        XLF_EFI_HANDOVER_32
+       - If 1, the kernel supports the 32-bit EFI handoff entry point
+          given at handover_offset.
+
+  Bit 3 (read): XLF_EFI_HANDOVER_64
+       - If 1, the kernel supports the 64-bit EFI handoff entry point
+          given at handover_offset + 0x200.
+
 Field name:    cmdline_size
 Type:          read
 Offset/size:   0x238/4
index cf5437deda81a003864f9e8a5f4e533d276a189d..199f453cb4de10016030c2dd230fb9a3a3125cee 100644 (file)
@@ -19,6 +19,9 @@ Offset        Proto   Name            Meaning
 090/010        ALL     hd1_info        hd1 disk parameter, OBSOLETE!!
 0A0/010        ALL     sys_desc_table  System description table (struct sys_desc_table)
 0B0/010        ALL     olpc_ofw_header OLPC's OpenFirmware CIF and friends
+0C0/004        ALL     ext_ramdisk_image ramdisk_image high 32bits
+0C4/004        ALL     ext_ramdisk_size  ramdisk_size high 32bits
+0C8/004        ALL     ext_cmd_line_ptr  cmd_line_ptr high 32bits
 140/080        ALL     edid_info       Video mode setup (struct edid_info)
 1C0/020        ALL     efi_info        EFI 32 information (struct efi_info)
 1E0/004        ALL     alk_mem_k       Alternative mem check, in KB
@@ -27,6 +30,7 @@ Offset        Proto   Name            Meaning
 1E9/001        ALL     eddbuf_entries  Number of entries in eddbuf (below)
 1EA/001        ALL     edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
                                (below)
+1EF/001        ALL     sentinel        Used to detect broken bootloaders
 290/040        ALL     edd_mbr_sig_buffer EDD MBR signatures
 2D0/A00        ALL     e820_map        E820 memory map table
                                (array of struct e820entry)
index 3e74f13af4266d8d7aab3b3910b93a73bc1b5b71..44c1d934c4e3d1e0aceb48b22d9328d1bd6f8410 100644 (file)
@@ -182,8 +182,7 @@ int iterate(void *p)
 
 static atomic_t drv_instance = ATOMIC_INIT(0);
 
-static int __devinit drv_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *pci_id)
+static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
        ...
        state->instance = atomic_inc_return(&drv_instance) - 1;
index 4e2a1f67a1fcf00b553e8190947368d240d74b44..168590fc0d5d9ee58cf1455c025171dbae7b2af0 100644 (file)
@@ -228,7 +228,7 @@ S:  Maintained
 F:     drivers/platform/x86/acerhdf.c
 
 ACER WMI LAPTOP EXTRAS
-M:     Joey Lee <jlee@novell.com>
+M:     "Lee, Chun-Yi" <jlee@suse.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/acer-wmi.c
@@ -449,6 +449,7 @@ T:  git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:     Maintained
 F:     drivers/char/agp/
 F:     include/linux/agp*
+F:     include/uapi/linux/agp*
 
 AHA152X SCSI DRIVER
 M:     "Juergen E. Fischer" <fischer@norbit.de>
@@ -589,6 +590,7 @@ M:  Jiri Kosina <jkosina@suse.cz>
 S:     Odd fixes
 F:     arch/x86/kernel/apm_32.c
 F:     include/linux/apm_bios.h
+F:     include/uapi/linux/apm_bios.h
 F:     drivers/char/apm-emulation.c
 
 APPLE BCM5974 MULTITOUCH DRIVER
@@ -646,7 +648,7 @@ F:  arch/arm/
 
 ARM SUB-ARCHITECTURES
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     MAINTAINED
+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
@@ -1005,7 +1007,6 @@ F:        drivers/mmc/host/msm_sdcc.c
 F:     drivers/mmc/host/msm_sdcc.h
 F:     drivers/tty/serial/msm_serial.h
 F:     drivers/tty/serial/msm_serial.c
-F:     drivers/platform/msm/
 F:     drivers/*/pm8???-*
 F:     include/linux/mfd/pm8xxx/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
@@ -1069,7 +1070,6 @@ M:        Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
-F:     arch/arm/common/time-acorn.c
 F:     arch/arm/include/asm/hardware/entry-macro-iomd.S
 F:     arch/arm/include/asm/hardware/ioc.h
 F:     arch/arm/include/asm/hardware/iomd.h
@@ -1094,7 +1094,6 @@ W:        http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/plat-samsung/
 F:     arch/arm/plat-s3c24xx/
-F:     arch/arm/plat-s5p/
 F:     arch/arm/mach-s3c24*/
 F:     arch/arm/mach-s3c64xx/
 F:     drivers/*/*s3c2410*
@@ -1125,7 +1124,6 @@ M:        Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     arch/arm/plat-s5p/dev-fimc*
 F:     arch/arm/plat-samsung/include/plat/*fimc*
 F:     drivers/media/platform/s5p-fimc/
 
@@ -1136,7 +1134,7 @@ M:        Jeongtae Park <jtp.park@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     arch/arm/plat-s5p/dev-mfc.c
+F:     arch/arm/plat-samsung/s5p-dev-mfc.c
 F:     drivers/media/platform/s5p-mfc/
 
 ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT
@@ -1254,7 +1252,7 @@ F:        drivers/video/vt8500lcdfb.*
 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/rtc/rtc-vt8500.c
 F:     drivers/mmc/host/wmt-sdmmc.c
 
 ARM/ZIPIT Z2 SUPPORT
@@ -1305,7 +1303,7 @@ F:        include/linux/dmaengine.h
 F:     include/linux/async_tx.h
 
 AT24 EEPROM DRIVER
-M:     Wolfram Sang <w.sang@pengutronix.de>
+M:     Wolfram Sang <wsa@the-dreams.de>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/misc/eeprom/at24.c
@@ -1353,6 +1351,14 @@ W:       http://wireless.kernel.org/en/users/Drivers/ath9k
 S:     Supported
 F:     drivers/net/wireless/ath/ath9k/
 
+WILOCITY WIL6210 WIRELESS DRIVER
+M:     Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
+L:     linux-wireless@vger.kernel.org
+L:     wil6210@qca.qualcomm.com
+S:     Supported
+W:     http://wireless.kernel.org/en/users/Drivers/wil6210
+F:     drivers/net/wireless/ath/wil6210/
+
 CARL9170 LINUX COMMUNITY WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
 L:     linux-wireless@vger.kernel.org
@@ -1388,6 +1394,7 @@ W:        http://linux-atm.sourceforge.net
 S:     Maintained
 F:     drivers/atm/
 F:     include/linux/atm*
+F:     include/uapi/linux/atm*
 
 ATMEL AT91 / AT32 MCI DRIVER
 M:     Ludovic Desroches <ludovic.desroches@atmel.com>
@@ -1406,13 +1413,13 @@ L:      linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/dma/at_hdmac.c
 F:     drivers/dma/at_hdmac_regs.h
-F:     arch/arm/mach-at91/include/mach/at_hdmac.h
+F:     include/linux/platform_data/dma-atmel.h
 
 ATMEL ISI DRIVER
 M:     Josh Wu <josh.wu@atmel.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
-F:     drivers/media/platform/atmel-isi.c
+F:     drivers/media/platform/soc_camera/atmel-isi.c
 F:     include/media/atmel-isi.h
 
 ATMEL LCDFB DRIVER
@@ -1467,6 +1474,7 @@ W:        http://people.redhat.com/sgrubb/audit/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
 S:     Maintained
 F:     include/linux/audit.h
+F:     include/uapi/linux/audit.h
 F:     kernel/audit*
 
 AUXILIARY DISPLAY DRIVERS
@@ -1481,7 +1489,7 @@ AVR32 ARCHITECTURE
 M:     Haavard Skinnemoen <hskinnemoen@gmail.com>
 M:     Hans-Christian Egtvedt <egtvedt@samfundet.no>
 W:     http://www.atmel.com/products/AVR32/
-W:     http://avr32linux.org/
+W:     http://mirror.egtvedt.no/avr32linux.org/
 W:     http://avrfreaks.net/
 S:     Maintained
 F:     arch/avr32/
@@ -1497,7 +1505,7 @@ M:        Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
-F:     include/linux/ax25.h
+F:     include/uapi/linux/ax25.h
 F:     include/net/ax25.h
 F:     net/ax25/
 
@@ -1558,7 +1566,7 @@ M:        "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
 S:     Maintained
 F:     Documentation/filesystems/bfs.txt
 F:     fs/bfs/
-F:     include/linux/bfs_fs.h
+F:     include/uapi/linux/bfs_fs.h
 
 BLACKFIN ARCHITECTURE
 M:     Mike Frysinger <vapier@gentoo.org>
@@ -1655,7 +1663,7 @@ L:        netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/bonding/
 S:     Supported
 F:     drivers/net/bonding/
-F:     include/linux/if_bonding.h
+F:     include/uapi/linux/if_bonding.h
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Gary Zambrano <zambrano@broadcom.com>
@@ -1734,6 +1742,7 @@ L:        linux-scsi@vger.kernel.org
 S:     Supported
 F:     block/bsg.c
 F:     include/linux/bsg.h
+F:     include/uapi/linux/bsg.h
 
 BT87X AUDIO DRIVER
 M:     Clemens Ladisch <clemens@ladisch.de>
@@ -1804,7 +1813,7 @@ L:        netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/caif/
 F:     drivers/net/caif/
-F:     include/linux/caif/
+F:     include/uapi/linux/caif/
 F:     include/net/caif/
 F:     net/caif/
 
@@ -1825,11 +1834,11 @@ W:      http://gitorious.org/linux-can
 T:     git git://gitorious.org/linux-can/linux-can-next.git
 S:     Maintained
 F:     net/can/
-F:     include/linux/can.h
 F:     include/linux/can/core.h
-F:     include/linux/can/bcm.h
-F:     include/linux/can/raw.h
-F:     include/linux/can/gw.h
+F:     include/uapi/linux/can.h
+F:     include/uapi/linux/can/bcm.h
+F:     include/uapi/linux/can/raw.h
+F:     include/uapi/linux/can/gw.h
 
 CAN NETWORK DRIVERS
 M:     Wolfgang Grandegger <wg@grandegger.com>
@@ -1840,15 +1849,16 @@ T:      git git://gitorious.org/linux-can/linux-can-next.git
 S:     Maintained
 F:     drivers/net/can/
 F:     include/linux/can/dev.h
-F:     include/linux/can/error.h
-F:     include/linux/can/netlink.h
 F:     include/linux/can/platform/
+F:     include/uapi/linux/can/error.h
+F:     include/uapi/linux/can/netlink.h
 
 CAPABILITIES
 M:     Serge Hallyn <serge.hallyn@canonical.com>
 L:     linux-security-module@vger.kernel.org
 S:     Supported
 F:     include/linux/capability.h
+F:     include/uapi/linux/capability.h
 F:     security/capability.c
 F:     security/commoncap.c
 F:     kernel/capability.c
@@ -1861,6 +1871,7 @@ W:        http://www.ibm.com/developerworks/power/cell/
 S:     Supported
 F:     arch/powerpc/include/asm/cell*.h
 F:     arch/powerpc/include/asm/spu*.h
+F:     arch/powerpc/include/uapi/asm/spu*.h
 F:     arch/powerpc/oprofile/*cell*
 F:     arch/powerpc/platforms/cell/
 
@@ -1909,7 +1920,7 @@ W:        http://wireless.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
 S:     Maintained
-F:     include/linux/nl80211.h
+F:     include/uapi/linux/nl80211.h
 F:     include/net/cfg80211.h
 F:     net/wireless/*
 X:     net/wireless/wext*
@@ -1961,9 +1972,9 @@ S:        Maintained
 F:     drivers/usb/host/ohci-ep93xx.c
 
 CIRRUS LOGIC CS4270 SOUND DRIVER
-M:     Timur Tabi <timur@freescale.com>
+M:     Timur Tabi <timur@tabi.org>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Supported
+S:     Odd Fixes
 F:     sound/soc/codecs/cs4270*
 
 CLEANCACHE API
@@ -2012,6 +2023,7 @@ S:        Maintained
 F:     Documentation/filesystems/coda.txt
 F:     fs/coda/
 F:     include/linux/coda*.h
+F:     include/uapi/linux/coda*.h
 
 COMMON CLK FRAMEWORK
 M:     Mike Turquette <mturquette@linaro.org>
@@ -2266,6 +2278,7 @@ W:        http://www.cyclades.com/
 S:     Orphan
 F:     drivers/tty/cyclades.c
 F:     include/linux/cyclades.h
+F:     include/uapi/linux/cyclades.h
 
 CYCLADES PC300 DRIVER
 W:     http://www.cyclades.com/
@@ -2323,6 +2336,7 @@ L:        dccp@vger.kernel.org
 W:     http://www.linuxfoundation.org/collaborate/workgroups/networking/dccp
 S:     Maintained
 F:     include/linux/dccp.h
+F:     include/uapi/linux/dccp.h
 F:     include/linux/tfrc.h
 F:     net/dccp/
 
@@ -2349,7 +2363,7 @@ M:        Massimo Dal Zotto <dz@debian.org>
 W:     http://www.debian.org/~dz/i8k/
 S:     Maintained
 F:     drivers/char/i8k.c
-F:     include/linux/i8k.h
+F:     include/uapi/linux/i8k.h
 
 DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
 M:     Doug Warzecha <Douglas_Warzecha@dell.com>
@@ -2422,6 +2436,7 @@ S:        Maintained
 F:     Documentation/filesystems/quota.txt
 F:     fs/quota/
 F:     include/linux/quota*.h
+F:     include/uapi/linux/quota*.h
 
 DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB)
 M:     Bernie Thompson <bernie@plugable.com>
@@ -2528,6 +2543,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:     Maintained
 F:     drivers/gpu/drm/
 F:     include/drm/
+F:     include/uapi/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
@@ -2537,6 +2553,7 @@ T:        git git://people.freedesktop.org/~danvet/drm-intel
 S:     Supported
 F:     drivers/gpu/drm/i915
 F:     include/drm/i915*
+F:     include/uapi/drm/i915*
 
 DRM DRIVERS FOR EXYNOS
 M:     Inki Dae <inki.dae@samsung.com>
@@ -2548,6 +2565,7 @@ 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*
+F:     include/uapi/drm/exynos*
 
 DRM DRIVERS FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@avionic-design.de>
@@ -2622,7 +2640,7 @@ W:        http://github.com/mkrufky
 Q:     http://patchwork.linuxtv.org/project/linux-media/list/
 T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
-F:     drivers/media/usb/dvb-usb-v2/cxusb*
+F:     drivers/media/usb/dvb-usb/cxusb*
 
 DVB_USB_CYPRESS_FIRMWARE MEDIA DRIVER
 M:     Antti Palosaari <crope@iki.fi>
@@ -2722,6 +2740,7 @@ L:        netfilter-devel@vger.kernel.org
 W:     http://ebtables.sourceforge.net/
 S:     Maintained
 F:     include/linux/netfilter_bridge/ebt_*.h
+F:     include/uapi/linux/netfilter_bridge/ebt_*.h
 F:     net/bridge/netfilter/ebt*.c
 
 EC100 MEDIA DRIVER
@@ -2933,12 +2952,6 @@ M:       Maxim Levitsky <maximlevitsky@gmail.com>
 S:     Maintained
 F:     drivers/media/rc/ene_ir.*
 
-EPSON 1355 FRAMEBUFFER DRIVER
-M:     Christopher Hoover <ch@murgatroid.com>
-M:     Christopher Hoover <ch@hpl.hp.com>
-S:     Maintained
-F:     drivers/video/epson1355fb.c
-
 EPSON S1D13XXX FRAMEBUFFER DRIVER
 M:     Kristoffer Ericson <kristoffer.ericson@gmail.com>
 S:     Maintained
@@ -2953,7 +2966,7 @@ S:        Maintained
 F:     drivers/net/ethernet/i825xx/eexpress.*
 
 ETHERNET BRIDGE
-M:     Stephen Hemminger <shemminger@vyatta.com>
+M:     Stephen Hemminger <stephen@networkplumber.org>
 L:     bridge@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net:Bridge
@@ -3051,6 +3064,7 @@ M:        Eric Paris <eparis@redhat.com>
 S:     Maintained
 F:     fs/notify/fanotify/
 F:     include/linux/fanotify.h
+F:     include/uapi/linux/fanotify.h
 
 FARSYNC SYNCHRONOUS DRIVER
 M:     Kevin Curtis <kevin.curtis@farsite.co.uk>
@@ -3074,6 +3088,7 @@ F:        drivers/scsi/fcoe/
 F:     include/scsi/fc/
 F:     include/scsi/libfc.h
 F:     include/scsi/libfcoe.h
+F:     include/uapi/scsi/fc/
 
 FILE LOCKING (flock() and fcntl()/lockf())
 M:     Matthew Wilcox <matthew@wil.cx>
@@ -3081,6 +3096,8 @@ L:        linux-fsdevel@vger.kernel.org
 S:     Maintained
 F:     include/linux/fcntl.h
 F:     include/linux/fs.h
+F:     include/uapi/linux/fcntl.h
+F:     include/uapi/linux/fs.h
 F:     fs/fcntl.c
 F:     fs/locks.c
 
@@ -3170,11 +3187,13 @@ F:      Documentation/devicetree/bindings/fb/
 F:     drivers/video/
 F:     include/video/
 F:     include/linux/fb.h
+F:     include/uapi/video/
+F:     include/uapi/linux/fb.h
 
 FREESCALE DIU FRAMEBUFFER DRIVER
-M:     Timur Tabi <timur@freescale.com>
+M:     Timur Tabi <timur@tabi.org>
 L:     linux-fbdev@vger.kernel.org
-S:     Supported
+S:     Maintained
 F:     drivers/video/fsl-diu-fb.*
 
 FREESCALE DMA DRIVER
@@ -3196,7 +3215,7 @@ M:        Sascha Hauer <kernel@pengutronix.de>
 L:     linux-fbdev@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     arch/arm/plat-mxc/include/mach/imxfb.h
+F:     include/linux/platform_data/video-imxfb.h
 F:     drivers/video/imxfb.c
 
 FREESCALE SOC FS_ENET DRIVER
@@ -3209,9 +3228,8 @@ F:        drivers/net/ethernet/freescale/fs_enet/
 F:     include/linux/fs_enet_pd.h
 
 FREESCALE QUICC ENGINE LIBRARY
-M:     Timur Tabi <timur@freescale.com>
 L:     linuxppc-dev@lists.ozlabs.org
-S:     Supported
+S:     Orphan
 F:     arch/powerpc/sysdev/qe_lib/
 F:     arch/powerpc/include/asm/*qe.h
 
@@ -3230,16 +3248,16 @@ S:      Maintained
 F:     drivers/net/ethernet/freescale/ucc_geth*
 
 FREESCALE QUICC ENGINE UCC UART DRIVER
-M:     Timur Tabi <timur@freescale.com>
+M:     Timur Tabi <timur@tabi.org>
 L:     linuxppc-dev@lists.ozlabs.org
-S:     Supported
+S:     Maintained
 F:     drivers/tty/serial/ucc_uart.c
 
 FREESCALE SOC SOUND DRIVERS
-M:     Timur Tabi <timur@freescale.com>
+M:     Timur Tabi <timur@tabi.org>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@lists.ozlabs.org
-S:     Supported
+S:     Maintained
 F:     sound/soc/fsl/fsl*
 F:     sound/soc/fsl/mpc8610_hpcd.c
 
@@ -3273,6 +3291,16 @@ F:       Documentation/filesystems/caching/
 F:     fs/fscache/
 F:     include/linux/fscache*.h
 
+F2FS FILE SYSTEM
+M:     Jaegeuk Kim <jaegeuk.kim@samsung.com>
+L:     linux-f2fs-devel@lists.sourceforge.net
+W:     http://en.wikipedia.org/wiki/F2FS
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
+S:     Maintained
+F:     Documentation/filesystems/f2fs.txt
+F:     fs/f2fs/
+F:     include/linux/f2fs_fs.h
+
 FUJITSU FR-V (FRV) PORT
 M:     David Howells <dhowells@redhat.com>
 S:     Maintained
@@ -3304,7 +3332,7 @@ L:        fuse-devel@lists.sourceforge.net
 W:     http://fuse.sourceforge.net/
 S:     Maintained
 F:     fs/fuse/
-F:     include/linux/fuse.h
+F:     include/uapi/linux/fuse.h
 
 FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
 M:     Rik Faith <faith@cs.unc.edu>
@@ -3351,6 +3379,7 @@ L:        linux-arch@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
 S:     Maintained
 F:     include/asm-generic
+F:     include/uapi/asm-generic
 
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:     "Michael S. Tsirkin" <mst@redhat.com>
@@ -3367,7 +3396,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git
 S:     Supported
 F:     Documentation/filesystems/gfs2*.txt
 F:     fs/gfs2/
-F:     include/linux/gfs2_ondisk.h
+F:     include/uapi/linux/gfs2_ondisk.h
 
 GIGASET ISDN DRIVERS
 M:     Hansjoerg Lipp <hjlipp@web.de>
@@ -3377,7 +3406,7 @@ W:        http://gigaset307x.sourceforge.net/
 S:     Maintained
 F:     Documentation/isdn/README.gigaset
 F:     drivers/isdn/gigaset/
-F:     include/linux/gigaset_dev.h
+F:     include/uapi/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
 M:     Grant Likely <grant.likely@secretlab.ca>
@@ -3534,6 +3563,7 @@ S:        Supported
 F:     Documentation/scsi/hpsa.txt
 F:     drivers/scsi/hpsa*.[ch]
 F:     include/linux/cciss*.h
+F:     include/uapi/linux/cciss*.h
 
 HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
 M:     Mike Miller <mike.miller@hp.com>
@@ -3542,6 +3572,7 @@ S:        Supported
 F:     Documentation/blockdev/cciss.txt
 F:     drivers/block/cciss*
 F:     include/linux/cciss_ioctl.h
+F:     include/uapi/linux/cciss_ioctl.h
 
 HFS FILESYSTEM
 L:     linux-fsdevel@vger.kernel.org
@@ -3576,6 +3607,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
 S:     Maintained
 F:     drivers/hid/
 F:     include/linux/hid*
+F:     include/uapi/linux/hid*
 
 HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
 M:     Thomas Gleixner <tglx@linutronix.de>
@@ -3607,7 +3639,7 @@ M:        Jes Sorensen <jes@trained-monkey.org>
 L:     linux-hippi@sunsite.dk
 S:     Maintained
 F:     include/linux/hippidevice.h
-F:     include/linux/if_hippi.h
+F:     include/uapi/linux/if_hippi.h
 F:     net/802/hippi.c
 F:     drivers/net/hippi/
 
@@ -3635,6 +3667,7 @@ S:        Maintained
 F:     Documentation/timers/hpet.txt
 F:     drivers/char/hpet.c
 F:     include/linux/hpet.h
+F:     include/uapi/linux/hpet.h
 
 HPET:  x86
 M:     "Venkatesh Pallipadi (Venki)" <venki@google.com>
@@ -3724,17 +3757,18 @@ S:      Maintained
 F:     drivers/i2c/i2c-stub.c
 
 I2C SUBSYSTEM
-M:     Wolfram Sang <w.sang@pengutronix.de>
+M:     Wolfram Sang <wsa@the-dreams.de>
 M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
 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/
-T:     git git://git.pengutronix.de/git/wsa/linux.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
 S:     Maintained
 F:     Documentation/i2c/
 F:     drivers/i2c/
 F:     include/linux/i2c.h
 F:     include/linux/i2c-*.h
+F:     include/uapi/linux/i2c.h
+F:     include/uapi/linux/i2c-*.h
 
 I2C-TAOS-EVM DRIVER
 M:     Jean Delvare <khali@linux-fr.org>
@@ -3850,7 +3884,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
 S:     Maintained
 F:     net/ieee802154/
 F:     net/mac802154/
-F:     drivers/ieee802154/
+F:     drivers/net/ieee802154/
 
 IGUANAWORKS USB IR TRANSCEIVER
 M:     Sean Young <sean@mess.org>
@@ -3901,7 +3935,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
 S:     Supported
 F:     Documentation/infiniband/
 F:     drivers/infiniband/
-F:     include/linux/if_infiniband.h
+F:     include/uapi/linux/if_infiniband.h
 
 INOTIFY
 M:     John McCutchan <john@johnmccutchan.com>
@@ -3911,6 +3945,7 @@ S:        Maintained
 F:     Documentation/filesystems/inotify.txt
 F:     fs/notify/inotify/
 F:     include/linux/inotify.h
+F:     include/uapi/linux/inotify.h
 
 INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
 M:     Dmitry Torokhov <dmitry.torokhov@gmail.com>
@@ -3921,6 +3956,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
 S:     Maintained
 F:     drivers/input/
 F:     include/linux/input.h
+F:     include/uapi/linux/input.h
 F:     include/linux/input/
 
 INPUT MULTITOUCH (MT) PROTOCOL
@@ -3941,7 +3977,6 @@ L:        linux-scsi@vger.kernel.org
 T:     git git://git.code.sf.net/p/intel-sas/isci
 S:     Supported
 F:     drivers/scsi/isci/
-F:     firmware/isci/
 
 INTEL IDLE DRIVER
 M:     Len Brown <lenb@kernel.org>
@@ -4036,12 +4071,6 @@ F:       Documentation/networking/ixgbe.txt
 F:     Documentation/networking/ixgbevf.txt
 F:     drivers/net/ethernet/intel/
 
-INTEL MRST PMU DRIVER
-M:     Len Brown <len.brown@intel.com>
-L:     linux-pm@vger.kernel.org
-S:     Supported
-F:     arch/x86/platform/mrst/pmu.*
-
 INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
 M:     Stanislav Yakovlev <stas.yakovlev@gmail.com>
 L:     linux-wireless@vger.kernel.org
@@ -4070,7 +4099,7 @@ S:        Supported
 W:     http://linuxwimax.org
 F:     Documentation/wimax/README.i2400m
 F:     drivers/net/wimax/i2400m/
-F:     include/linux/wimax/i2400m.h
+F:     include/uapi/linux/wimax/i2400m.h
 
 INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
 M:     Stanislaw Gruszka <sgruszka@redhat.com>
@@ -4092,9 +4121,9 @@ INTEL MANAGEMENT ENGINE (mei)
 M:     Tomas Winkler <tomas.winkler@intel.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
-F:     include/linux/mei.h
+F:     include/uapi/linux/mei.h
 F:     drivers/misc/mei/*
-F:     Documentation/mei/*
+F:     Documentation/misc-devices/mei/*
 
 IOC3 ETHERNET DRIVER
 M:     Ralf Baechle <ralf@linux-mips.org>
@@ -4134,6 +4163,7 @@ S:        Supported
 F:     Documentation/IPMI.txt
 F:     drivers/char/ipmi/
 F:     include/linux/ipmi*
+F:     include/uapi/linux/ipmi*
 
 IPS SCSI RAID DRIVER
 M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
@@ -4151,7 +4181,7 @@ L:        lvs-devel@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/ipvs-sysctl.txt
 F:     include/net/ip_vs.h
-F:     include/linux/ip_vs.h
+F:     include/uapi/linux/ip_vs.h
 F:     net/netfilter/ipvs/
 
 IPWIRELESS DRIVER
@@ -4164,8 +4194,8 @@ IPX NETWORK LAYER
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     include/linux/ipx.h
 F:     include/net/ipx.h
+F:     include/uapi/linux/ipx.h
 F:     net/ipx/
 
 IRDA SUBSYSTEM
@@ -4228,6 +4258,8 @@ F:        Documentation/isdn/
 F:     drivers/isdn/
 F:     include/linux/isdn.h
 F:     include/linux/isdn/
+F:     include/uapi/linux/isdn.h
+F:     include/uapi/linux/isdn/
 
 ISDN SUBSYSTEM (Eicon active card driver)
 M:     Armin Schindler <mac@melware.de>
@@ -4268,7 +4300,7 @@ W:        http://www.ivtvdriver.org
 S:     Maintained
 F:     Documentation/video4linux/*.ivtv
 F:     drivers/media/pci/ivtv/
-F:     include/linux/ivtv*
+F:     include/uapi/linux/ivtv*
 
 IX2505V MEDIA DRIVER
 M:     Malcolm Priestley <tvboxspy@gmail.com>
@@ -4306,7 +4338,7 @@ L:        linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/doc/jffs2.html
 S:     Maintained
 F:     fs/jffs2/
-F:     include/linux/jffs2.h
+F:     include/uapi/linux/jffs2.h
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 M:     Andrew Morton <akpm@linux-foundation.org>
@@ -4389,11 +4421,13 @@ W:      http://nfs.sourceforge.net/
 S:     Supported
 F:     fs/nfsd/
 F:     include/linux/nfsd/
+F:     include/uapi/linux/nfsd/
 F:     fs/lockd/
 F:     fs/nfs_common/
 F:     net/sunrpc/
 F:     include/linux/lockd/
 F:     include/linux/sunrpc/
+F:     include/uapi/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
 M:     Marcelo Tosatti <mtosatti@redhat.com>
@@ -4405,6 +4439,7 @@ F:        Documentation/*/kvm.txt
 F:     arch/*/kvm/
 F:     arch/*/include/asm/kvm*
 F:     include/linux/kvm*
+F:     include/uapi/linux/kvm*
 F:     virt/kvm/
 
 KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
@@ -4451,6 +4486,7 @@ W:        http://kernel.org/pub/linux/utils/kernel/kexec/
 L:     kexec@lists.infradead.org
 S:     Maintained
 F:     include/linux/kexec.h
+F:     include/uapi/linux/kexec.h
 F:     kernel/kexec.c
 
 KEYS/KEYRINGS:
@@ -4692,6 +4728,7 @@ LLC (802.2)
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:     Maintained
 F:     include/linux/llc.h
+F:     include/uapi/linux/llc.h
 F:     include/net/llc*
 F:     net/llc/
 
@@ -4867,7 +4904,7 @@ S:        Maintained
 
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:     Mirko Lindner <mlindner@marvell.com>
-M:     Stephen Hemminger <shemminger@vyatta.com>
+M:     Stephen Hemminger <stephen@networkplumber.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/marvell/sk*
@@ -4912,7 +4949,7 @@ MATROX FRAMEBUFFER DRIVER
 L:     linux-fbdev@vger.kernel.org
 S:     Orphan
 F:     drivers/video/matrox/matroxfb_*
-F:     include/linux/matroxfb.h
+F:     include/uapi/linux/matroxfb.h
 
 MAX16065 HARDWARE MONITOR DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
@@ -4994,7 +5031,7 @@ T:        git git://git.infradead.org/mtd-2.6.git
 S:     Maintained
 F:     drivers/mtd/
 F:     include/linux/mtd/
-F:     include/mtd/
+F:     include/uapi/mtd/
 
 MICROBLAZE ARCHITECTURE
 M:     Michal Simek <monstr@monstr.eu>
@@ -5032,12 +5069,6 @@ F:       Documentation/video4linux/meye.txt
 F:     drivers/media/pci/meye/
 F:     include/uapi/linux/meye.h
 
-MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
-M:     Pavel Pisa <ppisa@pikron.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     drivers/mmc/host/imxmmc.*
-
 MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
 M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
@@ -5052,7 +5083,7 @@ S:        Maintained
 F:     drivers/media/radio/radio-mr800.c
 
 MSI LAPTOP SUPPORT
-M:     "Lee, Chun-Yi" <jlee@novell.com>
+M:     "Lee, Chun-Yi" <jlee@suse.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/msi-laptop.c
@@ -5076,6 +5107,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
 S:     Maintained
 F:     drivers/mmc/
 F:     include/linux/mmc/
+F:     include/uapi/linux/mmc/
 
 MULTIMEDIA CARD (MMC) ETC. OVER SPI
 S:     Orphan
@@ -5147,7 +5179,7 @@ S:        Supported
 F:     drivers/infiniband/hw/nes/
 
 NETEM NETWORK EMULATOR
-M:     Stephen Hemminger <shemminger@vyatta.com>
+M:     Stephen Hemminger <stephen@networkplumber.org>
 L:     netem@lists.linux-foundation.org
 S:     Maintained
 F:     net/sched/sch_netem.c
@@ -5176,6 +5208,8 @@ S:        Supported
 F:     include/linux/netfilter*
 F:     include/linux/netfilter/
 F:     include/net/netfilter/
+F:     include/uapi/linux/netfilter*
+F:     include/uapi/linux/netfilter/
 F:     net/*/netfilter.c
 F:     net/*/netfilter/
 F:     net/netfilter/
@@ -5194,8 +5228,8 @@ M:        Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
-F:     include/linux/netrom.h
 F:     include/net/netrom.h
+F:     include/uapi/linux/netrom.h
 F:     net/netrom/
 
 NETWORK BLOCK DEVICE (NBD)
@@ -5204,6 +5238,7 @@ S:        Maintained
 F:     Documentation/blockdev/nbd.txt
 F:     drivers/block/nbd.c
 F:     include/linux/nbd.h
+F:     include/uapi/linux/nbd.h
 
 NETWORK DROP MONITOR
 M:     Neil Horman <nhorman@tuxdriver.com>
@@ -5225,6 +5260,9 @@ F:        include/net/
 F:     include/linux/in.h
 F:     include/linux/net.h
 F:     include/linux/netdevice.h
+F:     include/uapi/linux/in.h
+F:     include/uapi/linux/net.h
+F:     include/uapi/linux/netdevice.h
 
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
@@ -5270,6 +5308,7 @@ F:        net/rfkill/
 F:     net/wireless/
 F:     include/net/ieee80211*
 F:     include/linux/wireless.h
+F:     include/uapi/linux/wireless.h
 F:     include/net/iw_handler.h
 F:     drivers/net/wireless/
 
@@ -5289,6 +5328,8 @@ F:        include/linux/fcdevice.h
 F:     include/linux/fddidevice.h
 F:     include/linux/hippidevice.h
 F:     include/linux/inetdevice.h
+F:     include/uapi/linux/if_*
+F:     include/uapi/linux/netdevice.h
 
 NETXEN (1/10) GbE SUPPORT
 M:     Sony Chacko <sony.chacko@qlogic.com>
@@ -5306,8 +5347,8 @@ L:        linux-wireless@vger.kernel.org
 L:     linux-nfc@lists.01.org (moderated for non-subscribers)
 S:     Maintained
 F:     net/nfc/
-F:     include/linux/nfc.h
 F:     include/net/nfc/
+F:     include/uapi/linux/nfc.h
 F:     drivers/nfc/
 F:     include/linux/platform_data/pn544.h
 
@@ -5324,6 +5365,8 @@ F:        net/sunrpc/
 F:     include/linux/lockd/
 F:     include/linux/nfs*
 F:     include/linux/sunrpc/
+F:     include/uapi/linux/nfs*
+F:     include/uapi/linux/sunrpc/
 
 NI5010 NETWORK DRIVER
 M:     Jan-Pascal van Best <janpascal@vanbest.org>
@@ -5385,6 +5428,15 @@ F:       arch/arm/*omap*/
 F:     drivers/i2c/busses/i2c-omap.c
 F:     include/linux/i2c-omap.h
 
+OMAP DEVICE TREE SUPPORT
+M:     Benoît Cousson <b-cousson@ti.com>
+M:     Tony Lindgren <tony@atomide.com>
+L:     linux-omap@vger.kernel.org
+L:     devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/boot/dts/*omap*
+F:     arch/arm/boot/dts/*am3*
+
 OMAP CLOCK FRAMEWORK SUPPORT
 M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
@@ -5461,8 +5513,7 @@ M:        Benoît Cousson <b-cousson@ti.com>
 M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
-F:     arch/arm/mach-omap2/omap_hwmod.c
-F:     arch/arm/plat-omap/include/plat/omap_hwmod.h
+F:     arch/arm/mach-omap2/omap_hwmod.*
 
 OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
 M:     Benoît Cousson <b-cousson@ti.com>
@@ -5504,6 +5555,7 @@ M:        Harald Welte <laforge@gnumonks.org>
 S:     Maintained
 F:     drivers/char/pcmcia/cm4000_cs.c
 F:     include/linux/cm4000_cs.h
+F:     include/uapi/linux/cm4000_cs.h
 
 OMNIKEY CARDMAN 4040 DRIVER
 M:     Harald Welte <laforge@gnumonks.org>
@@ -5662,7 +5714,7 @@ S:        Orphan
 F:     drivers/parport/
 F:     include/linux/parport*.h
 F:     drivers/char/ppdev.c
-F:     include/linux/ppdev.h
+F:     include/uapi/linux/ppdev.h
 
 PARAVIRT_OPS INTERFACE
 M:     Jeremy Fitzhardinge <jeremy@goop.org>
@@ -5725,15 +5777,6 @@ L:       linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/muxes/i2c-mux-pca9541.c
 
-PCA9564/PCA9665 I2C BUS DRIVER
-M:     Wolfram Sang <w.sang@pengutronix.de>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     drivers/i2c/algos/i2c-algo-pca.c
-F:     drivers/i2c/busses/i2c-pca-*
-F:     include/linux/i2c-algo-pca.h
-F:     include/linux/i2c-pca-platform.h
-
 PCDP - PRIMARY CONSOLE AND DEBUG PORT
 M:     Khalid Aziz <khalid@gonehiking.org>
 S:     Maintained
@@ -5803,11 +5846,11 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
 S:     Supported
 F:     kernel/events/*
 F:     include/linux/perf_event.h
+F:     include/uapi/linux/perf_event.h
 F:     arch/*/kernel/perf_event*.c
 F:     arch/*/kernel/*/perf_event*.c
 F:     arch/*/kernel/*/*/perf_event*.c
 F:     arch/*/include/asm/perf_event.h
-F:     arch/*/lib/perf_event*.c
 F:     arch/*/kernel/perf_callchain.c
 F:     tools/perf/
 
@@ -5816,6 +5859,7 @@ M:        Christoph Hellwig <hch@infradead.org>
 L:     linux-abi-devel@lists.sourceforge.net
 S:     Maintained
 F:     include/linux/personality.h
+F:     include/uapi/linux/personality.h
 
 PHONET PROTOCOL
 M:     Remi Denis-Courmont <courmisch@gmail.com>
@@ -5823,6 +5867,7 @@ S:        Supported
 F:     Documentation/networking/phonet.txt
 F:     include/linux/phonet.h
 F:     include/net/phonet/
+F:     include/uapi/linux/phonet.h
 F:     net/phonet/
 
 PHRAM MTD DRIVER
@@ -5871,6 +5916,7 @@ M:        Jiri Kosina <jkosina@suse.cz>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
+F:     include/uapi/linux/pktcdvd.h
 
 PKUNITY SOC DRIVERS
 M:     Guan Xuetao <gxt@mprc.pku.edu.cn>
@@ -5945,7 +5991,7 @@ PPP OVER ATM (RFC 2364)
 M:     Mitchell Blank Jr <mitch@sfgoth.com>
 S:     Maintained
 F:     net/atm/pppoatm.c
-F:     include/linux/atmppp.h
+F:     include/uapi/linux/atmppp.h
 
 PPP OVER ETHERNET
 M:     Michal Ostrowski <mostrows@earthlink.net>
@@ -5958,6 +6004,7 @@ M:        James Chapman <jchapman@katalix.com>
 S:     Maintained
 F:     net/l2tp/l2tp_ppp.c
 F:     include/linux/if_pppol2tp.h
+F:     include/uapi/linux/if_pppol2tp.h
 
 PPS SUPPORT
 M:     Rodolfo Giometti <giometti@enneenne.com>
@@ -6055,6 +6102,7 @@ F:        include/asm-generic/syscall.h
 F:     include/linux/ptrace.h
 F:     include/linux/regset.h
 F:     include/linux/tracehook.h
+F:     include/uapi/linux/ptrace.h
 F:     kernel/ptrace.c
 
 PVRUSB2 VIDEO4LINUX DRIVER
@@ -6083,7 +6131,6 @@ T:        git git://gitorious.org/linux-pwm/linux-pwm.git
 F:     Documentation/pwm.txt
 F:     Documentation/devicetree/bindings/pwm/
 F:     include/linux/pwm.h
-F:     include/linux/of_pwm.h
 F:     drivers/pwm/
 F:     drivers/video/backlight/pwm_bl.c
 F:     include/linux/pwm_backlight.h
@@ -6179,8 +6226,8 @@ M:        Anders Larsen <al@alarsen.net>
 W:     http://www.alarsen.net/linux/qnx4fs/
 S:     Maintained
 F:     fs/qnx4/
-F:     include/linux/qnx4_fs.h
-F:     include/linux/qnxtypes.h
+F:     include/uapi/linux/qnx4_fs.h
+F:     include/uapi/linux/qnxtypes.h
 
 QT1010 MEDIA DRIVER
 M:     Antti Palosaari <crope@iki.fi>
@@ -6214,7 +6261,7 @@ M:        Benjamin Herrenschmidt <benh@kernel.crashing.org>
 L:     linux-fbdev@vger.kernel.org
 S:     Maintained
 F:     drivers/video/aty/radeon*
-F:     include/linux/radeonfb.h
+F:     include/uapi/linux/radeonfb.h
 
 RADIOSHARK RADIO DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
@@ -6315,6 +6362,7 @@ S:        Maintained
 F:     Documentation/rtc.txt
 F:     drivers/rtc/
 F:     include/linux/rtc.h
+F:     include/uapi/linux/rtc.h
 
 REISERFS FILE SYSTEM
 L:     reiserfs-devel@vger.kernel.org
@@ -6369,8 +6417,8 @@ M:        Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
-F:     include/linux/rose.h
 F:     include/net/rose.h
+F:     include/uapi/linux/rose.h
 F:     net/rose/
 
 RTL2830 MEDIA DRIVER
@@ -6527,7 +6575,7 @@ F:        drivers/media/platform/s3c-camif/
 F:     include/media/s3c_camif.h
 
 SERIAL DRIVERS
-M:     Alan Cox <alan@linux.intel.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial
@@ -6540,13 +6588,15 @@ F:      drivers/dma/dw_dmac_regs.h
 F:     drivers/dma/dw_dmac.c
 
 TIMEKEEPING, NTP
-M:     John Stultz <johnstul@us.ibm.com>
+M:     John Stultz <john.stultz@linaro.org>
 M:     Thomas Gleixner <tglx@linutronix.de>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
 S:     Supported
 F:     include/linux/clocksource.h
 F:     include/linux/time.h
 F:     include/linux/timex.h
+F:     include/uapi/linux/time.h
+F:     include/uapi/linux/timex.h
 F:     kernel/time/clocksource.c
 F:     kernel/time/time*.c
 F:     kernel/time/ntp.c
@@ -6571,6 +6621,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
 S:     Maintained
 F:     kernel/sched/
 F:     include/linux/sched.h
+F:     include/uapi/linux/sched.h
 
 SCORE ARCHITECTURE
 M:     Chen Liqin <liqin.chen@sunplusct.com>
@@ -6724,7 +6775,7 @@ SENSABLE PHANTOM
 M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
 F:     drivers/misc/phantom.c
-F:     include/linux/phantom.h
+F:     include/uapi/linux/phantom.h
 
 SERIAL ATA (SATA) SUBSYSTEM
 M:     Jeff Garzik <jgarzik@pobox.com>
@@ -6982,6 +7033,7 @@ L:        linux-raid@vger.kernel.org
 S:     Supported
 F:     drivers/md/
 F:     include/linux/raid/
+F:     include/uapi/linux/raid/
 
 SONIC NETWORK DRIVER
 M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
@@ -7022,10 +7074,11 @@ T:      git git://git.alsa-project.org/alsa-kernel.git
 S:     Maintained
 F:     Documentation/sound/
 F:     include/sound/
+F:     include/uapi/sound/
 F:     sound/
 
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
-M:     Liam Girdwood <lrg@ti.com>
+M:     Liam Girdwood <lgirdwood@gmail.com>
 M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -7122,6 +7175,7 @@ S:        Maintained
 F:     Documentation/spi/
 F:     drivers/spi/
 F:     include/linux/spi/
+F:     include/uapi/linux/spi/
 
 SPIDERNET NETWORK DRIVER for CELL
 M:     Ishizaki Kou <kou.ishizaki@toshiba.co.jp>
@@ -7258,7 +7312,7 @@ F:        drivers/staging/rtl8712/
 STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
 M:     Teddy Wang <teddy.wang@siliconmotion.com.cn>
 S:     Odd Fixes
-F:     drivers/staging/sm7xx/
+F:     drivers/staging/sm7xxfb/
 
 STAGING - SOFTLOGIC 6x10 MPEG CODEC
 M:     Ben Collins <bcollins@bluecherry.net>
@@ -7276,7 +7330,7 @@ S:        Odd Fixes
 F:     drivers/staging/speakup/
 
 STAGING - TI DSP BRIDGE DRIVERS
-M:     Omar Ramirez Luna <omar.ramirez@ti.com>
+M:     Omar Ramirez Luna <omar.ramirez@copitl.com>
 S:     Odd Fixes
 F:     drivers/staging/tidspbridge/
 
@@ -7384,8 +7438,8 @@ TC CLASSIFIER
 M:     Jamal Hadi Salim <jhs@mojatatu.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     include/linux/pkt_cls.h
 F:     include/net/pkt_cls.h
+F:     include/uapi/linux/pkt_cls.h
 F:     net/sched/
 
 TCP LOW PRIORITY MODULE
@@ -7477,6 +7531,7 @@ L:        netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/team/
 F:     include/linux/if_team.h
+F:     include/uapi/linux/if_team.h
 
 TECHNOTREND USB IR RECEIVER
 M:     Sean Young <sean@mess.org>
@@ -7575,7 +7630,7 @@ L:        netdev@vger.kernel.org (core kernel code)
 L:     tipc-discussion@lists.sourceforge.net (user apps, general discussion)
 W:     http://tipc.sourceforge.net/
 S:     Maintained
-F:     include/linux/tipc*.h
+F:     include/uapi/linux/tipc*.h
 F:     net/tipc/
 
 TILE ARCHITECTURE
@@ -7625,6 +7680,7 @@ W:        http://www.buzzard.org.uk/toshiba/
 S:     Maintained
 F:     drivers/char/toshiba.c
 F:     include/linux/toshiba.h
+F:     include/uapi/linux/toshiba.h
 
 TMIO MMC DRIVER
 M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@@ -7692,6 +7748,9 @@ F:        drivers/tty/serial/serial_core.c
 F:     include/linux/serial_core.h
 F:     include/linux/serial.h
 F:     include/linux/tty.h
+F:     include/uapi/linux/serial_core.h
+F:     include/uapi/linux/serial.h
+F:     include/uapi/linux/tty.h
 
 TUA9001 MEDIA DRIVER
 M:     Antti Palosaari <crope@iki.fi>
@@ -7771,7 +7830,7 @@ M:        David Herrmann <dh.herrmann@googlemail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/hid/uhid.c
-F:     include/linux/uhid.h
+F:     include/uapi/linux/uhid.h
 
 ULTRA-WIDEBAND (UWB) SUBSYSTEM:
 L:     linux-usb@vger.kernel.org
@@ -7800,6 +7859,7 @@ S:        Maintained
 F:     Documentation/cdrom/
 F:     drivers/cdrom/cdrom.c
 F:     include/linux/cdrom.h
+F:     include/uapi/linux/cdrom.h
 
 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
 M:     Vinayak Holikatti <vinholikatti@gmail.com>
@@ -7817,7 +7877,7 @@ T:        git git://git.infradead.org/ubi-2.6.git
 S:     Maintained
 F:     drivers/mtd/ubi/
 F:     include/linux/mtd/ubi.h
-F:     include/mtd/ubi-user.h
+F:     include/uapi/mtd/ubi-user.h
 
 UNSORTED BLOCK IMAGES (UBI) Fastmap
 M:     Richard Weinberger <richard@nod.at>
@@ -7851,7 +7911,7 @@ M:        Oliver Neukum <oliver@neukum.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/net/usb/cdc_*.c
-F:     include/linux/usb/cdc.h
+F:     include/uapi/linux/usb/cdc.h
 
 USB CYPRESS C67X00 DRIVER
 M:     Peter Korsgaard <jacmet@sunsite.dk>
@@ -8172,6 +8232,7 @@ S:        Maintained
 F:     Documentation/vfio.txt
 F:     drivers/vfio/
 F:     include/linux/vfio.h
+F:     include/uapi/linux/vfio.h
 
 VIDEOBUF2 FRAMEWORK
 M:     Pawel Osciak <pawel@osciak.com>
@@ -8188,6 +8249,7 @@ L:        virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/char/virtio_console.c
 F:     include/linux/virtio_console.h
+F:     include/uapi/linux/virtio_console.h
 
 VIRTIO CORE, NET AND BLOCK DRIVERS
 M:     Rusty Russell <rusty@rustcorp.com.au>
@@ -8206,7 +8268,7 @@ L:        virtualization@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/vhost/
-F:     include/linux/vhost.h
+F:     include/uapi/linux/vhost.h
 
 VIA RHINE NETWORK DRIVER
 M:     Roger Luethi <rl@hellgate.ch>
@@ -8346,6 +8408,7 @@ S:        Maintained
 F:     Documentation/watchdog/
 F:     drivers/watchdog/
 F:     include/linux/watchdog.h
+F:     include/uapi/linux/watchdog.h
 
 WD7000 SCSI DRIVER
 M:     Miroslav Zagorac <zaga@fly.cc.fer.hr>
@@ -8371,9 +8434,9 @@ L:        wimax@linuxwimax.org
 S:     Supported
 W:     http://linuxwimax.org
 F:     Documentation/wimax/README.wimax
-F:     include/linux/wimax.h
 F:     include/linux/wimax/debug.h
 F:     include/net/wimax.h
+F:     include/uapi/linux/wimax.h
 F:     net/wimax/
 
 WISTRON LAPTOP BUTTON DRIVER
@@ -8459,7 +8522,7 @@ F:        Documentation/x86/
 F:     arch/x86/
 
 X86 PLATFORM DRIVERS
-M:     Matthew Garrett <mjg@redhat.com>
+M:     Matthew Garrett <matthew.garrett@nebula.com>
 L:     platform-driver-x86@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
 S:     Maintained
@@ -8491,6 +8554,7 @@ F:        drivers/*/xen-*front.c
 F:     drivers/xen/
 F:     arch/x86/include/asm/xen/
 F:     include/xen/
+F:     include/uapi/xen/
 
 XEN HYPERVISOR ARM
 M:     Stefano Stabellini <stefano.stabellini@eu.citrix.com>
index 6f07f4a28b479e01ef73371537794974e2ec4824..6fccf653177055cb4e250096d33df5eeb21a8671 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
-PATCHLEVEL = 7
+PATCHLEVEL = 8
 SUBLEVEL = 0
 EXTRAVERSION =
-NAME = Terrified Chipmunk
+NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -124,7 +124,7 @@ $(if $(KBUILD_OUTPUT),, \
 PHONY += $(MAKECMDGOALS) sub-make
 
 $(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
-       $(Q)@:
+       @:
 
 sub-make: FORCE
        $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
@@ -165,11 +165,12 @@ export srctree objtree VPATH
 # then ARCH is assigned, getting whatever value it gets normally, and 
 # SUBARCH is subsequently ignored.
 
-SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
+SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
+                                 -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                 -e s/sh[234].*/sh/ )
+                                 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
@@ -1027,11 +1028,14 @@ clean: rm-dirs  := $(CLEAN_DIRS)
 clean: rm-files := $(CLEAN_FILES)
 clean-dirs      := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples)
 
-PHONY += $(clean-dirs) clean archclean
+PHONY += $(clean-dirs) clean archclean vmlinuxclean
 $(clean-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
 
-clean: archclean
+vmlinuxclean:
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
+
+clean: archclean vmlinuxclean
 
 # mrproper - Delete all generated files, including .config
 #
@@ -1258,7 +1262,6 @@ scripts: ;
 endif # KBUILD_EXTMOD
 
 clean: $(clean-dirs)
-       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
        @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
index 8e9e3246b2b4e0f1a0b2218f5e49a8cacecb24d2..97fb7d0365d15505d500a126588f889a7647fcd8 100644 (file)
@@ -76,6 +76,15 @@ config OPTPROBES
        depends on KPROBES && HAVE_OPTPROBES
        depends on !PREEMPT
 
+config KPROBES_ON_FTRACE
+       def_bool y
+       depends on KPROBES && HAVE_KPROBES_ON_FTRACE
+       depends on DYNAMIC_FTRACE_WITH_REGS
+       help
+        If function tracer is enabled and the arch supports full
+        passing of pt_regs to function tracing, then kprobes can
+        optimize on top of function tracing.
+
 config UPROBES
        bool "Transparent user-space probes (EXPERIMENTAL)"
        depends on UPROBE_EVENT && PERF_EVENTS
@@ -158,6 +167,9 @@ config HAVE_KRETPROBES
 config HAVE_OPTPROBES
        bool
 
+config HAVE_KPROBES_ON_FTRACE
+       bool
+
 config HAVE_NMI_WATCHDOG
        bool
 #
@@ -291,12 +303,6 @@ config ARCH_WANT_OLD_COMPAT_IPC
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        bool
 
-config GENERIC_KERNEL_THREAD
-       bool
-
-config GENERIC_KERNEL_EXECVE
-       bool
-
 config HAVE_ARCH_SECCOMP_FILTER
        bool
        help
@@ -362,6 +368,9 @@ config MODULES_USE_ELF_REL
          Modules only use ELF REL relocations.  Modules with ELF RELA
          relocations will give an error.
 
+config GENERIC_SIGALTSTACK
+       bool
+
 #
 # ABI hall of shame
 #
index 5dd7f5db24d45e6d98961ae53cc4478224068d8b..9b504af2e9667168a0ed47143bcaac4c2517745f 100644 (file)
@@ -5,7 +5,6 @@ config ALPHA
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS
-       select HAVE_IRQ_WORK
        select HAVE_PCSPKR_PLATFORM
        select HAVE_PERF_EVENTS
        select HAVE_DMA_ATTRS
@@ -20,10 +19,9 @@ config ALPHA
        select GENERIC_CMOS_UPDATE
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_SIGALTSTACK
        help
          The Alpha is a 64-bit general-purpose processor designed and
          marketed by the Digital Equipment Corporation of blessed memory,
index c5ee7cbb2fcdf8cbdf928ae43beaaaf0be7e7102..6abd0af11f13513bf1a31c9fc7d66b31e58cafbb 100644 (file)
@@ -9,8 +9,8 @@
 #ifndef _ASM_AXP_PARPORT_H
 #define _ASM_AXP_PARPORT_H 1
 
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+static int parport_pc_find_isa_ports (int autoirq, int autodma);
+static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
        return parport_pc_find_isa_ports (autoirq, autodma);
 }
index df9a6cd748d500e4cf4d394b0c0b24fc4a4c955c..21128505ddbe31e006718355d90e791a2f9c532e 100644 (file)
@@ -8,6 +8,7 @@
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_user_stack_pointer() rdusp()
 
 #define task_pt_regs(task) \
   ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1)
index d6069ff3b1c8f270151be7abe34525ba5e60a4f4..b3396ee039b77df8ba4459dad3f00ac3a47be438 100644 (file)
@@ -15,7 +15,6 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 965bbfa59c658f7d0d6c6e7a4c116e05174d4bc5..dd4ca4bcbb4a0488cfd6c42334cb8dae97e2b16d 100644 (file)
@@ -84,12 +84,6 @@ typedef unsigned long sigset_t;
 #define SA_ONESHOT     SA_RESETHAND
 #define SA_NOMASK      SA_NODEFER
 
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    4096
 #define SIGSTKSZ       16384
 
index 14db93e4c8a83662d459a6ff1a818318dbc61eeb..dbc1760f418b4c26914a0bd6a05456d112f76d8b 100644 (file)
@@ -1139,6 +1139,7 @@ struct rusage32 {
 SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
 {
        struct rusage32 r;
+       cputime_t utime, stime;
 
        if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
                return -EINVAL;
@@ -1146,8 +1147,9 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
        memset(&r, 0, sizeof(r));
        switch (who) {
        case RUSAGE_SELF:
-               jiffies_to_timeval32(current->utime, &r.ru_utime);
-               jiffies_to_timeval32(current->stime, &r.ru_stime);
+               task_cputime(current, &utime, &stime);
+               jiffies_to_timeval32(utime, &r.ru_utime);
+               jiffies_to_timeval32(stime, &r.ru_stime);
                r.ru_minflt = current->min_flt;
                r.ru_majflt = current->maj_flt;
                break;
index ef757147cbf9ae2e63c74c44a7c01d9528db9e10..edb4e0097b75eff056ea89d37146ec2fe77eadc7 100644 (file)
@@ -59,13 +59,13 @@ struct pci_controller *pci_isa_hose;
  * Quirks.
  */
 
-static void __devinit quirk_isa_bridge(struct pci_dev *dev)
+static void quirk_isa_bridge(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_ISA << 8;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
 
-static void __devinit quirk_cypress(struct pci_dev *dev)
+static void quirk_cypress(struct pci_dev *dev)
 {
        /* The Notorious Cy82C693 chip.  */
 
@@ -104,7 +104,7 @@ static void __devinit quirk_cypress(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
 
 /* Called for each device after PCI setup is done. */
-static void __devinit pcibios_fixup_final(struct pci_dev *dev)
+static void pcibios_fixup_final(struct pci_dev *dev)
 {
        unsigned int class = dev->class >> 8;
 
@@ -198,8 +198,7 @@ subsys_initcall(pcibios_init);
 #ifdef ALPHA_RESTORE_SRM_SETUP
 static struct pdev_srm_saved_conf *srm_saved_configs;
 
-void __devinit
-pdev_save_srm_config(struct pci_dev *dev)
+void pdev_save_srm_config(struct pci_dev *dev)
 {
        struct pdev_srm_saved_conf *tmp;
        static int printed = 0;
@@ -241,8 +240,7 @@ pci_restore_srm_config(void)
 }
 #endif
 
-void __devinit
-pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev = bus->self;
 
index 336393c9c11f507bb14897de9c3ab7c74fd8a0c3..02d02c047f17e13d8c7714e0cd4d328ea2a2ce11 100644 (file)
@@ -122,12 +122,6 @@ SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
        return sigsuspend(&blocked);
 }
 
-asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
-       return do_sigaltstack(uss, uoss, rdusp());
-}
-
 /*
  * Do a signal return; undo the signal stack.
  */
@@ -418,9 +412,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __put_user(0, &frame->uc.uc_link);
        err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
-       err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-       err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+       err |= __save_altstack(&frame->uc.uc_stack, oldsp);
        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, 
                                set->sig[0], oldsp);
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
index a41ad90a97a692b039a2e8dbee2f57aa4b1a3300..9603bc234b479ce8ffbbbc961f8c0df9da97fff4 100644 (file)
@@ -68,7 +68,7 @@ enum ipi_message_type {
 };
 
 /* Set to a secondary's cpuid when it comes online.  */
-static int smp_secondary_alive __devinitdata = 0;
+static int smp_secondary_alive = 0;
 
 int smp_num_probed;            /* Internal processor count */
 int smp_num_cpus = 1;          /* Number that came online.  */
@@ -172,7 +172,7 @@ smp_callin(void)
 }
 
 /* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
-static int __devinit
+static int
 wait_for_txrdy (unsigned long cpumask)
 {
        unsigned long timeout;
@@ -468,7 +468,7 @@ smp_prepare_cpus(unsigned int max_cpus)
        smp_num_cpus = smp_num_probed;
 }
 
-void __devinit
+void
 smp_prepare_boot_cpu(void)
 {
 }
index 2533db280d9ba1f7ea642d4c947b5d532484a526..5cf4a481b8c57ea01e0709764f2e4c11ad26b863 100644 (file)
@@ -303,7 +303,7 @@ titan_late_init(void)
 
 }
 
-static int __devinit
+static int
 titan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 intline;
index 8c83d98424c7a68703261d8bbc496130c784c21c..9bbe760f2352dc86266ace6a8d4d4d5f08a26eda 100644 (file)
@@ -12,8 +12,6 @@ config ARM
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select GENERIC_PCI_IOMAP
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
@@ -38,7 +36,6 @@ config ARM
        select HAVE_GENERIC_HARDIRQS
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
        select HAVE_IDE if PCI || ISA || PCMCIA
-       select HAVE_IRQ_WORK
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
@@ -373,7 +370,6 @@ config ARCH_CNS3XXX
 config ARCH_CLPS711X
        bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
        select ARCH_REQUIRE_GPIOLIB
-       select ARCH_USES_GETTIMEOFFSET
        select AUTO_ZRELADDR
        select CLKDEV_LOOKUP
        select COMMON_CLK
@@ -1232,6 +1228,7 @@ config ARM_ERRATA_430973
 config ARM_ERRATA_458693
        bool "ARM errata: Processor deadlock when a false hazard is created"
        depends on CPU_V7
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 458693 Cortex-A8 (r2p0)
          erratum. For very specific sequences of memory operations, it is
@@ -1245,6 +1242,7 @@ config ARM_ERRATA_458693
 config ARM_ERRATA_460075
        bool "ARM errata: Data written to the L2 cache can be overwritten with stale data"
        depends on CPU_V7
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 460075 Cortex-A8 (r2p0)
          erratum. Any asynchronous access to the L2 cache may encounter a
@@ -1257,6 +1255,7 @@ config ARM_ERRATA_460075
 config ARM_ERRATA_742230
        bool "ARM errata: DMB operation may be faulty"
        depends on CPU_V7 && SMP
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 742230 Cortex-A9
          (r1p0..r2p2) erratum. Under rare circumstances, a DMB instruction
@@ -1269,6 +1268,7 @@ config ARM_ERRATA_742230
 config ARM_ERRATA_742231
        bool "ARM errata: Incorrect hazard handling in the SCU may lead to data corruption"
        depends on CPU_V7 && SMP
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 742231 Cortex-A9
          (r2p0..r2p2) erratum. Under certain conditions, specific to the
@@ -1319,6 +1319,7 @@ config PL310_ERRATA_727915
 config ARM_ERRATA_743622
        bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
        depends on CPU_V7
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 743622 Cortex-A9
          (r2p*) erratum. Under very rare conditions, a faulty
@@ -1332,6 +1333,7 @@ config ARM_ERRATA_743622
 config ARM_ERRATA_751472
        bool "ARM errata: Interrupted ICIALLUIS may prevent completion of broadcasted operation"
        depends on CPU_V7
+       depends on !ARCH_MULTIPLATFORM
        help
          This option enables the workaround for the 751472 Cortex-A9 (prior
          to r3p0) erratum. An interrupted ICIALLUIS operation may prevent the
index 49ca86e37b8d3c0cbe2b0e84a5ab3abeacee6926..fe4d9c3ad761c8dfaadce6e214d709417947f396 100644 (file)
@@ -44,7 +44,7 @@
 
 #else
 
-#include <mach/debug-macro.S>
+#include CONFIG_DEBUG_LL_INCLUDE
 
                .macro  writeb, ch, rb
                senduart \ch, \rb
index d077ef8426df07e78bf6b1de6bffd774f1d2db4a..5ebb44fe826a9b0b36d051272910a26775e5a16f 100644 (file)
@@ -42,11 +42,10 @@ dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-smdkv310.dtb \
        exynos4210-trats.dtb \
-       exynos5250-smdk5250.dtb \
-       exynos5440-ssdk5440.dtb \
        exynos4412-smdk4412.dtb \
        exynos5250-smdk5250.dtb \
-       exynos5250-snow.dtb
+       exynos5250-snow.dtb \
+       exynos5440-ssdk5440.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
        ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
@@ -156,6 +155,7 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
 dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
 
 targets += dtbs
+targets += $(dtb-y)
 endif
 
 # *.dtb used to be generated in the directory above. Clean out the
index 00044026ef1f470bd6bc6eb85b3409d2c0bf6556..9b82facb2561cfdb1cbc9cda25f5021668752e4a 100644 (file)
@@ -26,7 +26,7 @@
 
        memory {
                device_type = "memory";
-               reg = <0x00000000 0x20000000>; /* 512 MB */
+               reg = <0x00000000 0x40000000>; /* 1 GB */
        };
 
        soc {
index cf6c48a09eacf36e84b4caf4b83be0c35d0b22e8..4c0abe85405fe533ba0cedd41c95d4b9de4b4dc7 100644 (file)
                ranges;
 
                serial@d0012000 {
-                               compatible = "ns16550";
+                               compatible = "snps,dw-apb-uart";
                                reg = <0xd0012000 0x100>;
                                reg-shift = <2>;
                                interrupts = <41>;
+                               reg-io-width = <4>;
                                status = "disabled";
                };
                serial@d0012100 {
-                               compatible = "ns16550";
+                               compatible = "snps,dw-apb-uart";
                                reg = <0xd0012100 0x100>;
                                reg-shift = <2>;
                                interrupts = <42>;
+                               reg-io-width = <4>;
                                status = "disabled";
                };
 
index c45c7b4dc35230c52957fb1d32054a261e66e2ad..e041f42ed711b7e31fe93f2601fc153b2db6c2c0 100644 (file)
                reg = <0>;
                clocks = <&cpuclk 0>;
            };
-       }
+
+           cpu@1 {
+               device_type = "cpu";
+               compatible = "marvell,sheeva-v7";
+               reg = <1>;
+               clocks = <&cpuclk 1>;
+           };
+       };
 
        soc {
                pinctrl {
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <17>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>;
+                       interrupts = <87>, <88>, <89>;
                };
        };
 };
index a2aee5707377c3886a51217d40c102ed5e68c1e1..9e23bd8c9536d9b3d02c14a275efad5111d03f4a 100644 (file)
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>, <23>;
+                       interrupts = <87>, <88>, <89>, <90>;
                };
 
                gpio2: gpio@d0018180 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018180 0x40>,
-                           <0xd0018870 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018180 0x40>;
                        ngpios = <3>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <24>;
+                       interrupts = <91>;
+               };
+
+               ethernet@d0034000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0034000 0x2500>;
+                               interrupts = <14>;
+                               clocks = <&gateclk 1>;
+                               status = "disabled";
                };
        };
 };
index da03a129243a548853e5afa611b84f1b5fd73ebe..965966110e3850a46eb247ca115c28ef827aa984 100644 (file)
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>, <23>;
+                       interrupts = <87>, <88>, <89>, <90>;
                };
 
                gpio2: gpio@d0018180 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018180 0x40>,
-                           <0xd0018870 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018180 0x40>;
                        ngpios = <3>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <24>;
+                       interrupts = <91>;
+               };
+
+               ethernet@d0034000 {
+                               compatible = "marvell,armada-370-neta";
+                               reg = <0xd0034000 0x2500>;
+                               interrupts = <14>;
+                               clocks = <&gateclk 1>;
+                               status = "disabled";
                };
        };
  };
index 367aa3f94912ac9d78a35d22321c64667af406cf..2e37ef101c9035d65efefa83854ba79c742a8d94 100644 (file)
 
        soc {
                serial@d0012200 {
-                               compatible = "ns16550";
+                               compatible = "snps,dw-apb-uart";
                                reg = <0xd0012200 0x100>;
                                reg-shift = <2>;
                                interrupts = <43>;
+                               reg-io-width = <4>;
                                status = "disabled";
                };
                serial@d0012300 {
-                               compatible = "ns16550";
+                               compatible = "snps,dw-apb-uart";
                                reg = <0xd0012300 0x100>;
                                reg-shift = <2>;
                                interrupts = <44>;
+                               reg-io-width = <4>;
                                status = "disabled";
                };
 
                                status = "disabled";
                };
 
-               ethernet@d0034000 {
-                               compatible = "marvell,armada-370-neta";
-                               reg = <0xd0034000 0x2500>;
-                               interrupts = <14>;
-                               clocks = <&gateclk 1>;
-                               status = "disabled";
-               };
-
                xor@d0060900 {
                        compatible = "marvell,orion-xor";
                        reg = <0xd0060900 0x100
index e154f242c680e0ca3db90aabf823490dcb146607..222047f1ece9bfac7ed0562540bfaff483dc89e3 100644 (file)
 
        i2c@0 {
                compatible = "i2c-gpio";
-               gpios = <&pioA 23 0 /* sda */
-                        &pioA 24 0 /* scl */
+               gpios = <&pioA 25 0 /* sda */
+                        &pioA 26 0 /* scl */
                        >;
                i2c-gpio,sda-open-drain;
                i2c-gpio,scl-open-drain;
index 68bccf41a2c6a1855c6dfd87555faabf81306cb7..cb7bcc51608d81cd51bba98ec29455973ca9daf0 100644 (file)
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx-0 {
+                                               atmel,pins =
+                                                       <1 16 0x1 0x0   /* PB16 periph A */
+                                                        1 17 0x1 0x0   /* PB17 periph A */
+                                                        1 18 0x1 0x0>; /* PB18 periph A */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx-0 {
+                                               atmel,pins =
+                                                       <1 19 0x1 0x0   /* PB19 periph A */
+                                                        1 20 0x1 0x0   /* PB20 periph A */
+                                                        1 21 0x1 0x0>; /* PB21 periph A */
+                                       };
+                               };
+
                                pioA: gpio@fffff400 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff400 0x200>;
                                compatible = "atmel,at91rm9200-ssc";
                                reg = <0xfffbc000 0x4000>;
                                interrupts = <14 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
                                status = "disabled";
                        };
 
index 32ec62cf538585bf496187e0076afabd67c7be27..271d4de026e9df4ca1fc0114209e22f4da4d8cb5 100644 (file)
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx-0 {
+                                               atmel,pins =
+                                                       <1 0 0x2 0x0    /* PB0 periph B */
+                                                        1 1 0x2 0x0    /* PB1 periph B */
+                                                        1 2 0x2 0x0>;  /* PB2 periph B */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx-0 {
+                                               atmel,pins =
+                                                       <1 3 0x2 0x0    /* PB3 periph B */
+                                                        1 4 0x2 0x0    /* PB4 periph B */
+                                                        1 5 0x2 0x0>;  /* PB5 periph B */
+                                       };
+                               };
+
+                               ssc1 {
+                                       pinctrl_ssc1_tx: ssc1_tx-0 {
+                                               atmel,pins =
+                                                       <1 6 0x1 0x0    /* PB6 periph A */
+                                                        1 7 0x1 0x0    /* PB7 periph A */
+                                                        1 8 0x1 0x0>;  /* PB8 periph A */
+                                       };
+
+                                       pinctrl_ssc1_rx: ssc1_rx-0 {
+                                               atmel,pins =
+                                                       <1 9 0x1 0x0    /* PB9 periph A */
+                                                        1 10 0x1 0x0   /* PB10 periph A */
+                                                        1 11 0x1 0x0>; /* PB11 periph A */
+                                       };
+                               };
+
                                pioA: gpio@fffff200 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff200 0x200>;
                                compatible = "atmel,at91rm9200-ssc";
                                reg = <0xfff98000 0x4000>;
                                interrupts = <16 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
                                status = "disabled";
                        };
 
                                compatible = "atmel,at91rm9200-ssc";
                                reg = <0xfff9c000 0x4000>;
                                interrupts = <17 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
                                status = "disabled";
                        };
 
index 231858ffd850fec57eee5a91f06aee53f4c22f7f..6b1d4cab24c2a9e62537515991f109287dbc0091 100644 (file)
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx-0 {
+                                               atmel,pins =
+                                                       <3 0 0x1 0x0    /* PD0 periph A */
+                                                        3 1 0x1 0x0    /* PD1 periph A */
+                                                        3 2 0x1 0x0>;  /* PD2 periph A */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx-0 {
+                                               atmel,pins =
+                                                       <3 3 0x1 0x0    /* PD3 periph A */
+                                                        3 4 0x1 0x0    /* PD4 periph A */
+                                                        3 5 0x1 0x0>;  /* PD5 periph A */
+                                       };
+                               };
+
+                               ssc1 {
+                                       pinctrl_ssc1_tx: ssc1_tx-0 {
+                                               atmel,pins =
+                                                       <3 10 0x1 0x0   /* PD10 periph A */
+                                                        3 11 0x1 0x0   /* PD11 periph A */
+                                                        3 12 0x1 0x0>; /* PD12 periph A */
+                                       };
+
+                                       pinctrl_ssc1_rx: ssc1_rx-0 {
+                                               atmel,pins =
+                                                       <3 13 0x1 0x0   /* PD13 periph A */
+                                                        3 14 0x1 0x0   /* PD14 periph A */
+                                                        3 15 0x1 0x0>; /* PD15 periph A */
+                                       };
+                               };
+
                                pioA: gpio@fffff200 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff200 0x200>;
                                compatible = "atmel,at91sam9g45-ssc";
                                reg = <0xfff9c000 0x4000>;
                                interrupts = <16 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
                                status = "disabled";
                        };
 
                                compatible = "atmel,at91sam9g45-ssc";
                                reg = <0xfffa0000 0x4000>;
                                interrupts = <17 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
                                status = "disabled";
                        };
 
index e9efb34f437983370649fa096c006fe1638c1e01..80e29c605d4e53de1a8f948b5acb0eb975aee641 100644 (file)
@@ -28,6 +28,7 @@
                tcb1 = &tcb1;
                i2c0 = &i2c0;
                i2c1 = &i2c1;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx-0 {
+                                               atmel,pins =
+                                                       <0 24 0x2 0x0   /* PA24 periph B */
+                                                        0 25 0x2 0x0   /* PA25 periph B */
+                                                        0 26 0x2 0x0>; /* PA26 periph B */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx-0 {
+                                               atmel,pins =
+                                                       <0 27 0x2 0x0   /* PA27 periph B */
+                                                        0 28 0x2 0x0   /* PA28 periph B */
+                                                        0 29 0x2 0x0>; /* PA29 periph B */
+                                       };
+                               };
+
                                pioA: gpio@fffff400 {
                                        compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                        reg = <0xfffff400 0x200>;
                                status = "disabled";
                        };
 
+                       ssc0: ssc@f0010000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf0010000 0x4000>;
+                               interrupts = <28 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+                               status = "disabled";
+                       };
+
                        usart0: serial@f801c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf801c000 0x4000>;
index 40ac3a4eb1abc80a3560fbf6e33183bdd9dd5e72..8ecca6948d811f827e623e48f039238dad9fe6bf 100644 (file)
                                interrupts = <1 4 7>;
                        };
 
-                       ssc0: ssc@f0010000 {
-                               compatible = "atmel,at91sam9g45-ssc";
-                               reg = <0xf0010000 0x4000>;
-                               interrupts = <28 4 5>;
-                               status = "disabled";
-                       };
-
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
                                                atmel,pins =
                                                        <0 3 0x1 0x0>;  /* PA3 periph A */
                                        };
+
+                                       pinctrl_usart0_sck: usart0_sck-0 {
+                                               atmel,pins =
+                                                       <0 4 0x1 0x0>;  /* PA4 periph A */
+                                       };
                                };
 
                                usart1 {
 
                                        pinctrl_usart1_rts: usart1_rts-0 {
                                                atmel,pins =
-                                                       <3 27 0x3 0x0>; /* PC27 periph C */
+                                                       <2 27 0x3 0x0>; /* PC27 periph C */
                                        };
 
                                        pinctrl_usart1_cts: usart1_cts-0 {
                                                atmel,pins =
-                                                       <3 28 0x3 0x0>; /* PC28 periph C */
+                                                       <2 28 0x3 0x0>; /* PC28 periph C */
+                                       };
+
+                                       pinctrl_usart1_sck: usart1_sck-0 {
+                                               atmel,pins =
+                                                       <2 28 0x3 0x0>; /* PC29 periph C */
                                        };
                                };
 
 
                                        pinctrl_uart2_rts: uart2_rts-0 {
                                                atmel,pins =
-                                                       <0 0 0x2 0x0>;  /* PB0 periph B */
+                                                       <1 0 0x2 0x0>;  /* PB0 periph B */
                                        };
 
                                        pinctrl_uart2_cts: uart2_cts-0 {
                                                atmel,pins =
-                                                       <0 1 0x2 0x0>;  /* PB1 periph B */
+                                                       <1 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+
+                                       pinctrl_usart2_sck: usart2_sck-0 {
+                                               atmel,pins =
+                                                       <1 2 0x2 0x0>;  /* PB2 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 */
+                                                       <2 23 0x2 0x1   /* PC22 periph B with pullup */
+                                                        2 23 0x2 0x0>; /* PC23 periph B */
                                        };
 
                                        pinctrl_usart3_rts: usart3_rts-0 {
                                                atmel,pins =
-                                                       <3 24 0x2 0x0>; /* PC24 periph B */
+                                                       <2 24 0x2 0x0>; /* PC24 periph B */
                                        };
 
                                        pinctrl_usart3_cts: usart3_cts-0 {
                                                atmel,pins =
-                                                       <3 25 0x2 0x0>; /* PC25 periph B */
+                                                       <2 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+
+                                       pinctrl_usart3_sck: usart3_sck-0 {
+                                               atmel,pins =
+                                                       <2 26 0x2 0x0>; /* PC26 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 */
+                                                       <2 8 0x3 0x0    /* PC8 periph C */
+                                                        2 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 */
+                                                       <2 16 0x3 0x0   /* PC16 periph C */
+                                                        2 17 0x3 0x1>; /* PC17 periph C with pullup */
                                        };
                                };
 
 
                                        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 */
+                                                       <1 8 0x1 0x0    /* PB8 periph A */
+                                                        1 11 0x1 0x0   /* PB11 periph A */
+                                                        1 12 0x1 0x0   /* PB12 periph A */
+                                                        1 13 0x1 0x0   /* PB13 periph A */
+                                                        1 14 0x1 0x0   /* PB14 periph A */
+                                                        1 15 0x1 0x0   /* PB15 periph A */
+                                                        1 16 0x1 0x0   /* PB16 periph A */
+                                                        1 17 0x1 0x0>; /* PB17 periph A */
                                        };
                                };
 
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx-0 {
+                                               atmel,pins =
+                                                       <0 24 0x2 0x0   /* PA24 periph B */
+                                                        0 25 0x2 0x0   /* PA25 periph B */
+                                                        0 26 0x2 0x0>; /* PA26 periph B */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx-0 {
+                                               atmel,pins =
+                                                       <0 27 0x2 0x0   /* PA27 periph B */
+                                                        0 28 0x2 0x0   /* PA28 periph B */
+                                                        0 29 0x2 0x0>; /* PA29 periph B */
+                                       };
+                               };
+
                                pioA: gpio@fffff400 {
                                        compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                        reg = <0xfffff400 0x200>;
                                };
                        };
 
+                       ssc0: ssc@f0010000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf0010000 0x4000>;
+                               interrupts = <28 4 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+                               status = "disabled";
+                       };
+
                        mmc0: mmc@f0008000 {
                                compatible = "atmel,hsmci";
                                reg = <0xf0008000 0x600>;
index fddd1741743320fbdd29afbdb75133ae46673fa1..46c09801703655eb0a8fb28b8332cafa674f9b72 100644 (file)
@@ -96,8 +96,8 @@
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
index 2efd9c891bc91f85522a6158854fd14e89b7f65f..63f2fbcfe8196823a93ac5f74f2eadebd3ae52f7 100644 (file)
                        gpio-bank = <8>;
                };
 
-               pinctrl {
+               pinctrl@80157000 {
+                       // This is actually the PRCMU base address
+                       reg = <0x80157000 0x2000>;
                        compatible = "stericsson,nmk_pinctrl";
                };
 
index fed7d3f9f431071af027d72a12c92dcb6f365943..cdee96fca6e25fec9a0e24208344c03621298721 100644 (file)
 };
 
 &uart0 { status = "okay"; };
-&sdio0 { status = "okay"; };
 &sata0 { status = "okay"; };
 &i2c0 { status = "okay"; };
 
+&sdio0 {
+       status = "okay";
+       /* sdio0 card detect is connected to wrong pin on CuBox */
+       cd-gpios = <&gpio0 12 1>;
+};
+
 &spi0 {
        status = "okay";
 
 };
 
 &pinctrl {
-       pinctrl-0 = <&pmx_gpio_18>;
+       pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>;
        pinctrl-names = "default";
 
+       pmx_gpio_12: pmx-gpio-12 {
+               marvell,pins = "mpp12";
+               marvell,function = "gpio";
+       };
+
        pmx_gpio_18: pmx-gpio-18 {
                marvell,pins = "mpp18";
                marvell,function = "gpio";
index f3f7e9d8adca4862c92cd22d00eb6d15267a8a8c..42eac1ff3cc82a02c5f52fddba478e76d83548d8 100644 (file)
                pinctrl: pinctrl@d0200 {
                        compatible = "marvell,dove-pinctrl";
                        reg = <0xd0200 0x10>;
+                       clocks = <&gate_clk 22>;
                };
 
                spi0: spi@10600 {
index 46477ac1de99fd4e148c6b8593c1c6f2502eff98..139b40cc3a23e63087fc6154ca6e7f79ed828fae 100644 (file)
@@ -32,6 +32,7 @@
 
                cpu@0 {
                        compatible = "arm,cortex-a15";
+                       device_type = "cpu";
                        reg = <0>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
@@ -39,6 +40,7 @@
 
                cpu@1 {
                        compatible = "arm,cortex-a15";
+                       device_type = "cpu";
                        reg = <1>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
@@ -46,6 +48,7 @@
 
                cpu@2 {
                        compatible = "arm,cortex-a15";
+                       device_type = "cpu";
                        reg = <2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
@@ -53,6 +56,7 @@
 
                cpu@3 {
                        compatible = "arm,cortex-a15";
+                       device_type = "cpu";
                        reg = <3>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
index 9b23a8255e39a148eecdd18e04391f4a2f6529f0..f63490707f3a56646c8cc09edd471009d6644b14 100644 (file)
@@ -26,7 +26,7 @@
        };
 
        chosen {
-               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
        };
 
        sdhci@12530000 {
index 942d5761ca971dd7317c8398d5ddaddd0b0fce98..e05b18f3c33d67d6e5202083bf60f8aa65b4344f 100644 (file)
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
index 2e3b6efaf1a2632062fd93a8ca7d0eec792a9c0c..3acf594ea60bda97bc5e53187011455bf86b0c5b 100644 (file)
 
        hdmi {
                compatible = "samsung,exynos5-hdmi";
-               reg = <0x14530000 0x100000>;
+               reg = <0x14530000 0x70000>;
                interrupts = <0 95 0>;
        };
 
index 921c83cf694f57fe7138fb8a703e022133f5f480..81e2c964a900f8a74d5efbac4aca73491bcc719a 100644 (file)
@@ -21,7 +21,7 @@
        };
 
        chosen {
-               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x81000000,8M console=ttySAC2,115200 init=/linuxrc";
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x81000000,8M console=ttySAC0,115200 init=/linuxrc";
        };
 
        spi {
index a9ae5d32e80dfa057f01bb49dacb728035480e19..5927a8df562536550b101669f45978f33907e0ac 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu@0 {
+               cpu@900 {
                        compatible = "arm,cortex-a9";
-                       reg = <0>;
+                       device_type = "cpu";
+                       reg = <0x900>;
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
                };
 
-               cpu@1 {
+               cpu@901 {
                        compatible = "arm,cortex-a9";
-                       reg = <1>;
+                       device_type = "cpu";
+                       reg = <0x901>;
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
                };
 
-               cpu@2 {
+               cpu@902 {
                        compatible = "arm,cortex-a9";
-                       reg = <2>;
+                       device_type = "cpu";
+                       reg = <0x902>;
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
                };
 
-               cpu@3 {
+               cpu@903 {
                        compatible = "arm,cortex-a9";
-                       reg = <3>;
+                       device_type = "cpu";
+                       reg = <0x903>;
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
index 7c43b8e70b9fcb1c29da27a059f658440ddec246..e7484e4ea659ca261149476a6e7fc6c07dd85690 100644 (file)
                                hog_pins_a: hog@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
-                                               0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+                                               0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
                                        >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
                                };
 
-                               led_pin_gpio0_17: led_gpio0_17@0 {
+                               led_pin_gpio2_1: led_gpio2_1@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
-                                               0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
+                                               0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
                                        >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
        leds {
                compatible = "gpio-leds";
                pinctrl-names = "default";
-               pinctrl-0 = <&led_pin_gpio0_17>;
+               pinctrl-0 = <&led_pin_gpio2_1>;
 
                user {
                        label = "green";
index 24731cb78e8ecd72616d272aaeff0e224807e0cc..7f67402328d377aa213a579860ff934db4e2483f 100644 (file)
@@ -14,7 +14,7 @@
 
 / {
        model = "Buglabs i.MX31 Bug 1.x";
-       compatible = "fsl,imx31-bug", "fsl,imx31";
+       compatible = "buglabs,imx31-bug", "fsl,imx31";
 
        memory {
                reg = <0x80000000 0x8000000>; /* 128M */
index 552aed4ff9823e63bdfdca1df059cff82b7f2baa..edc3f1eb6699238b776a1affc9f647103dfdc4ca 100644 (file)
                                compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
                                reg = <0x53fcc000 0x4000>;
                                interrupts = <83>;
-                               clocks = <&clks 158>, <&clks 157>;
+                               clocks = <&clks 87>, <&clks 86>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
index 9ae2004d567531422ad64c4321e97849da0714e6..4ccea2130a6cd2b42029522ac2c8c527fba2728f 100644 (file)
@@ -39,6 +39,7 @@
                        #size-cells = <0>;
                        interrupts = <32>;
                        clock-frequency = <100000>;
+                       clocks = <&gate_clk 7>;
                        status = "disabled";
                };
        };
index 9bc6785ad228f9522c73ad0df60befa33ef798a4..77d21abfcdf73a3430f529be076cb4f17cd9e13d 100644 (file)
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        chosen {
@@ -6,6 +7,21 @@
        };
 
        ocp@f1000000 {
+               pinctrl: pinctrl@10000 {
+                       pinctrl-0 = < &pmx_spi &pmx_twsi0 &pmx_uart0
+                                       &pmx_ns2_sata0 &pmx_ns2_sata1>;
+                       pinctrl-names = "default";
+
+                       pmx_ns2_sata0: pmx-ns2-sata0 {
+                               marvell,pins = "mpp21";
+                               marvell,function = "sata0";
+                       };
+                       pmx_ns2_sata1: pmx-ns2-sata1 {
+                               marvell,pins = "mpp20";
+                               marvell,function = "sata1";
+                       };
+               };
+
                serial@12000 {
                        clock-frequency = <166666667>;
                        status = "okay";
index c0de5a7f660d976269087e7f8e888b141adf8468..cd15452a52a62024f9518a5abdb677ab8292fd9c 100644 (file)
                        gpios = <&gpio1 16 1>;
                };
        };
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               sata0_power: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "SATA0 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 4 0>;
+               };
+       };
 };
index 7735cee4a9c6fb8a34ffb001eed617137a0fef6c..d6ab442b7011e8777efa036b551aa8e8ef438e49 100644 (file)
@@ -36,6 +36,7 @@
                        reg = <0x10100 0x40>;
                        ngpios = <32>;
                        interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <35>, <36>, <37>, <38>;
                };
 
@@ -46,6 +47,7 @@
                        reg = <0x10140 0x40>;
                        ngpios = <18>;
                        interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <39>, <40>, <41>;
                };
 
                        compatible = "marvell,orion-ehci";
                        reg = <0x50000 0x1000>;
                        interrupts = <19>;
+                       clocks = <&gate_clk 3>;
                        status = "okay";
                };
 
index e8814fe0e27760b475b0c850880e44b0923a8b50..b4dc3ed9a3ecc95949d07e79889e53a8600d66ee 100644 (file)
@@ -48,6 +48,8 @@
 
                        macb0: ethernet@fffc4000 {
                                phy-mode = "mii";
+                               pinctrl-0 = <&pinctrl_macb_rmii
+                                            &pinctrl_macb_rmii_mii_alt>;
                                status = "okay";
                        };
 
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
new file mode 100644 (file)
index 0000000..5cab825
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Stefan Roese
+ * Stefan Roese <sr@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+
+/ {
+       model = "Cubietech Cubieboard";
+       compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10";
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       chosen {
+               bootargs = "earlyprintk console=ttyS0,115200";
+       };
+
+       soc {
+               uart0: uart@01c28000 {
+                       status = "okay";
+               };
+
+               uart1: uart@01c28400 {
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
new file mode 100644 (file)
index 0000000..e61fdd4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Stefan Roese
+ * Stefan Roese <sr@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "sunxi.dtsi"
+
+/ {
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/sun4i-cubieboard.dts b/arch/arm/boot/dts/sun4i-cubieboard.dts
deleted file mode 100644 (file)
index 5cab825..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <sr@denx.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-/include/ "sun4i-a10.dtsi"
-
-/ {
-       model = "Cubietech Cubieboard";
-       compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10";
-
-       aliases {
-               serial0 = &uart0;
-               serial1 = &uart1;
-       };
-
-       chosen {
-               bootargs = "earlyprintk console=ttyS0,115200";
-       };
-
-       soc {
-               uart0: uart@01c28000 {
-                       status = "okay";
-               };
-
-               uart1: uart@01c28400 {
-                       status = "okay";
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/sun4i.dtsi b/arch/arm/boot/dts/sun4i.dtsi
deleted file mode 100644 (file)
index e61fdd4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <sr@denx.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/include/ "sunxi.dtsi"
-
-/ {
-       memory {
-               reg = <0x40000000 0x80000000>;
-       };
-};
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
new file mode 100644 (file)
index 0000000..498a091
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun5i-a13.dtsi"
+
+/ {
+       model = "Olimex A13-Olinuxino";
+       compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
+
+       chosen {
+               bootargs = "earlyprintk console=ttyS0,115200";
+       };
+
+       soc {
+               uart1: uart@01c28400 {
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
new file mode 100644 (file)
index 0000000..59a2d26
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "sunxi.dtsi"
+
+/ {
+       memory {
+               reg = <0x40000000 0x20000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/sun5i-olinuxino.dts b/arch/arm/boot/dts/sun5i-olinuxino.dts
deleted file mode 100644 (file)
index 498a091..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-/include/ "sun5i-a13.dtsi"
-
-/ {
-       model = "Olimex A13-Olinuxino";
-       compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
-
-       chosen {
-               bootargs = "earlyprintk console=ttyS0,115200";
-       };
-
-       soc {
-               uart1: uart@01c28400 {
-                       status = "okay";
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
deleted file mode 100644 (file)
index 59a2d26..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/include/ "sunxi.dtsi"
-
-/ {
-       memory {
-               reg = <0x40000000 0x20000000>;
-       };
-};
index 8bbc2bfef221a2449da1211b2b880aeb07364f94..8b36abea9f2edba7cc4390693324c829142b8a76 100644 (file)
                };
 
                uart0: uart@01c28000 {
-                       compatible = "ns8250";
+                       compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
                        interrupts = <1>;
                        reg-shift = <2>;
+                       reg-io-width = <4>;
                        clock-frequency = <24000000>;
                        status = "disabled";
                };
 
                uart1: uart@01c28400 {
-                       compatible = "ns8250";
+                       compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
                        interrupts = <2>;
                        reg-shift = <2>;
+                       reg-io-width = <4>;
                        clock-frequency = <24000000>;
                        status = "disabled";
                };
index 63411b036932011e6fe1b8764c7fa9ecdd0ee48f..ed0bc9546837d8f40f3bf873e20055717c5d1451 100644 (file)
                interrupts = <11>;
        };
 
+       watchdog {
+               compatible = "ti,twl4030-wdt";
+       };
+
        vdac: regulator-vdac {
                compatible = "ti,twl4030-vdac";
                regulator-min-microvolt = <1800000>;
index 1fc405a9ecfb0a4e6cacd94ba9442d6ce75575fa..cf8071ad22d5fb5acfd1382f82d16e606c28e068 100644 (file)
@@ -45,7 +45,6 @@
                        reg = <1>;
                };
 
-/* A7s disabled till big.LITTLE patches are available...
                cpu2: cpu@2 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
@@ -63,7 +62,6 @@
                        compatible = "arm,cortex-a7";
                        reg = <0x102>;
                };
-*/
        };
 
        memory@80000000 {
index 36ae03a3f5d1a07527145ff545ded90888ba0a7b..87dfa9026c5bdcb1ba9d57d718d00da671c8fe21 100644 (file)
@@ -351,6 +351,25 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
        irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static u8 gic_get_cpumask(struct gic_chip_data *gic)
+{
+       void __iomem *base = gic_data_dist_base(gic);
+       u32 mask, i;
+
+       for (i = mask = 0; i < 32; i += 4) {
+               mask = readl_relaxed(base + GIC_DIST_TARGET + i);
+               mask |= mask >> 16;
+               mask |= mask >> 8;
+               if (mask)
+                       break;
+       }
+
+       if (!mask)
+               pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
+
+       return mask;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic)
 {
        unsigned int i;
@@ -369,7 +388,9 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
        /*
         * Set all global interrupts to this CPU only.
         */
-       cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0);
+       cpumask = gic_get_cpumask(gic);
+       cpumask |= cpumask << 8;
+       cpumask |= cpumask << 16;
        for (i = 32; i < gic_irqs; i += 4)
                writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
@@ -400,7 +421,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
         * Get what the GIC says our CPU mask is.
         */
        BUG_ON(cpu >= NR_GIC_CPU_IF);
-       cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0);
+       cpu_mask = gic_get_cpumask(gic);
        gic_cpu_map[cpu] = cpu_mask;
 
        /*
index 9173d112ea0156a31b2f2769731a3b80be7de680..e57d7e5bf96a1a16681ed1ba73bf31c291ba3da5 100644 (file)
@@ -686,8 +686,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
  *     %-EINVAL        no platform data passed
  *     %0              successful.
  */
-static int __devinit
-__sa1111_probe(struct device *me, struct resource *mem, int irq)
+static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
 {
        struct sa1111_platform_data *pd = me->platform_data;
        struct sa1111 *sachip;
@@ -1011,7 +1010,7 @@ static int sa1111_resume(struct platform_device *dev)
 #define sa1111_resume  NULL
 #endif
 
-static int __devinit sa1111_probe(struct platform_device *pdev)
+static int sa1111_probe(struct platform_device *pdev)
 {
        struct resource *mem;
        int irq;
index 0c616d5fcb0f7bf3a6811ea08f7fd2dcc63c819b..a5c3dc38aa1818d29285d16789df7788bd83aa4c 100644 (file)
@@ -176,7 +176,7 @@ static int scoop_resume(struct platform_device *dev)
 #define scoop_resume   NULL
 #endif
 
-static int __devinit scoop_probe(struct platform_device *pdev)
+static int scoop_probe(struct platform_device *pdev)
 {
        struct scoop_dev *devptr;
        struct scoop_config *inf;
@@ -243,7 +243,7 @@ err_ioremap:
        return ret;
 }
 
-static int __devexit scoop_remove(struct platform_device *pdev)
+static int scoop_remove(struct platform_device *pdev)
 {
        struct scoop_dev *sdev = platform_get_drvdata(pdev);
        int ret;
@@ -268,7 +268,7 @@ static int __devexit scoop_remove(struct platform_device *pdev)
 
 static struct platform_driver scoop_driver = {
        .probe          = scoop_probe,
-       .remove         = __devexit_p(scoop_remove),
+       .remove         = scoop_remove,
        .suspend        = scoop_suspend,
        .resume         = scoop_resume,
        .driver         = {
index e4df17ca90c7114efaca806977d153a87b7ad5ba..8f324b99416e46548ce2bdb9a02edac2340835bd 100644 (file)
@@ -206,6 +206,7 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
                                struct device_node *node)
 {
        struct vic_device *v;
+       int i;
 
        if (vic_id >= ARRAY_SIZE(vic_devices)) {
                printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
@@ -220,6 +221,10 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
        vic_id++;
        v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
                                          &vic_irqdomain_ops, v);
+       /* create an IRQ mapping for each valid IRQ */
+       for (i = 0; i < fls(valid_sources); i++)
+               if (valid_sources & (1 << i))
+                       irq_create_mapping(v->domain, i);
 }
 
 static void vic_ack_irq(struct irq_data *d)
@@ -416,9 +421,9 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
                return -EIO;
 
        /*
-        * Passing -1 as first IRQ makes the simple domain allocate descriptors
+        * Passing 0 as first IRQ makes the simple domain allocate descriptors
         */
-       __vic_init(regs, -1, ~0, ~0, node);
+       __vic_init(regs, 0, ~0, ~0, node);
 
        return 0;
 }
index b175577d7abb5aec9541461e35407f0f9059c04a..1ea959019fcd3c19295b8a27a458198100344fe6 100644 (file)
@@ -19,6 +19,7 @@ CONFIG_SOC_AT91SAM9260=y
 CONFIG_SOC_AT91SAM9263=y
 CONFIG_SOC_AT91SAM9G45=y
 CONFIG_SOC_AT91SAM9X5=y
+CONFIG_SOC_AT91SAM9N12=y
 CONFIG_MACH_AT91SAM_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_TIMER_HZ=128
@@ -31,7 +32,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
+CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
 CONFIG_KEXEC=y
 CONFIG_AUTO_ZRELADDR=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index dbea6f4efe9f7775879032ddf4ff3444a7a80a63..2eeff1e64b6e15d77f76aa75eb7c6152d3cf800f 100644 (file)
@@ -6,6 +6,7 @@ CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_SOCFPGA=y
+CONFIG_ARCH_SUNXI=y
 # CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
 CONFIG_ARM_ERRATA_754322=y
 CONFIG_SMP=y
index a702fb345c01e5693d82f22d0eeb5fc2d7c88b2a..b5bc96cb65a79d87c2f65814e9cc4fecd69e4df1 100644 (file)
@@ -33,9 +33,7 @@ CONFIG_MVNETA=y
 CONFIG_MARVELL_PHY=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_I2C=y
-CONFIG_I2C_MV64XXX=y
+CONFIG_SERIAL_8250_DW=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_USB_SUPPORT is not set
index a1dc5c071e71250879e27ae3c92632a3409375cb..82ce8d738fa1c8a6f4ba730828867de22aa392c3 100644 (file)
@@ -65,6 +65,8 @@ CONFIG_MAC80211_RC_PID=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_CONNECTOR=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -132,9 +134,11 @@ CONFIG_POWER_SUPPLY=y
 CONFIG_WATCHDOG=y
 CONFIG_OMAP_WATCHDOG=y
 CONFIG_TWL4030_WATCHDOG=y
+CONFIG_MFD_TPS65217=y
 CONFIG_REGULATOR_TWL4030=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
+CONFIG_REGULATOR_TPS65217=y
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
@@ -170,6 +174,7 @@ CONFIG_SND_DEBUG=y
 CONFIG_SND_USB_AUDIO=m
 CONFIG_SND_SOC=m
 CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
 CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
index 73cf03aa981e1b665d9a40f4f80847335ca49441..1c4df27f93322604398d70f9c585332e97374b10 100644 (file)
@@ -37,7 +37,7 @@
  */
 #define PAGE_OFFSET            UL(CONFIG_PAGE_OFFSET)
 #define TASK_SIZE              (UL(CONFIG_PAGE_OFFSET) - UL(0x01000000))
-#define TASK_UNMAPPED_BASE     (UL(CONFIG_PAGE_OFFSET) / 3)
+#define TASK_UNMAPPED_BASE     ALIGN(TASK_SIZE / 3, SZ_16M)
 
 /*
  * The maximum size of a 26-bit user space task.
index 4eb6d005ffaa4b625c9f86fc8532b046d0cf1f6a..86dff32a073755f46c40c379d27a29f9aab5b829 100644 (file)
@@ -7,8 +7,14 @@
 
 #ifndef __ASSEMBLER__
 unsigned int scu_get_core_count(void __iomem *);
-void scu_enable(void __iomem *);
 int scu_power_mode(void __iomem *, unsigned int);
+
+#ifdef CONFIG_SMP
+void scu_enable(void __iomem *scu_base);
+#else
+static inline void scu_enable(void __iomem *scu_base) {}
+#endif
+
 #endif
 
 #endif
index 7cd13cc62624b223873d654b4c8acf40ddd9f4f2..21a2700d295715faabf5083d7dfde05f7628cfa8 100644 (file)
@@ -41,7 +41,6 @@
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 921c57fdc52e13802076b632f3b571266703f06b..33073bdcf091beaf32611cb93dffeb363233b45e 100644 (file)
@@ -87,13 +87,6 @@ typedef unsigned long sigset_t;
 #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
 
index 9b722612553ddbe3c03257b0e3d3fc8b6d939939..379cf32923908365853c7f9eafc6a5fdba54c76c 100644 (file)
@@ -78,7 +78,7 @@ void pcibios_report_status(u_int status_mask, int warn)
  * Bug 3 is responsible for the sound DMA grinding to a halt.  We now
  * live with bug 2.
  */
-static void __devinit pci_fixup_83c553(struct pci_dev *dev)
+static void pci_fixup_83c553(struct pci_dev *dev)
 {
        /*
         * Set memory region to start at address 0, and enable IO
@@ -130,7 +130,7 @@ static void __devinit pci_fixup_83c553(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553);
 
-static void __devinit pci_fixup_unassign(struct pci_dev *dev)
+static void pci_fixup_unassign(struct pci_dev *dev)
 {
        dev->resource[0].end -= dev->resource[0].start;
        dev->resource[0].start = 0;
@@ -142,7 +142,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F,
  * if it is the host bridge by marking it as such.  These resources are of
  * no consequence to the PCI layer (they are handled elsewhere).
  */
-static void __devinit pci_fixup_dec21285(struct pci_dev *dev)
+static void pci_fixup_dec21285(struct pci_dev *dev)
 {
        int i;
 
@@ -161,7 +161,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_d
 /*
  * PCI IDE controllers use non-standard I/O port decoding, respect it.
  */
-static void __devinit pci_fixup_ide_bases(struct pci_dev *dev)
+static void pci_fixup_ide_bases(struct pci_dev *dev)
 {
        struct resource *r;
        int i;
@@ -182,7 +182,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 /*
  * Put the DEC21142 to sleep
  */
-static void __devinit pci_fixup_dec21142(struct pci_dev *dev)
+static void pci_fixup_dec21142(struct pci_dev *dev)
 {
        pci_write_config_dword(dev, 0x40, 0x80000000);
 }
@@ -204,7 +204,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, pci_fixup_d
  * functional.  However, The CY82C693U _does not work_ in bus
  * master mode without locking the PCI bus solid.
  */
-static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
+static void pci_fixup_cy82c693(struct pci_dev *dev)
 {
        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
                u32 base0, base1;
@@ -254,7 +254,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
 
-static void __devinit pci_fixup_it8152(struct pci_dev *dev)
+static void pci_fixup_it8152(struct pci_dev *dev)
 {
        int i;
        /* fixup for ITE 8152 devices */
@@ -361,9 +361,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
                bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
 }
-#ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_fixup_bus);
-#endif
 
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
@@ -380,7 +378,7 @@ EXPORT_SYMBOL(pcibios_fixup_bus);
  * PCI standard swizzle is implemented on plug-in cards and Cardbus based
  * PCI extenders, so it can not be ignored.
  */
-static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
 {
        struct pci_sys_data *sys = dev->sysdata;
        int slot, oldpin = *pin;
index 6809200c31fb73349df3af95cd737c0e70293ada..14f7c3b14632e22c02632faeaca9f07adcbc232f 100644 (file)
@@ -100,12 +100,14 @@ ENTRY(printch)
                b       1b
 ENDPROC(printch)
 
+#ifdef CONFIG_MMU
 ENTRY(debug_ll_addr)
                addruart r2, r3, ip
                str     r2, [r0]
                str     r3, [r1]
                mov     pc, lr
 ENDPROC(debug_ll_addr)
+#endif
 
 #else
 
index 36d20bd501200880dad2a662a8a3d29f15506e5c..9b6de8c988f30e67af04325c081c8d0809e9f663 100644 (file)
@@ -339,7 +339,7 @@ static struct miscdevice etb_miscdev = {
        .fops = &etb_fops,
 };
 
-static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
+static int etb_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct tracectx *t = &tracer;
        int ret = 0;
@@ -531,7 +531,7 @@ static ssize_t trace_mode_store(struct kobject *kobj,
 static struct kobj_attribute trace_mode_attr =
        __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
 
-static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
+static int etm_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct tracectx *t = &tracer;
        int ret = 0;
index 4eee351f4668e2bbee54c3771a5389ce8900c10c..486a15ae901192fa3e26539b3d2b7003a1528e0f 100644 (file)
@@ -246,6 +246,7 @@ __create_page_tables:
 
        /*
         * Then map boot params address in r2 if specified.
+        * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
         */
        mov     r0, r2, lsr #SECTION_SHIFT
        movs    r0, r0, lsl #SECTION_SHIFT
@@ -253,6 +254,8 @@ __create_page_tables:
        addne   r3, r3, #PAGE_OFFSET
        addne   r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
        orrne   r6, r7, r0
+       strne   r6, [r3], #1 << PMD_ORDER
+       addne   r6, r6, #1 << SECTION_SHIFT
        strne   r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
@@ -331,7 +334,7 @@ ENTRY(secondary_startup)
         * as it has already been validated by the primary processor.
         */
 #ifdef CONFIG_ARM_VIRT_EXT
-       bl      __hyp_stub_install
+       bl      __hyp_stub_install_secondary
 #endif
        safe_svcmode_maskall r9
 
index 65b2417aebce0beed61a7510702168cad2d9c3dc..1315c4ccfa563a04928347ec560ed618dcd3f958 100644 (file)
@@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary)
         * immediately.
         */
        compare_cpu_mode_with_primary   r4, r5, r6, r7
-       bxne    lr
+       movne   pc, lr
 
        /*
         * Once we have given up on one CPU, we do not try to install the
@@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary)
         */
 
        cmp     r4, #HYP_MODE
-       bxne    lr                      @ give up if the CPU is not in HYP mode
+       movne   pc, lr                  @ give up if the CPU is not in HYP mode
 
 /*
  * Configure HSCTLR to set correct exception endianness/instruction set
@@ -120,7 +120,8 @@ ENTRY(__hyp_stub_install_secondary)
  * Eventually, CPU-specific code might be needed -- assume not for now
  *
  * This code relies on the "eret" instruction to synchronize the
- * various coprocessor accesses.
+ * various coprocessor accesses. This is done when we switch to SVC
+ * (see safe_svcmode_maskall).
  */
        @ Now install the hypervisor stub:
        adr     r7, __hyp_stub_vectors
@@ -155,14 +156,7 @@ THUMB(     orr     r7, #(1 << 30)  )       @ HSCTLR.TE
 1:
 #endif
 
-       bic     r7, r4, #MODE_MASK
-       orr     r7, r7, #SVC_MODE
-THUMB( orr     r7, r7, #PSR_T_BIT      )
-       msr     spsr_cxsf, r7           @ This is SPSR_hyp.
-
-       __MSR_ELR_HYP(14)               @ msr elr_hyp, lr
-       __ERET                          @ return, switching to SVC mode
-                                       @ The boot CPU mode is left in r4.
+       bx      lr                      @ The boot CPU mode is left in r4.
 ENDPROC(__hyp_stub_install_secondary)
 
 __hyp_stub_do_trap:
@@ -200,7 +194,7 @@ ENDPROC(__hyp_get_vectors)
        @ fall through
 ENTRY(__hyp_set_vectors)
        __HVC(0)
-       bx      lr
+       mov     pc, lr
 ENDPROC(__hyp_set_vectors)
 
 #ifndef ZIMAGE
index 9a4f6307a01620996f08c29ebec7c03d05ff05fd..5f6620684e255cb7e8e5b34d36e31771682e8e40 100644 (file)
@@ -132,7 +132,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
        return 0;
 }
 
-static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
+static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
        int cpu;
        for_each_possible_cpu(cpu) {
@@ -178,7 +178,7 @@ static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
 /*
  * PMU platform driver and devicetree bindings.
  */
-static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
+static struct of_device_id cpu_pmu_of_device_ids[] = {
        {.compatible = "arm,cortex-a15-pmu",    .data = armv7_a15_pmu_init},
        {.compatible = "arm,cortex-a9-pmu",     .data = armv7_a9_pmu_init},
        {.compatible = "arm,cortex-a8-pmu",     .data = armv7_a8_pmu_init},
@@ -190,7 +190,7 @@ static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
        {},
 };
 
-static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
+static struct platform_device_id cpu_pmu_plat_device_ids[] = {
        {.name = "arm-pmu"},
        {},
 };
@@ -198,7 +198,7 @@ static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
 /*
  * CPU PMU identification and probing.
  */
-static int __devinit probe_current_pmu(struct arm_pmu *pmu)
+static int probe_current_pmu(struct arm_pmu *pmu)
 {
        int cpu = get_cpu();
        unsigned long cpuid = read_cpuid_id();
@@ -252,7 +252,7 @@ static int __devinit probe_current_pmu(struct arm_pmu *pmu)
        return ret;
 }
 
-static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
+static int cpu_pmu_device_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id;
        int (*init_fn)(struct arm_pmu *);
index f3e22ff8b6a2c2bc5f620e9b8a389cb17b56a136..041d0526a2885fb424bd58716af0c10e29e95419 100644 (file)
@@ -653,7 +653,7 @@ static int armv6_map_event(struct perf_event *event)
                                &armv6_perf_cache_map, 0xFF);
 }
 
-static int __devinit armv6pmu_init(struct arm_pmu *cpu_pmu)
+static int armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
        cpu_pmu->name           = "v6";
        cpu_pmu->handle_irq     = armv6pmu_handle_irq;
@@ -685,7 +685,7 @@ static int armv6mpcore_map_event(struct perf_event *event)
                                &armv6mpcore_perf_cache_map, 0xFF);
 }
 
-static int __devinit armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
        cpu_pmu->name           = "v6mpcore";
        cpu_pmu->handle_irq     = armv6pmu_handle_irq;
index 7d0cce85d17e56ea1049403b38b4d4532dc7d6b1..4fbc757d9cffd6daebd6dd070047d2cfe1ff5e06 100644 (file)
@@ -1226,7 +1226,7 @@ static void armv7pmu_init(struct arm_pmu *cpu_pmu)
        cpu_pmu->max_period     = (1LLU << 32) - 1;
 };
 
-static u32 __devinit armv7_read_num_pmnc_events(void)
+static u32 armv7_read_num_pmnc_events(void)
 {
        u32 nb_cnt;
 
@@ -1237,7 +1237,7 @@ static u32 __devinit armv7_read_num_pmnc_events(void)
        return nb_cnt + 1;
 }
 
-static int __devinit armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
        armv7pmu_init(cpu_pmu);
        cpu_pmu->name           = "ARMv7 Cortex-A8";
@@ -1246,7 +1246,7 @@ static int __devinit armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
        return 0;
 }
 
-static int __devinit armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
        armv7pmu_init(cpu_pmu);
        cpu_pmu->name           = "ARMv7 Cortex-A9";
@@ -1255,7 +1255,7 @@ static int __devinit armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
        return 0;
 }
 
-static int __devinit armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
        armv7pmu_init(cpu_pmu);
        cpu_pmu->name           = "ARMv7 Cortex-A5";
@@ -1264,7 +1264,7 @@ static int __devinit armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
        return 0;
 }
 
-static int __devinit armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
        armv7pmu_init(cpu_pmu);
        cpu_pmu->name           = "ARMv7 Cortex-A15";
@@ -1274,7 +1274,7 @@ static int __devinit armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
        return 0;
 }
 
-static int __devinit armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
+static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
        armv7pmu_init(cpu_pmu);
        cpu_pmu->name           = "ARMv7 Cortex-A7";
index 0c8265e53d5f7b079a49e80b70912e2edc1d7372..2b0fe30ec12e11715b834b13ee8998c043e2463d 100644 (file)
@@ -440,7 +440,7 @@ static int xscale_map_event(struct perf_event *event)
                                &xscale_perf_cache_map, 0xFF);
 }
 
-static int __devinit xscale1pmu_init(struct arm_pmu *cpu_pmu)
+static int xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
        cpu_pmu->name           = "xscale1";
        cpu_pmu->handle_irq     = xscale1pmu_handle_irq;
@@ -810,7 +810,7 @@ static inline void xscale2pmu_write_counter(struct perf_event *event, u32 val)
        }
 }
 
-static int __devinit xscale2pmu_init(struct arm_pmu *cpu_pmu)
+static int xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
        cpu_pmu->name           = "xscale2";
        cpu_pmu->handle_irq     = xscale2pmu_handle_irq;
index 9a89bf4aefe1e35ff8000a57f0d7b07b9219997c..3f6cbb2e3edae392f2b73520b89b6ee3b19e8437 100644 (file)
@@ -733,7 +733,7 @@ void __init setup_arch(char **cmdline_p)
        setup_processor();
        mdesc = setup_machine_fdt(__atags_pointer);
        if (!mdesc)
-               mdesc = setup_machine_tags(__atags_pointer, machine_arch_type);
+               mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
        machine_desc = mdesc;
        machine_name = mdesc->name;
 
index b9f015e843d8d10c461197c4399663942fb721e9..45eac87ed66a692859e7431af684f0b33b3ffeed 100644 (file)
@@ -75,7 +75,7 @@ void scu_enable(void __iomem *scu_base)
 int scu_power_mode(void __iomem *scu_base, unsigned int mode)
 {
        unsigned int val;
-       int cpu = cpu_logical_map(smp_processor_id());
+       int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
 
        if (mode > 3 || mode == 1 || cpu > 3)
                return -EINVAL;
index df745188f5de4abdf3bd04faaa5d31b653b0f210..ab1017bd1667d9772e01a903099aa665b3f86b7d 100644 (file)
@@ -109,10 +109,12 @@ static void set_segfault(struct pt_regs *regs, unsigned long addr)
 {
        siginfo_t info;
 
+       down_read(&current->mm->mmap_sem);
        if (find_vma(current->mm, addr) == NULL)
                info.si_code = SEGV_MAPERR;
        else
                info.si_code = SEGV_ACCERR;
+       up_read(&current->mm->mmap_sem);
 
        info.si_signo = SIGSEGV;
        info.si_errno = 0;
index b9f38e388b43ed968cda7b16d2efe081faefc0c0..11c1785bf63e40366f96135d22f291d60e2a20af 100644 (file)
@@ -140,6 +140,8 @@ SECTIONS
        }
 #endif
 
+       NOTES
+
        _etext = .;                     /* End of text and rodata section */
 
 #ifndef CONFIG_XIP_KERNEL
@@ -295,8 +297,6 @@ SECTIONS
        }
 #endif
 
-       NOTES
-
        BSS_SECTION(0, 0, 0)
        _end = .;
 
index 9ee866ce0478027b72cb001ca4cfb1a80326da3f..4b678478cf95d9f60d6a4484b4a490ee46228d45 100644 (file)
@@ -105,6 +105,8 @@ static void __init soc_detect(u32 dbgu_base)
        switch (socid) {
        case ARCH_ID_AT91RM9200:
                at91_soc_initdata.type = AT91_SOC_RM9200;
+               if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE)
+                       at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
                at91_boot_soc = at91rm9200_soc;
                break;
 
index 9211e8800c79a60397afa92c1e463c4cc569e974..6e2f1631df5b0e1321c9d80d11beea76c8c29607 100644 (file)
@@ -358,7 +358,7 @@ static int cpld_video_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit cpld_video_remove(struct i2c_client *client)
+static int cpld_video_remove(struct i2c_client *client)
 {
        cpld_client = NULL;
        return 0;
index f2232ca6d0707b7f8b5c64b976778000430f4bdf..abafb92031c0966a9728a5dd5309872a71e86886 100644 (file)
@@ -256,7 +256,7 @@ static int cdce_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit cdce_remove(struct i2c_client *client)
+static int cdce_remove(struct i2c_client *client)
 {
        cdce_i2c_client = NULL;
        return 0;
@@ -274,7 +274,7 @@ static struct i2c_driver cdce_driver = {
                .name   = "cdce949",
        },
        .probe          = cdce_probe,
-       .remove         = __devexit_p(cdce_remove),
+       .remove         = cdce_remove,
        .id_table       = cdce_id,
 };
 
index 0ef4435b16570dccde5af41737bf25987051270d..8a275f2975220f94063442c569510dbe5ea72dc9 100644 (file)
@@ -135,7 +135,7 @@ static struct pci_ops pcie_ops = {
        .write = pcie_wr_conf,
 };
 
-static void __devinit rc_pci_fixup(struct pci_dev *dev)
+static void rc_pci_fixup(struct pci_dev *dev)
 {
        /*
         * Prevent enumeration of root complex.
index 91d5b6f1d5afa80c6c0fbb5d35a88af1a2750838..85afb031b6766909354b88502c379598f2b1d37a 100644 (file)
@@ -74,6 +74,8 @@ config SOC_EXYNOS5440
        depends on ARCH_EXYNOS5
        select ARM_ARCH_TIMER
        select AUTO_ZRELADDR
+       select PINCTRL
+       select PINCTRL_EXYNOS5440
        help
          Enable EXYNOS5440 SoC support
 
@@ -412,7 +414,7 @@ config MACH_EXYNOS4_DT
        select CPU_EXYNOS4210
        select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
        select PINCTRL
-       select PINCTRL_EXYNOS4
+       select PINCTRL_EXYNOS
        select USE_OF
        help
          Machine support for Samsung Exynos4 machine with device tree enabled.
index efead60b943699d160fa8754e9435cfba4a658fc..bbcb3dea0d40e61de4c003a6c3ac46cc8b5157dc 100644 (file)
@@ -529,7 +529,7 @@ static struct clk exynos4_init_clocks_off[] = {
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 8),
        }, {
-               .name           = "dwmmc",
+               .name           = "biu",
                .parent         = &exynos4_clk_aclk_133.clk,
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 9),
@@ -1134,7 +1134,7 @@ static struct clksrc_clk exynos4_clksrcs[] = {
                .reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
        }, {
                .clk    = {
-                       .name           = "sclk_dwmmc",
+                       .name           = "ciu",
                        .parent         = &exynos4_clk_dout_mmc4.clk,
                        .enable         = exynos4_clksrc_mask_fsys_ctrl,
                        .ctrlbit        = (1 << 16),
index ddd4b72c6f9a9530e432399708b7e38af889e1c6..1a89824a5f781bfef84f7afc9167c41874198798 100644 (file)
@@ -424,11 +424,18 @@ static void __init exynos5_init_clocks(int xtal)
 {
        printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
 
+       /* EXYNOS5440 can support only common clock framework */
+
+       if (soc_is_exynos5440())
+               return;
+
+#ifdef CONFIG_SOC_EXYNOS5250
        s3c24xx_register_baseclocks(xtal);
        s5p_register_clocks(xtal);
 
        exynos5_register_clocks();
        exynos5_setup_clocks();
+#endif
 }
 
 #define COMBINER_ENABLE_SET    0x0
@@ -679,7 +686,8 @@ void __init exynos5_init_irq(void)
         * Theses parameters should be NULL and 0 because EXYNOS4
         * uses GIC instead of VIC.
         */
-       s5p_init_irq(NULL, 0);
+       if (!of_machine_is_compatible("samsung,exynos5440"))
+               s5p_init_irq(NULL, 0);
 
        gic_arch_extn.irq_set_wake = s3c_irq_wake;
 }
index a1cb42c3959015bfd764b4b94e2374be8916f643..9d1a60951d7bb0d9ce8dbb55d6be2179fac65e35 100644 (file)
 #include <mach/irqs.h>
 #include <mach/regs-audss.h>
 
-static const char *rclksrc[] = {
-       [0] = "busclk",
-       [1] = "i2sclk",
-};
-
 static int exynos4_cfg_i2s(struct platform_device *pdev)
 {
        /* configure GPIO for i2s port */
@@ -55,7 +50,6 @@ static struct s3c_audio_pdata i2sv5_pdata = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
                                         | QUIRK_NEED_RSTCLR,
-                       .src_clk = rclksrc,
                        .idma_addr = EXYNOS4_AUDSS_INT_MEM,
                },
        },
@@ -78,17 +72,11 @@ struct platform_device exynos4_device_i2s0 = {
        },
 };
 
-static const char *rclksrc_v3[] = {
-       [0] = "sclk_i2s",
-       [1] = "no_such_clock",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
        .cfg_gpio = exynos4_cfg_i2s,
        .type = {
                .i2s = {
                        .quirks = QUIRK_NO_MUXPSR,
-                       .src_clk = rclksrc_v3,
                },
        },
 };
index f038c8cadca484e1831cd3277394bd8565ab88c1..e99d3d8f2bcf436ab52a07f5c8d1d7ad519d8467 100644 (file)
@@ -163,6 +163,7 @@ static char const *exynos5_dt_compat[] __initdata = {
 
 static void __init exynos5_reserve(void)
 {
+#ifdef CONFIG_S5P_DEV_MFC
        struct s5p_mfc_dt_meminfo mfc_mem;
 
        /* Reserve memory for MFC only if it's available */
@@ -170,6 +171,7 @@ static void __init exynos5_reserve(void)
        if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
                s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
                                mfc_mem.lsize);
+#endif
 }
 
 DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
index e6f4191cd14c1af36c5df0ac14bb9d136f2f22e9..5e34b9c16196c4d7009d90e5bb55a596c918ee20 100644 (file)
@@ -621,7 +621,7 @@ static struct pwm_lookup origen_pwm_lookup[] = {
        PWM_LOOKUP("s3c24xx-pwm.0", 0, "pwm-backlight.0", NULL),
 };
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
 static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
        .panel  = {
                .timing = {
@@ -793,7 +793,7 @@ static void __init origen_machine_init(void)
        s5p_i2c_hdmiphy_set_platdata(NULL);
        s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0);
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
        s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
        exynos4_fimd0_gpio_setup_24bpp();
 #else
index a1555a73c7afd08f46cec725159b8b3ce1d2afd8..ae6da40c2aa9e168e9bb338b91556985089e5e4f 100644 (file)
@@ -246,7 +246,7 @@ static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
        .cols           = 8,
 };
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
 static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
        .panel  = {
                .timing = {
@@ -360,7 +360,7 @@ static void __init smdk4x12_machine_init(void)
 
        s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata);
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
        s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
        exynos4_fimd0_gpio_setup_24bpp();
 #else
index b7384241fb03ac836e08a74bab3cac4aae8c8881..35548e3c097d8e34916d027457ec6baa2d02b903 100644 (file)
@@ -159,7 +159,7 @@ static struct platform_device smdkv310_lcd_lte480wv = {
        .dev.platform_data      = &smdkv310_lcd_lte480wv_data,
 };
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
 static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
        .panel  = {
                .timing = {
@@ -402,7 +402,7 @@ static void __init smdkv310_machine_init(void)
        samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
        pwm_add_table(smdkv310_pwm_lookup, ARRAY_SIZE(smdkv310_pwm_lookup));
 
-#ifdef CONFIG_DRM_EXYNOS
+#ifdef CONFIG_DRM_EXYNOS_FIMD
        s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
        exynos4_fimd0_gpio_setup_24bpp();
 #else
index 4ca8ff14a5bfe99dc587bce680fb4afbb4d634a5..c5c840e947b88030156c95c99933891a43416974 100644 (file)
@@ -198,7 +198,7 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
        int i;
 
-       if (!soc_is_exynos5250())
+       if (!(soc_is_exynos5250() || soc_is_exynos5440()))
                scu_enable(scu_base_addr());
 
        /*
index dc248167d206c7072864cda37c01df675fcef50f..e6c06128293962b24adbe84892e19d4a876ff373 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <asm/arch_timer.h>
 #include <asm/cacheflush.h>
+#include <asm/cputype.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/arm_timer.h>
@@ -59,7 +60,7 @@ static void __init highbank_scu_map_io(void)
 
 void highbank_set_cpu_jump(int cpu, void *jump_addr)
 {
-       cpu = cpu_logical_map(cpu);
+       cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0);
        writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
        __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
        outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
@@ -135,7 +136,7 @@ static struct sys_timer highbank_timer = {
 
 static void highbank_power_off(void)
 {
-       hignbank_set_pwr_shutdown();
+       highbank_set_pwr_shutdown();
 
        while (1)
                cpu_do_idle();
index 7b60faccd5518da90c6bc404e32636cb3631be49..f30c528433967e43b1f1afa1050c13feefbbe914 100644 (file)
@@ -30,7 +30,7 @@ void __ref highbank_cpu_die(unsigned int cpu)
 {
        flush_cache_all();
 
-       highbank_set_cpu_jump(cpu, secondary_startup);
+       highbank_set_cpu_jump(cpu, phys_to_virt(0));
        highbank_set_core_pwr();
 
        cpu_do_idle();
index 1129957f6c1df90cdc10a90a4b6b0f4c6e5a2c37..4ecc864ac8b95dbe63283c4c0637c9436558d8a7 100644 (file)
@@ -32,6 +32,7 @@ static void __cpuinit highbank_secondary_init(unsigned int cpu)
 
 static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
+       highbank_set_cpu_jump(cpu, secondary_startup);
        gic_raise_softirq(cpumask_of(cpu), 0);
        return 0;
 }
@@ -61,19 +62,8 @@ static void __init highbank_smp_init_cpus(void)
 
 static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
 {
-       int i;
-
        if (scu_base_addr)
                scu_enable(scu_base_addr);
-
-       /*
-        * Write the address of secondary startup into the jump table
-        * The cores are in wfi and wait until they receive a soft interrupt
-        * and a non-zero value to jump to. Then the secondary CPU branches
-        * to this address.
-        */
-       for (i = 1; i < max_cpus; i++)
-               highbank_set_cpu_jump(i, secondary_startup);
 }
 
 struct smp_operations highbank_smp_ops __initdata = {
index 74aa135966f00c87716ca537df45e65c825d3273..04eddb4f438095da0fff7caee5f4561b7fe2c1f3 100644 (file)
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/cpu_pm.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/suspend.h>
 
+#include <asm/cacheflush.h>
 #include <asm/proc-fns.h>
 #include <asm/suspend.h>
 
 
 static int highbank_suspend_finish(unsigned long val)
 {
+       outer_flush_all();
+       outer_disable();
+
+       highbank_set_pwr_suspend();
+
        cpu_do_idle();
+
+       highbank_clear_pwr_request();
        return 0;
 }
 
 static int highbank_pm_enter(suspend_state_t state)
 {
-       hignbank_set_pwr_suspend();
+       cpu_pm_enter();
+       cpu_cluster_pm_enter();
+
        highbank_set_cpu_jump(0, cpu_resume);
        cpu_suspend(0, highbank_suspend_finish);
 
+       cpu_cluster_pm_exit();
+       cpu_pm_exit();
+
+       highbank_smc1(0x102, 0x1);
+       if (scu_base_addr)
+               scu_enable(scu_base_addr);
        return 0;
 }
 
index e13e8ea7c6cb30fdf5863c668765d39904984754..5995df7f2622eaa20382d7ad0e90483675a6b5eb 100644 (file)
@@ -37,35 +37,50 @@ extern void __iomem *sregs_base;
 
 static inline void highbank_set_core_pwr(void)
 {
-       int cpu = cpu_logical_map(smp_processor_id());
+       int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
        if (scu_base_addr)
                scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
        else
                writel_relaxed(1, sregs_base + SREG_CPU_PWR_CTRL(cpu));
 }
 
-static inline void hignbank_set_pwr_suspend(void)
+static inline void highbank_clear_core_pwr(void)
+{
+       int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
+       if (scu_base_addr)
+               scu_power_mode(scu_base_addr, SCU_PM_NORMAL);
+       else
+               writel_relaxed(0, sregs_base + SREG_CPU_PWR_CTRL(cpu));
+}
+
+static inline void highbank_set_pwr_suspend(void)
 {
        writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
        highbank_set_core_pwr();
 }
 
-static inline void hignbank_set_pwr_shutdown(void)
+static inline void highbank_set_pwr_shutdown(void)
 {
        writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
        highbank_set_core_pwr();
 }
 
-static inline void hignbank_set_pwr_soft_reset(void)
+static inline void highbank_set_pwr_soft_reset(void)
 {
        writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
        highbank_set_core_pwr();
 }
 
-static inline void hignbank_set_pwr_hard_reset(void)
+static inline void highbank_set_pwr_hard_reset(void)
 {
        writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
        highbank_set_core_pwr();
 }
 
+static inline void highbank_clear_pwr_request(void)
+{
+       writel(~0UL, sregs_base + HB_SREG_A9_PWR_REQ);
+       highbank_clear_core_pwr();
+}
+
 #endif
index aed96ad9bd4a7ddf8a7f2f544ca03e6d3f14a5bb..37d8384dcf1923bbae0d21a812784bc8037df8b8 100644 (file)
@@ -22,9 +22,9 @@
 void highbank_restart(char mode, const char *cmd)
 {
        if (mode == 'h')
-               hignbank_set_pwr_hard_reset();
+               highbank_set_pwr_hard_reset();
        else
-               hignbank_set_pwr_soft_reset();
+               highbank_set_pwr_soft_reset();
 
        while (1)
                cpu_do_idle();
index 1ad0d76de8c7b57029faccb9c88dda430a93bab7..0a2349dc70184021e268db86ef9c3cb0e966f8a3 100644 (file)
@@ -841,8 +841,6 @@ config SOC_IMX6Q
        select ARCH_HAS_CPUFREQ
        select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
-       select ARM_ERRATA_743622
-       select ARM_ERRATA_751472
        select ARM_ERRATA_754322
        select ARM_ERRATA_764369 if SMP
        select ARM_ERRATA_775420
@@ -853,6 +851,7 @@ config SOC_IMX6Q
        select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
+       select HAVE_IMX_SRC
        select HAVE_SMP
        select MFD_SYSCON
        select PINCTRL
index b197aa73dc4b448ad603256f8ea1ea5a9be8e30c..2c570cdaae7b1f9152f6cb1e0dd122882cfac028 100644 (file)
@@ -254,9 +254,9 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
        clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
        /* i.mx25 has the i.mx35 type cspi */
        clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
index 4c1d1e4efc74ed1694ef0f0eca2ab68396171426..1ffe3b534e51562aca68b587c383bb3df00b38a8 100644 (file)
@@ -236,9 +236,9 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
        clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
        clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
        clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
        clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
index 8be64e0a4ace0bec7a33f64ad2c056dfd0ad6947..16ccbd41dea9da4b830787b11e099dff7a19a141 100644 (file)
@@ -139,9 +139,9 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
-       clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
        /* i.mx31 has the i.mx21 type uart */
        clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
index 66f3d65ea2755f0a522f2fdea52f9b9351fe5beb..f0727e80815dc7adcb7ed2f1fbfcb43723fbd91a 100644 (file)
@@ -251,9 +251,9 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27");
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
index 579023f59dc1458690c91bf5059706e4dd99c6c6..fb7cb841b64c70aa8a411fd061cbf34ff6d7b480 100644 (file)
@@ -269,9 +269,9 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51");
+       clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51");
+       clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51");
        clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
index 7f2c10c7413abaf0786b45a29933bc60745bd12c..c0c4e723b7f5dee0a34526fd280cab2e8b3966b1 100644 (file)
@@ -436,6 +436,9 @@ int __init mx6q_clocks_init(void)
        for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
                clk_prepare_enable(clk[clks_init_on[i]]);
 
+       /* Set initial power mode */
+       imx6q_set_lpm(WAIT_CLOCKED);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 7191ab4434e52b5c881e170e9e7925e918ba42f5..fa36fb84ab193f2fb8480bf3cc70d68232824844 100644 (file)
@@ -142,6 +142,7 @@ extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_clock_map_io(void);
 
 extern void imx_cpu_die(unsigned int cpu);
+extern int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
index 36e8b399447037a73eb5261381a39cd88d9ea2bf..d8c75c3c925d7173dbfe05ecece495d5d3d9d7a7 100644 (file)
@@ -188,7 +188,7 @@ static struct cpufreq_driver mxc_driver = {
        .name = "imx",
 };
 
-static int __devinit mxc_cpufreq_driver_init(void)
+static int mxc_cpufreq_driver_init(void)
 {
        return cpufreq_register_driver(&mxc_driver);
 }
index 6277baf1b7be74496c4f000867bc9a899d7a7adb..9bd5777ff0e78aee55115a6255925ec0804a6593 100644 (file)
@@ -63,6 +63,7 @@ struct platform_device *__init imx_add_flexcan(
 
 #include <linux/fsl_devices.h>
 struct imx_fsl_usb2_udc_data {
+       const char *devid;
        resource_size_t iobase;
        resource_size_t irq;
 };
index 37e44398197b4703b7130734d166963f9e894e01..3c06bd96e9cc5e094a183213b1bdfd957ceda1b4 100644 (file)
 #include "../hardware.h"
 #include "devices-common.h"
 
-#define imx_fsl_usb2_udc_data_entry_single(soc)                                \
+#define imx_fsl_usb2_udc_data_entry_single(soc, _devid)                        \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _USB_OTG_BASE_ADDR,                    \
                .irq = soc ## _INT_USB_OTG,                             \
        }
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX25);
+       imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX27);
+       imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX31
 const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX31);
+       imx_fsl_usb2_udc_data_entry_single(MX31, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
 #ifdef CONFIG_SOC_IMX35
 const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX35);
+       imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
 #ifdef CONFIG_SOC_IMX51
 const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX51);
+       imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51");
 #endif
 
 struct platform_device *__init imx_add_fsl_usb2_udc(
@@ -57,7 +58,7 @@ struct platform_device *__init imx_add_fsl_usb2_udc(
                        .flags = IORESOURCE_IRQ,
                },
        };
-       return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
+       return imx_add_platform_device_dmamask(data->devid, -1,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 10b0ed39f07f9ff5cea15ca7fd5359f96506bd34..25a47c616b2d7c2b855eaf510b84b4d466b51d62 100644 (file)
@@ -54,7 +54,7 @@ struct platform_device *__init imx_add_imx_fb(
                        .flags = IORESOURCE_IRQ,
                },
        };
-       return imx_add_platform_device_dmamask("imx-fb", 0,
+       return imx_add_platform_device_dmamask(data->devid, 0,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 3dec962b0770aa9f088829da920c76a44a9d4113..7bc5fe15dda2a3cbc5eb43bd1c93d69830c4af70 100644 (file)
@@ -46,9 +46,11 @@ static inline void cpu_enter_lowpower(void)
 void imx_cpu_die(unsigned int cpu)
 {
        cpu_enter_lowpower();
-       imx_enable_cpu(cpu, false);
+       cpu_do_idle();
+}
 
-       /* spin here until hardware takes it down */
-       while (1)
-               ;
+int imx_cpu_kill(unsigned int cpu)
+{
+       imx_enable_cpu(cpu, false);
+       return 1;
 }
diff --git a/arch/arm/mach-imx/iram.h b/arch/arm/mach-imx/iram.h
deleted file mode 100644 (file)
index 022690c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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.
- */
-#include <linux/errno.h>
-
-#ifdef CONFIG_IRAM_ALLOC
-
-int __init iram_init(unsigned long base, unsigned long size);
-void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
-void iram_free(unsigned long dma_addr, unsigned int size);
-
-#else
-
-static inline int __init iram_init(unsigned long base, unsigned long size)
-{
-       return -ENOMEM;
-}
-
-static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
-{
-       return NULL;
-}
-
-static inline void iram_free(unsigned long base, unsigned long size) {}
-
-#endif
index 6c80424f678e3fad821aa8ea60685485db5ddb6e..e05cf407db659c834f6c2f4d500c26242c4e2d53 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/genalloc.h>
-
-#include "iram.h"
+#include "linux/platform_data/imx-iram.h"
 
 static unsigned long iram_phys_base;
 static void __iomem *iram_virt_base;
index c461e98496c308924f96a3daa65c37d60d0f3f8e..7a9686ad994ce99fed6431692040d162f3c0f5ce 100644 (file)
@@ -21,7 +21,7 @@
 #define BP_MMDC_MAPSR_PSD      0
 #define BP_MMDC_MAPSR_PSS      4
 
-static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+static int imx_mmdc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        void __iomem *mmdc_base, *reg;
index 3777b805b76ba8645c50c41993f8ba06b550927d..66fae885c8429f3b9147d4a3c33cd6e739a0ae05 100644 (file)
@@ -92,5 +92,6 @@ struct smp_operations  imx_smp_ops __initdata = {
        .smp_boot_secondary     = imx_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = imx_cpu_die,
+       .cpu_kill               = imx_cpu_kill,
 #endif
 };
index a17543da602da4d8c5504961434bba5bfa2551b2..ee42d20cba19f022d4a9ece8616e27b443d7e82e 100644 (file)
@@ -41,6 +41,7 @@ static int imx6q_pm_enter(suspend_state_t state)
                cpu_suspend(0, imx6q_suspend_finish);
                imx_smp_prepare();
                imx_gpc_post_resume();
+               imx6q_set_lpm(WAIT_CLOCKED);
                break;
        default:
                return -EINVAL;
index be50e795536d1aa2375df9957a057bac5d28e942..e7fcea7f33008b3e8ee5c3288475a726fd88c13d 100644 (file)
@@ -475,13 +475,12 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
 {
        int ret = 0;
 
+       if (!ap_syscon_base)
+               return -EINVAL;
+
        if (nr == 0) {
                sys->mem_offset = PHYS_PCI_MEM_BASE;
                ret = pci_v3_setup_resources(sys);
-               /* Remap the Integrator system controller */
-               ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
-               if (!ap_syscon_base)
-                       return -EINVAL;
        }
 
        return ret;
@@ -497,6 +496,13 @@ void __init pci_v3_preinit(void)
        unsigned int temp;
        int ret;
 
+       /* Remap the Integrator system controller */
+       ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+       if (!ap_syscon_base) {
+               pr_err("unable to remap the AP syscon for PCIv3\n");
+               return;
+       }
+
        pcibios_min_mem = 0x00100000;
 
        /*
index 2f28018c44478d97a5d108c861faaa1d1ae0483e..9082b84aeebb54cd7831256937f85299dd07a039 100644 (file)
@@ -504,7 +504,7 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
 /* Scan an IOP13XX PCI bus.  nr selects which ATU we use.
  */
-struct pci_bus * __devinit iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
+struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
 {
        int which_atu;
        struct pci_bus *bus = NULL;
index ff4150a2ad05259383d147626fbae49648e1a256..de4fd2bb1e27960a36d4301792a072bee90409f3 100644 (file)
@@ -67,6 +67,10 @@ static void __init kirkwood_legacy_clk_init(void)
        orion_clkdev_add(NULL, "mv643xx_eth_port.1",
                         of_clk_get_from_provider(&clkspec));
 
+       clkspec.args[0] = CGC_BIT_SDIO;
+       orion_clkdev_add(NULL, "mvsdio",
+                        of_clk_get_from_provider(&clkspec));
+
 }
 
 static void __init kirkwood_of_clk_init(void)
index 8821720ab5a481ca048b0acb1ef01010055ffa7f..f4632a809f6895a0481ea1876e3e0fe25da36fe8 100644 (file)
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data ns2_ge00_data = {
        .phy_addr       = MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int ns2_mpp_config[] __initdata = {
-       MPP0_SPI_SCn,
-       MPP1_SPI_MOSI,
-       MPP2_SPI_SCK,
-       MPP3_SPI_MISO,
-       MPP4_NF_IO6,
-       MPP5_NF_IO7,
-       MPP6_SYSRST_OUTn,
-       MPP7_GPO,               /* Fan speed (bit 1) */
-       MPP8_TW0_SDA,
-       MPP9_TW0_SCK,
-       MPP10_UART0_TXD,
-       MPP11_UART0_RXD,
-       MPP12_GPO,              /* Red led */
-       MPP14_GPIO,             /* USB fuse */
-       MPP16_GPIO,             /* SATA 0 power */
-       MPP17_GPIO,             /* SATA 1 power */
-       MPP18_NF_IO0,
-       MPP19_NF_IO1,
-       MPP20_SATA1_ACTn,
-       MPP21_SATA0_ACTn,
-       MPP22_GPIO,             /* Fan speed (bit 0) */
-       MPP23_GPIO,             /* Fan power */
-       MPP24_GPIO,             /* USB mode select */
-       MPP25_GPIO,             /* Fan rotation fail */
-       MPP26_GPIO,             /* USB device vbus */
-       MPP28_GPIO,             /* USB enable host vbus */
-       MPP29_GPIO,             /* Blue led (slow register) */
-       MPP30_GPIO,             /* Blue led (command register) */
-       MPP31_GPIO,             /* Board power off */
-       MPP32_GPIO,             /* Power button (0 = Released, 1 = Pushed) */
-       MPP33_GPO,              /* Fan speed (bit 2) */
-       0
-};
-
 #define NS2_GPIO_POWER_OFF     31
 
 static void ns2_power_off(void)
@@ -71,8 +35,6 @@ void __init ns2_init(void)
        /*
         * Basic setup. Needs to be called early.
         */
-       kirkwood_mpp_conf(ns2_mpp_config);
-
        if (of_machine_is_compatible("lacie,netspace_lite_v2") ||
            of_machine_is_compatible("lacie,netspace_mini_v2"))
                ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
index 15e69fcde9f4d262f80d749938ce8c477130e0d9..23d2dd1b1b1ed4079d61d20fd60ec898d9901de9 100644 (file)
@@ -64,8 +64,6 @@ static unsigned int topkick_mpp_config[] __initdata = {
        0
 };
 
-#define TOPKICK_SATA0_PWR_ENABLE 36
-
 void __init usi_topkick_init(void)
 {
        /*
@@ -73,8 +71,6 @@ void __init usi_topkick_init(void)
         */
        kirkwood_mpp_conf(topkick_mpp_config);
 
-       /* SATA0 power enable */
-       gpio_set_value(TOPKICK_SATA0_PWR_ENABLE, 1);
 
        kirkwood_ge00_init(&topkick_ge00_data);
        kirkwood_sdio_init(&topkick_mvsdio_data);
index ef102646ba9abbd4e650b79e8ded6e5137ff6bd6..a1c3ab6fc809da0061f01f15746d225a25b5645f 100644 (file)
@@ -214,7 +214,7 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
  * 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)
+static void rc_pci_fixup(struct pci_dev *dev)
 {
        if (dev->bus->parent == NULL && dev->devfn == 0) {
                int i;
index 255502ddd87924b444a27ba9f669d463f73ba251..b0c306ccbc6e38369167a7aef437914bd85affd7 100644 (file)
@@ -92,7 +92,7 @@ static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
        },
 };
 
-static void __devinit acs5k_i2c_init(void)
+static void acs5k_i2c_init(void)
 {
        /* The gpio interface */
        platform_device_register(&acs5k_i2c_device);
index a6c08ede4491dfb2672806de2021b8c95c63848a..bf5e64906e65604375a0781e51c95bbea7242924 100644 (file)
@@ -61,7 +61,7 @@ struct gen_pool *sram_get_gpool(char *pool_name)
 }
 EXPORT_SYMBOL(sram_get_gpool);
 
-static int __devinit sram_probe(struct platform_device *pdev)
+static int sram_probe(struct platform_device *pdev)
 {
        struct sram_platdata *pdata = pdev->dev.platform_data;
        struct sram_bank_info *info;
@@ -125,7 +125,7 @@ out:
        return ret;
 }
 
-static int __devexit sram_remove(struct platform_device *pdev)
+static int sram_remove(struct platform_device *pdev)
 {
        struct sram_bank_info *info;
 
index 8f1eecd881863ffe304bb760bba99bc5b7cdac6a..507f5ca806977343ae688a058ecb96131b8e0797 100644 (file)
@@ -120,7 +120,7 @@ int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
  * and unknown state. This function should be called early to
  * wait on the ARM9.
  */
-void __devinit proc_comm_boot_wait(void)
+void proc_comm_boot_wait(void)
 {
        void __iomem *base = MSM_SHARED_RAM_BASE;
  
index c5a2eddc6cdc1517d5e36fd11a5b0f5d97ead7a3..b1588a1ea2f8c1627f5c288486779f12744969e5 100644 (file)
@@ -988,7 +988,7 @@ int smd_core_init(void)
        return 0;
 }
 
-static int __devinit msm_smd_probe(struct platform_device *pdev)
+static int msm_smd_probe(struct platform_device *pdev)
 {
        /*
         * If we haven't waited for the ARM9 to boot up till now,
index a9a154a646dde94fb75b81f86cd6aa094250edfe..ee8c0b51df2c7013126f52ef8f441d4b9ccb6a8a 100644 (file)
@@ -173,7 +173,7 @@ static struct pci_ops pcie_ops = {
        .write = pcie_wr_conf,
 };
 
-static void __devinit rc_pci_fixup(struct pci_dev *dev)
+static void rc_pci_fixup(struct pci_dev *dev)
 {
        /*
         * Prevent enumeration of root complex.
index 5dcb369b58aa0c79e55159f9affbd8b0c2a105d2..99df4df680fda3b54e3dce605ea3793d3f6bd26b 100644 (file)
@@ -1,6 +1,8 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
        -I$(srctree)/arch/arm/plat-orion/include
 
+AFLAGS_coherency_ll.o          := -Wa,-march=armv7-a
+
 obj-y += system-controller.o
 obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
 obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
index 98167a4319f72d3735adf6ab4e277d68da8790b8..9f19069248da2341e643f1c6161fc8576c5803c3 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
 #include <linux/platform_data/clocksource-nomadik-mtu.h>
-#include <linux/platform_data/mtd-nomadik-nand.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
index b549d0571548ed8d3682e6946e2bce6f0e2fb4ed..215f8cdb400430b7e21f98c6271cdea71313f3f5 100644 (file)
 
 #include <mach/hardware.h>
 
-#define IRQ_VIC_START                /* first VIC interrupt is 1 */
+#define IRQ_VIC_START          32      /* first VIC interrupt is 1 */
 
 /*
  * Interrupt numbers generic for all Nomadik Chip cuts
  */
-#define IRQ_WATCHDOG                   1
-#define IRQ_SOFTINT                    2
-#define IRQ_CRYPTO                     3
-#define IRQ_OWM                                4
-#define IRQ_MTU0                       5
-#define IRQ_MTU1                       6
-#define IRQ_GPIO0                      7
-#define IRQ_GPIO1                      8
-#define IRQ_GPIO2                      9
-#define IRQ_GPIO3                      10
-#define IRQ_RTC_RTT                    11
-#define IRQ_SSP                                12
-#define IRQ_UART0                      13
-#define IRQ_DMA1                       14
-#define IRQ_CLCD_MDIF                  15
-#define IRQ_DMA0                       16
-#define IRQ_PWRFAIL                    17
-#define IRQ_UART1                      18
-#define IRQ_FIRDA                      19
-#define IRQ_MSP0                       20
-#define IRQ_I2C0                       21
-#define IRQ_I2C1                       22
-#define IRQ_SDMMC                      23
-#define IRQ_USBOTG                     24
-#define IRQ_SVA_IT0                    25
-#define IRQ_SVA_IT1                    26
-#define IRQ_SAA_IT0                    27
-#define IRQ_SAA_IT1                    28
-#define IRQ_UART2                      29
-#define IRQ_MSP2                       30
-#define IRQ_L2CC                       49
-#define IRQ_HPI                                50
-#define IRQ_SKE                                51
-#define IRQ_KP                         52
-#define IRQ_MEMST                      55
-#define IRQ_SGA_IT                     59
-#define IRQ_USBM                       61
-#define IRQ_MSP1                       63
+#define IRQ_WATCHDOG                   (IRQ_VIC_START+0)
+#define IRQ_SOFTINT                    (IRQ_VIC_START+1)
+#define IRQ_CRYPTO                     (IRQ_VIC_START+2)
+#define IRQ_OWM                                (IRQ_VIC_START+3)
+#define IRQ_MTU0                       (IRQ_VIC_START+4)
+#define IRQ_MTU1                       (IRQ_VIC_START+5)
+#define IRQ_GPIO0                      (IRQ_VIC_START+6)
+#define IRQ_GPIO1                      (IRQ_VIC_START+7)
+#define IRQ_GPIO2                      (IRQ_VIC_START+8)
+#define IRQ_GPIO3                      (IRQ_VIC_START+9)
+#define IRQ_RTC_RTT                    (IRQ_VIC_START+10)
+#define IRQ_SSP                                (IRQ_VIC_START+11)
+#define IRQ_UART0                      (IRQ_VIC_START+12)
+#define IRQ_DMA1                       (IRQ_VIC_START+13)
+#define IRQ_CLCD_MDIF                  (IRQ_VIC_START+14)
+#define IRQ_DMA0                       (IRQ_VIC_START+15)
+#define IRQ_PWRFAIL                    (IRQ_VIC_START+16)
+#define IRQ_UART1                      (IRQ_VIC_START+17)
+#define IRQ_FIRDA                      (IRQ_VIC_START+18)
+#define IRQ_MSP0                       (IRQ_VIC_START+19)
+#define IRQ_I2C0                       (IRQ_VIC_START+20)
+#define IRQ_I2C1                       (IRQ_VIC_START+21)
+#define IRQ_SDMMC                      (IRQ_VIC_START+22)
+#define IRQ_USBOTG                     (IRQ_VIC_START+23)
+#define IRQ_SVA_IT0                    (IRQ_VIC_START+24)
+#define IRQ_SVA_IT1                    (IRQ_VIC_START+25)
+#define IRQ_SAA_IT0                    (IRQ_VIC_START+26)
+#define IRQ_SAA_IT1                    (IRQ_VIC_START+27)
+#define IRQ_UART2                      (IRQ_VIC_START+28)
+#define IRQ_MSP2                       (IRQ_VIC_START+29)
+#define IRQ_L2CC                       (IRQ_VIC_START+30)
+#define IRQ_HPI                                (IRQ_VIC_START+31)
+#define IRQ_SKE                                (IRQ_VIC_START+32)
+#define IRQ_KP                         (IRQ_VIC_START+33)
+#define IRQ_MEMST                      (IRQ_VIC_START+34)
+#define IRQ_SGA_IT                     (IRQ_VIC_START+35)
+#define IRQ_USBM                       (IRQ_VIC_START+36)
+#define IRQ_MSP1                       (IRQ_VIC_START+37)
 
 #define NOMADIK_GPIO_OFFSET            (IRQ_VIC_START+64)
 
index f0e69cbc5baaefa8a0372a485408687d2395be07..222d58c0ae76951efa9651e064182cf138ed0dbd 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram-init.o sram.o time.o irq.o mux.o flash.o \
-        serial.o devices.o dma.o
+        serial.o devices.o dma.o fb.o
 obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
index a8fce3ccc707fcea16c27f9edd8a47ef8961d2a0..2e98a3ac7c5e1f5fdc56046507bda4b61aa1b3ae 100644 (file)
@@ -160,7 +160,7 @@ static struct omap_lcd_config ams_delta_lcd_config __initdata = {
        .ctrl_name      = "internal",
 };
 
-static struct omap_usb_config ams_delta_usb_config = {
+static struct omap_usb_config ams_delta_usb_config __initdata = {
        .register_host  = 1,
        .hmc_mode       = 16,
        .pins[0]        = 2,
diff --git a/arch/arm/mach-omap1/fb.c b/arch/arm/mach-omap1/fb.c
new file mode 100644 (file)
index 0000000..c770d45
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * File: arch/arm/plat-omap/fb.c
+ *
+ * Framebuffer device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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 (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/memblock.h>
+#include <linux/io.h>
+#include <linux/omapfb.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach/map.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static bool omapfb_lcd_configured;
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+       .name           = "omapfb",
+       .id             = -1,
+       .dev = {
+               .dma_mask               = &omap_fb_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &omapfb_config,
+       },
+       .num_resources = 0,
+};
+
+void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
+{
+       omapfb_config.lcd = *config;
+       omapfb_lcd_configured = true;
+}
+
+static int __init omap_init_fb(void)
+{
+       /*
+        * If the board file has not set the lcd config with
+        * omapfb_set_lcd_config(), don't bother registering the omapfb device
+        */
+       if (!omapfb_lcd_configured)
+               return 0;
+
+       return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
+{
+}
+
+#endif
index e962926b67bc48dcd146fab36901971910164556..efc8f207f6fcd7845065b569f835764ff47e9ba5 100644 (file)
@@ -142,7 +142,7 @@ static struct omap_mbox mbox_dsp_info = {
 
 static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
 
-static int __devinit omap1_mbox_probe(struct platform_device *pdev)
+static int omap1_mbox_probe(struct platform_device *pdev)
 {
        struct resource *mem;
        int ret;
@@ -165,7 +165,7 @@ static int __devinit omap1_mbox_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit omap1_mbox_remove(struct platform_device *pdev)
+static int omap1_mbox_remove(struct platform_device *pdev)
 {
        omap_mbox_unregister();
        iounmap(mbox_base);
@@ -174,7 +174,7 @@ static int __devexit omap1_mbox_remove(struct platform_device *pdev)
 
 static struct platform_driver omap1_mbox_driver = {
        .probe  = omap1_mbox_probe,
-       .remove = __devexit_p(omap1_mbox_remove),
+       .remove = omap1_mbox_remove,
        .driver = {
                .name   = "omap-mailbox",
        },
index 104fed366b8f4877f79d05b325f7e3b835f1b5c6..1a1db5971cd9e6e412b7c8151040f6c907c2868f 100644 (file)
@@ -629,8 +629,14 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config)
 static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
 #endif
 
-void __init omap1_usb_init(struct omap_usb_config *pdata)
+void __init omap1_usb_init(struct omap_usb_config *_pdata)
 {
+       struct omap_usb_config *pdata;
+
+       pdata = kmemdup(_pdata, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return;
+
        pdata->usb0_init = omap1_usb0_init;
        pdata->usb1_init = omap1_usb1_init;
        pdata->usb2_init = omap1_usb2_init;
index a8004f33b7e2ac6357bc8454e95d9a69dddcfbe4..947cafe65aefda11f9e00a43c8758807d1229f96 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
+obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \
         common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
         omap_device.o sram.o
 
index 5c8e9cee2c2e99a4e1562b07021edb77eb36a554..769c1feee1c469049290f9101745cc28ef01742f 100644 (file)
@@ -397,6 +397,12 @@ static struct omap_board_mux board_mux[] __initdata = {
                  OMAP_PULL_ENA),
        OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
 
+       /* UART2 - BT/FM/GPS shared transport */
+       OMAP4_MUX(UART2_CTS,    OMAP_PIN_INPUT  | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_RTS,    OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_RX,     OMAP_PIN_INPUT  | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_TX,     OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 7e5febe456d97b0088d7dfe455124b8153f4ff41..ab7e952d207013e42888c2a7cbfe0cd4e7b1b162 100644 (file)
@@ -1935,6 +1935,8 @@ int __init omap2420_clk_init(void)
                        omap2_init_clk_hw_omap_clocks(c->lk.clk);
        }
 
+       omap2xxx_clkt_vps_late_init();
+
        omap2_clk_disable_autoidle_all();
 
        omap2_clk_enable_init_clocks(enable_init_clks,
index eda079b96c6aac0389c6539f7d93a0b0cf539e4f..eb3dab68d5362b4b6340de4fccca2b5fd8fff825 100644 (file)
@@ -2050,6 +2050,8 @@ int __init omap2430_clk_init(void)
                        omap2_init_clk_hw_omap_clocks(c->lk.clk);
        }
 
+       omap2xxx_clkt_vps_late_init();
+
        omap2_clk_disable_autoidle_all();
 
        omap2_clk_enable_init_clocks(enable_init_clks,
index bdf39481fbd6022d96af89e54a44e5bf402fb62f..6ef87580c33f6772a1fed5445b1bb2344fb96a6d 100644 (file)
@@ -1167,6 +1167,8 @@ static const struct clk_ops emu_src_ck_ops = {
        .recalc_rate    = &omap2_clksel_recalc,
        .get_parent     = &omap2_clksel_find_parent_index,
        .set_parent     = &omap2_clksel_set_parent,
+       .enable         = &omap2_clkops_enable_clkdm,
+       .disable        = &omap2_clkops_disable_clkdm,
 };
 
 static struct clk emu_src_ck;
index 5789a5e255638d60f797a18840b3f0b01394e50a..a2cc046b47f460a83a0954ae5249e617ea091f01 100644 (file)
@@ -2026,14 +2026,13 @@ int __init omap4xxx_clk_init(void)
         * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
         * state when turning the ABE clock domain. Workaround this by
         * locking the ABE DPLL on boot.
+        * Lock the ABE DPLL in any case to avoid issues with audio.
         */
-       if (cpu_is_omap446x()) {
-               rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
-               if (!rc)
-                       rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
-               if (rc)
-                       pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-       }
+       rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
+       if (!rc)
+               rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
        return 0;
 }
index 3d944d3263d2ae36966ed9f0a01e0c5849288948..e6c328128a0a3fbf0fc7745c5d3895b9c61c9759 100644 (file)
 #define OMAP343X_PADCONF_ETK_D14       OMAP343X_PADCONF_ETK(16)
 #define OMAP343X_PADCONF_ETK_D15       OMAP343X_PADCONF_ETK(17)
 
-/* 34xx GENERAL_WKUP regist offsets */
+/* 34xx GENERAL_WKUP register offsets */
 #define OMAP343X_CONTROL_WKUP_DEBOBSMUX(i) (OMAP343X_CONTROL_GENERAL_WKUP + \
                                                0x008 + (i))
 #define OMAP343X_CONTROL_WKUP_DEBOBS0 (OMAP343X_CONTROL_GENERAL_WKUP + 0x008)
index 5e304d0719a2ae763885d8e5468de14a1dad0257..626f3ea3142f55dfd0bcd5337a9758eab5d0cf71 100644 (file)
@@ -639,7 +639,7 @@ static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
        return cnt;
 }
 
-static void omap_init_ocp2scp(void)
+static void __init omap_init_ocp2scp(void)
 {
        struct omap_hwmod       *oh;
        struct platform_device  *pdev;
index 2bb18838cba9994dbd25be0b0c209bb261ee43e4..0a02aab5df677db9bc5577093f5f6091d4c86ff8 100644 (file)
@@ -504,8 +504,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
                if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
                        freqsel = _omap3_dpll_compute_freqsel(clk,
                                                dd->last_rounded_n);
-                       if (!freqsel)
-                               WARN_ON(1);
+                       WARN_ON(!freqsel);
                }
 
                pr_debug("%s: %s: set rate: locking rate to %lu.\n",
index fce5aa3fff49b8cfea304426da3d316e71055273..2a2cfa88ddbfdd456b6522c678ac7321057ad517 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/omap_drm.h>
 
+#include "soc.h"
 #include "omap_device.h"
 #include "omap_hwmod.h"
-#include <plat/cpu.h>
 
 #if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE)
 
@@ -57,7 +57,7 @@ static int __init omap_init_drm(void)
                        oh->name);
        }
 
-       platform_data.omaprev = GET_OMAP_REVISION();
+       platform_data.omaprev = GET_OMAP_TYPE;
 
        return platform_device_register(&omap_drm_device);
 
index 679a0478644fe4a5a008a233105d23a00dc9c96b..4be5cfc81ab8cd8c0ab1b6333b13c33fe6d0d733 100644 (file)
@@ -31,8 +31,7 @@
 #include <video/omap-panel-nokia-dsi.h>
 #include <video/omap-panel-picodlp.h>
 
-#include <plat/cpu.h>
-
+#include "soc.h"
 #include "dss-common.h"
 #include "mux.h"
 
diff --git a/arch/arm/mach-omap2/fb.c b/arch/arm/mach-omap2/fb.c
new file mode 100644 (file)
index 0000000..d9bd965
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Framebuffer device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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 (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/memblock.h>
+#include <linux/io.h>
+#include <linux/omapfb.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach/map.h>
+
+#include "soc.h"
+
+#ifdef CONFIG_OMAP2_VRFB
+
+/*
+ * The first memory resource is the register region for VRFB,
+ * the rest are VRFB virtual memory areas for each VRFB context.
+ */
+
+static const struct resource omap2_vrfb_resources[] = {
+       DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
+       DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+       DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+       DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+       DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+};
+
+static const struct resource omap3_vrfb_resources[] = {
+       DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
+       DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+       DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+       DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+       DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+       DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
+       DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
+       DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
+       DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
+       DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
+       DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
+       DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
+       DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
+};
+
+static int __init omap_init_vrfb(void)
+{
+       struct platform_device *pdev;
+       const struct resource *res;
+       unsigned int num_res;
+
+       if (cpu_is_omap24xx()) {
+               res = omap2_vrfb_resources;
+               num_res = ARRAY_SIZE(omap2_vrfb_resources);
+       } else if (cpu_is_omap34xx()) {
+               res = omap3_vrfb_resources;
+               num_res = ARRAY_SIZE(omap3_vrfb_resources);
+       } else {
+               return 0;
+       }
+
+       pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
+                       res, num_res, NULL, 0);
+
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
+       else
+               return 0;
+}
+
+arch_initcall(omap_init_vrfb);
+#endif
+
+#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+static struct omapfb_platform_data omapfb_config;
+
+static struct platform_device omap_fb_device = {
+       .name           = "omapfb",
+       .id             = -1,
+       .dev = {
+               .dma_mask               = &omap_fb_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &omapfb_config,
+       },
+       .num_resources = 0,
+};
+
+static int __init omap_init_fb(void)
+{
+       return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#endif
index 65468f6d7f0e62382ee6df3c16fcb2cad5eb054e..8033cb747c86ecc60ca18397ec9a9a2bfd9855ca 100644 (file)
@@ -744,7 +744,7 @@ static int gpmc_setup_irq(void)
        return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
 }
 
-static __devexit int gpmc_free_irq(void)
+static int gpmc_free_irq(void)
 {
        int i;
 
@@ -762,7 +762,7 @@ static __devexit int gpmc_free_irq(void)
        return 0;
 }
 
-static void __devexit gpmc_mem_exit(void)
+static void gpmc_mem_exit(void)
 {
        int cs;
 
@@ -774,7 +774,7 @@ static void __devexit gpmc_mem_exit(void)
 
 }
 
-static int __devinit gpmc_mem_init(void)
+static int gpmc_mem_init(void)
 {
        int cs, rc;
        unsigned long boot_rom_space = 0;
@@ -1121,7 +1121,7 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
        return 0;
 }
 
-static __devinit int gpmc_probe(struct platform_device *pdev)
+static int gpmc_probe(struct platform_device *pdev)
 {
        int rc;
        u32 l;
@@ -1177,7 +1177,7 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int gpmc_remove(struct platform_device *pdev)
+static int gpmc_remove(struct platform_device *pdev)
 {
        gpmc_free_irq();
        gpmc_mem_exit();
@@ -1187,7 +1187,7 @@ static __devexit int gpmc_remove(struct platform_device *pdev)
 
 static struct platform_driver gpmc_driver = {
        .probe          = gpmc_probe,
-       .remove         = __devexit_p(gpmc_remove),
+       .remove         = gpmc_remove,
        .driver         = {
                .name   = DEVICE_NAME,
                .owner  = THIS_MODULE,
index 0d974565f8ca7ec6fae5d6f1fe081c398e2b243b..0b080267b7f6355dac3b9adcd8b732b7cc44f936 100644 (file)
@@ -342,7 +342,7 @@ struct omap_mbox mbox_2_info = {
 struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL };
 #endif
 
-static int __devinit omap2_mbox_probe(struct platform_device *pdev)
+static int omap2_mbox_probe(struct platform_device *pdev)
 {
        struct resource *mem;
        int ret;
@@ -395,7 +395,7 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit omap2_mbox_remove(struct platform_device *pdev)
+static int omap2_mbox_remove(struct platform_device *pdev)
 {
        omap_mbox_unregister();
        iounmap(mbox_base);
@@ -404,7 +404,7 @@ static int __devexit omap2_mbox_remove(struct platform_device *pdev)
 
 static struct platform_driver omap2_mbox_driver = {
        .probe = omap2_mbox_probe,
-       .remove = __devexit_p(omap2_mbox_remove),
+       .remove = omap2_mbox_remove,
        .driver = {
                .name = "omap-mailbox",
        },
index 7642fc4672c1f57b2b67a1839b341e9f15260170..6da4f7ae9d7f2d80545a53443b9ae51f1e64f214 100644 (file)
@@ -16,8 +16,8 @@
 #include <linux/slab.h>
 
 #include <linux/platform_data/iommu-omap.h>
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
 
 static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
 {
index 081c71edddf4562797c632fc8f19bb86a8bac07d..646c14d9fdb9dfbe656437b45c6757c8db4d1b15 100644 (file)
@@ -2070,7 +2070,7 @@ static struct omap_hwmod_irq_info am33xx_usbss_mpu_irqs[] = {
        { .name = "usbss-irq", .irq = 17 + OMAP_INTC_START, },
        { .name = "musb0-irq", .irq = 18 + OMAP_INTC_START, },
        { .name = "musb1-irq", .irq = 19 + OMAP_INTC_START, },
-       { .irq = -1 + OMAP_INTC_START, },
+       { .irq = -1, },
 };
 
 static struct omap_hwmod am33xx_usbss_hwmod = {
@@ -2515,7 +2515,7 @@ static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
        .user           = OCP_USER_MPU,
 };
 
-struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
+static struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
        {
                .pa_start       = 0x4A101000,
                .pa_end         = 0x4A101000 + SZ_256 - 1,
@@ -2523,7 +2523,7 @@ struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
        { }
 };
 
-struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+static struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
        .master         = &am33xx_cpgmac0_hwmod,
        .slave          = &am33xx_mdio_hwmod,
        .addr           = am33xx_mdio_addr_space,
index f9fab942d5ba003f853d1259cf83e57f64a96ac0..793f54ac7d14b7cae5117404a564d527414d3e50 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/omap-dma.h>
 
-#include <linux/platform_data/omap_ocp2scp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/iommu-omap.h>
@@ -2133,8 +2132,12 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
         * 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.
+        *
+        * Also, McPDM needs to be configured to NO_IDLE mode when it
+        * is in used otherwise vital clocks will be gated which
+        * results 'slow motion' audio playback.
         */
-       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
index fefd40166624d97196c8f000c63061f01c18761f..615e5b1fb025dddebadf72e21a7845c0a4306c14 100644 (file)
@@ -292,8 +292,8 @@ int __init omap3_twl_set_sr_bit(bool enable)
        if (twl_sr_enable_autoinit)
                pr_warning("%s: unexpected multiple calls\n", __func__);
 
-       ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
-                                       TWL4030_DCDC_GLOBAL_CFG);
+       ret = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp,
+                             TWL4030_DCDC_GLOBAL_CFG);
        if (ret)
                goto err;
 
@@ -302,8 +302,8 @@ int __init omap3_twl_set_sr_bit(bool enable)
        else
                temp &= ~SMARTREFLEX_ENABLE;
 
-       ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
-                               TWL4030_DCDC_GLOBAL_CFG);
+       ret = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp,
+                              TWL4030_DCDC_GLOBAL_CFG);
        if (!ret) {
                twl_sr_enable_autoinit = true;
                return 0;
index 250d909e38bdf1204dd42c786b8e89f670b60f43..eb78ae7a3464e4f00a3e4d36655a53a556e82528 100644 (file)
@@ -11,8 +11,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/pm_runtime.h>
-
 #include <asm/pmu.h>
 
 #include "soc.h"
index faeab18696dfff6dc8e092c90c25fdd40be6f9a6..418de9c3b3195e0ccc283fc90a70a486beafa3b3 100644 (file)
@@ -18,9 +18,8 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include "soc.h"
 #include "common.h"
-#include <plat/cpu.h>
-
 #include "vp.h"
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
+/*
+ * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
+ * these are reversed from the bits used on OMAP3+
+ */
+#define OMAP24XX_PWRDM_POWER_ON                        0x0
+#define OMAP24XX_PWRDM_POWER_RET               0x1
+#define OMAP24XX_PWRDM_POWER_OFF               0x3
+
 /*
  * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
  *   hardware register (which are specific to the OMAP2xxx SoCs) to
@@ -68,6 +75,34 @@ static u32 omap2xxx_prm_read_reset_sources(void)
        return r;
 }
 
+/**
+ * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
+ * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
+ *
+ * Return the common power state bits corresponding to the OMAP2xxx
+ * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
+ */
+static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
+{
+       u8 pwrst;
+
+       switch (omap2xxx_pwrst) {
+       case OMAP24XX_PWRDM_POWER_OFF:
+               pwrst = PWRDM_POWER_OFF;
+               break;
+       case OMAP24XX_PWRDM_POWER_RET:
+               pwrst = PWRDM_POWER_RET;
+               break;
+       case OMAP24XX_PWRDM_POWER_ON:
+               pwrst = PWRDM_POWER_ON;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return pwrst;
+}
+
 /**
  * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
  *
@@ -98,10 +133,56 @@ int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
        return 0;
 }
 
+static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       u8 omap24xx_pwrst;
+
+       switch (pwrst) {
+       case PWRDM_POWER_OFF:
+               omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
+               break;
+       case PWRDM_POWER_RET:
+               omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
+               break;
+       case PWRDM_POWER_ON:
+               omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+                                  (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
+                                  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+       return 0;
+}
+
+static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+       u8 omap2xxx_pwrst;
+
+       omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+                                                      OMAP2_PM_PWSTCTRL,
+                                                      OMAP_POWERSTATE_MASK);
+
+       return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
+}
+
+static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+       u8 omap2xxx_pwrst;
+
+       omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+                                                      OMAP2_PM_PWSTST,
+                                                      OMAP_POWERSTATEST_MASK);
+
+       return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
+}
+
 struct pwrdm_ops omap2_pwrdm_operations = {
-       .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
-       .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
-       .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
+       .pwrdm_set_next_pwrst   = omap2xxx_pwrdm_set_next_pwrst,
+       .pwrdm_read_next_pwrst  = omap2xxx_pwrdm_read_next_pwrst,
+       .pwrdm_read_pwrst       = omap2xxx_pwrdm_read_pwrst,
        .pwrdm_set_logic_retst  = omap2_pwrdm_set_logic_retst,
        .pwrdm_set_mem_onst     = omap2_pwrdm_set_mem_onst,
        .pwrdm_set_mem_retst    = omap2_pwrdm_set_mem_retst,
index 30517f5af70708e360c140ef22374adc7560ec89..a3e121f94a864e63108ba1c54522aeb904395918 100644 (file)
@@ -103,28 +103,6 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 /* Powerdomain low-level functions */
 
 /* Common functions across OMAP2 and OMAP3 */
-int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
-{
-       omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-                                  (pwrst << OMAP_POWERSTATE_SHIFT),
-                                  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
-       return 0;
-}
-
-int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
-{
-       return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-                                            OMAP2_PM_PWSTCTRL,
-                                            OMAP_POWERSTATE_MASK);
-}
-
-int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
-{
-       return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-                                            OMAP2_PM_PWSTST,
-                                            OMAP_POWERSTATEST_MASK);
-}
-
 int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
                                                                u8 pwrst)
 {
index db198d058584d06203860216abeb5cc43b1ab074..e648bd55b0729a6b1023e1cc7b04b8f0c786e0fe 100644 (file)
@@ -18,9 +18,8 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include "soc.h"
 #include "common.h"
-#include <plat/cpu.h>
-
 #include "vp.h"
 #include "powerdomain.h"
 #include "prm3xxx.h"
@@ -278,6 +277,28 @@ static u32 omap3xxx_prm_read_reset_sources(void)
 
 /* Powerdomain low-level functions */
 
+static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+                                  (pwrst << OMAP_POWERSTATE_SHIFT),
+                                  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+       return 0;
+}
+
+static int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+       return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+                                            OMAP2_PM_PWSTCTRL,
+                                            OMAP_POWERSTATE_MASK);
+}
+
+static int omap3_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+       return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+                                            OMAP2_PM_PWSTST,
+                                            OMAP_POWERSTATEST_MASK);
+}
+
 /* Applicable only for OMAP3. Not supported on OMAP2 */
 static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 {
@@ -356,9 +377,9 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap3_pwrdm_operations = {
-       .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
-       .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
-       .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
+       .pwrdm_set_next_pwrst   = omap3_pwrdm_set_next_pwrst,
+       .pwrdm_read_next_pwrst  = omap3_pwrdm_read_next_pwrst,
+       .pwrdm_read_pwrst       = omap3_pwrdm_read_pwrst,
        .pwrdm_read_prev_pwrst  = omap3_pwrdm_read_prev_pwrst,
        .pwrdm_set_logic_retst  = omap2_pwrdm_set_logic_retst,
        .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
index 7498bc77fe8b8e69e5dbfe106dd24861c3a2c203..c05a343d465dcc1374a7c3a19142ca2e75d77517 100644 (file)
@@ -56,9 +56,9 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
  *   enumeration)
  */
 static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
-       { OMAP4430_RST_GLOBAL_WARM_SW_SHIFT,
+       { OMAP4430_GLOBAL_WARM_SW_RST_SHIFT,
          OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
-       { OMAP4430_RST_GLOBAL_COLD_SW_SHIFT,
+       { OMAP4430_GLOBAL_COLD_RST_SHIFT,
          OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
        { OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
          OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
@@ -333,7 +333,7 @@ static u32 omap44xx_prm_read_reset_sources(void)
        u32 r = 0;
        u32 v;
 
-       v = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+       v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
                                    OMAP4_RM_RSTST);
 
        p = omap44xx_prm_reset_src_map;
index 22b0979206ca08b7cd929eee361607f802561af2..8ee1fbdec5615c47c9345c88eb689249e8ea90ae 100644 (file)
@@ -62,8 +62,8 @@
 
 /* OMAP4 specific register offsets */
 #define OMAP4_RM_RSTCTRL                               0x0000
-#define OMAP4_RM_RSTTIME                               0x0004
-#define OMAP4_RM_RSTST                                 0x0008
+#define OMAP4_RM_RSTST                                 0x0004
+#define OMAP4_RM_RSTTIME                               0x0008
 #define OMAP4_PM_PWSTCTRL                              0x0000
 #define OMAP4_PM_PWSTST                                        0x0004
 
index 06e141543623d46801f3cf7206d3e9879253f648..b8ad6e632bb84d9ed3ede854cefeeebe6b4cc00c 100644 (file)
@@ -165,17 +165,13 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
        struct device_node *np;
 
        for_each_matching_node(np, match) {
-               if (!of_device_is_available(np)) {
-                       of_node_put(np);
+               if (!of_device_is_available(np))
                        continue;
-               }
 
-               if (property && !of_get_property(np, property, NULL)) {
-                       of_node_put(np);
+               if (property && !of_get_property(np, property, NULL))
                        continue;
-               }
 
-               prom_add_property(np, &device_disabled);
+               of_add_property(np, &device_disabled);
                return np;
        }
 
index cd50e328db2a46e4470e57bb8bbe5af0d30f595c..d9c7c3bf0d9cca840a618590c16145ef621c399d 100644 (file)
@@ -506,7 +506,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
 /*****************************************************************************
  * General PCIe + PCI
  ****************************************************************************/
-static void __devinit rc_pci_fixup(struct pci_dev *dev)
+static void rc_pci_fixup(struct pci_dev *dev)
 {
        /*
         * Prevent enumeration of root complex.
index fb5a7910af35b7a86534116f53b821aa2d36755c..9936c180bf016bbf769e60a16309c603c69c1a6f 100644 (file)
@@ -123,7 +123,7 @@ static const struct of_device_id memc_ids[] = {
        {}
 };
 
-static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+static int sirfsoc_memc_probe(struct platform_device *op)
 {
        struct device_node *np = op->dev.of_node;
 
index 9d80f1e20a98fc0364c113ff37df6c8bf5818fac..5573536021302b91f0d52048f14a94b3abfe3513 100644 (file)
@@ -107,7 +107,7 @@ static const struct of_device_id rtciobrg_ids[] = {
        {}
 };
 
-static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+static int sirfsoc_rtciobrg_probe(struct platform_device *op)
 {
        struct device_node *np = op->dev.of_node;
 
index 048c4299473c586ab2a814b7bf625130c0b063ed..7a39efc50865b27d678b561431ba29d4e5dce560 100644 (file)
@@ -198,7 +198,7 @@ static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
 
 static struct platform_device *corgipm_device;
 
-static int __devinit corgipm_init(void)
+static int corgipm_init(void)
 {
        int ret;
 
index a611ad3153c7b2e7e9a7e78803df0f9876bc677e..b6132aa95dc08b1ef2cc6ae0c4a5565b5213a0ab 100644 (file)
        GPIO76_LCD_PCLK,        \
        GPIO77_LCD_BIAS
 
+/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */
+#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT)
+#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT)
 
 extern int keypad_set_wake(unsigned int on);
 #endif /* __ASM_ARCH_MFP_PXA27X_H */
index 8047ee0effc582b421a28085624a2b58250e88e4..616cb87b61792544f470110cd6322b2d3ea9d914 100644 (file)
@@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void)
 EXPORT_SYMBOL(pxa27x_clear_otgph);
 
 static unsigned long ac97_reset_config[] = {
-       GPIO113_GPIO,
+       GPIO113_AC97_nRESET_GPIO_HIGH,
        GPIO113_AC97_nRESET,
-       GPIO95_GPIO,
+       GPIO95_AC97_nRESET_GPIO_HIGH,
        GPIO95_AC97_nRESET,
 };
 
index ec55c575ed192f7969d64b19dc0dbb8837ae89eb..0a36d3585f26822191e7355c9d2e4208c77fcaff 100644 (file)
@@ -829,7 +829,7 @@ static const struct platform_suspend_ops sharpsl_pm_ops = {
 };
 #endif
 
-static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
+static int sharpsl_pm_probe(struct platform_device *pdev)
 {
        int ret, irq;
 
@@ -941,7 +941,7 @@ static struct platform_driver sharpsl_pm_driver = {
        },
 };
 
-static int __devinit sharpsl_pm_init(void)
+static int sharpsl_pm_init(void)
 {
        return platform_driver_register(&sharpsl_pm_driver);
 }
index 842596d4d31e19e59cd898084125944a03db7b90..e191f9996b26b967dbfbe8a176af92b73123dc1e 100644 (file)
@@ -232,7 +232,7 @@ struct sharpsl_charger_machinfo spitz_pm_machinfo = {
 
 static struct platform_device *spitzpm_device;
 
-static int __devinit spitzpm_init(void)
+static int spitzpm_init(void)
 {
        int ret;
 
index b9b1e5c2b29048247910612448a5498cb4513b7f..fc3646c2c694a74fe6ac3f572704e70444637312 100644 (file)
@@ -102,7 +102,7 @@ err_reset:
        return rc;
 }
 
-static int __devexit tosa_bt_remove(struct platform_device *dev)
+static int tosa_bt_remove(struct platform_device *dev)
 {
        struct tosa_bt_data *data = dev->dev.platform_data;
        struct rfkill *rfk = platform_get_drvdata(dev);
@@ -125,7 +125,7 @@ static int __devexit tosa_bt_remove(struct platform_device *dev)
 
 static struct platform_driver tosa_bt_driver = {
        .probe = tosa_bt_probe,
-       .remove = __devexit_p(tosa_bt_remove),
+       .remove = tosa_bt_remove,
 
        .driver = {
                .name = "tosa-bt",
index 124bce6b4d7ba55df09bc262a3caf2acaf58b0fe..a301e61a55544c2ef6b889e59459bda68812ce90 100644 (file)
@@ -47,7 +47,7 @@
 #define REALVIEW_EB_USB_BASE           0x4F000000      /* USB */
 
 #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
-#define REALVIEW_EB11MP_PRIV_MEM_BASE  0x1F000000
+#define REALVIEW_EB11MP_PRIV_MEM_BASE  0x10100000
 #define REALVIEW_EB11MP_L220_BASE      0x10102000      /* L220 registers */
 #define REALVIEW_EB11MP_SYS_PLD_CTRL1  0xD8            /* Register offset for MPCore sysctl */
 #else
index d6b5073692d2fdda8db2656a032f374894e57463..44754230fdcc3e23098f1cfcacee1530af508da4 100644 (file)
 /*
  * Only define NR_IRQS if less than NR_IRQS_EB
  */
-#define NR_IRQS_EB             (IRQ_EB_GIC_START + 96)
+#define NR_IRQS_EB             (IRQ_EB_GIC_START + 128)
 
 #if defined(CONFIG_MACH_REALVIEW_EB) \
        && (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
index 57aee916bdb10cb50d220cd1b6ee152b05561778..3f40c61b6e0295f7b9911ed62cff3dae6484d79a 100644 (file)
@@ -62,7 +62,7 @@ static const struct rfkill_ops h1940bt_rfkill_ops = {
        .set_block = h1940bt_set_block,
 };
 
-static int __devinit h1940bt_probe(struct platform_device *pdev)
+static int h1940bt_probe(struct platform_device *pdev)
 {
        struct rfkill *rfk;
        int ret = 0;
index 5876c6ba7500d9f348533a59bfb520359c1e682f..45e74363aaa99a6db34a46f16cdcc10b7b169cf1 100644 (file)
@@ -93,7 +93,7 @@ static struct notifier_block osiris_dvs_nb = {
        .notifier_call  = osiris_dvs_notify,
 };
 
-static int __devinit osiris_dvs_probe(struct platform_device *pdev)
+static int osiris_dvs_probe(struct platform_device *pdev)
 {
        int ret;
 
@@ -126,7 +126,7 @@ err_nogpio:
        return ret;
 }
 
-static int __devexit osiris_dvs_remove(struct platform_device *pdev)
+static int osiris_dvs_remove(struct platform_device *pdev)
 {
        dev_info(&pdev->dev, "exiting\n");
 
@@ -167,7 +167,7 @@ static const struct dev_pm_ops osiris_dvs_pm = {
 
 static struct platform_driver osiris_dvs_driver = {
        .probe          = osiris_dvs_probe,
-       .remove         = __devexit_p(osiris_dvs_remove),
+       .remove         = osiris_dvs_remove,
        .driver         = {
                .name   = "osiris-dvs",
                .owner  = THIS_MODULE,
index 1a6f8577744926fc593ec6a2a8aea1b8c509850e..803711e283b233d609e7172b7d4678da724a682f 100644 (file)
@@ -149,25 +149,6 @@ static struct clk init_clocks_off[] = {
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C6410_CLKCON_PCLK_I2C1,
        }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.0",
-               .parent         = &clk_p,
-               .enable         = s3c64xx_pclk_ctrl,
-               .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.1",
-               .parent         = &clk_p,
-               .enable         = s3c64xx_pclk_ctrl,
-               .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
-       }, {
-#ifdef CONFIG_CPU_S3C6410
-               .name           = "iis",
-               .parent         = &clk_p,
-               .enable         = s3c64xx_pclk_ctrl,
-               .ctrlbit        = S3C6410_CLKCON_PCLK_IIS2,
-       }, {
-#endif
                .name           = "keypad",
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
@@ -337,6 +318,32 @@ static struct clk clk_48m_spi1 = {
        .ctrlbit        = S3C_CLKCON_SCLK_SPI1_48,
 };
 
+static struct clk clk_i2s0 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.0",
+       .parent         = &clk_p,
+       .enable         = s3c64xx_pclk_ctrl,
+       .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
+};
+
+static struct clk clk_i2s1 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.1",
+       .parent         = &clk_p,
+       .enable         = s3c64xx_pclk_ctrl,
+       .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
+};
+
+#ifdef CONFIG_CPU_S3C6410
+static struct clk clk_i2s2 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.2",
+       .parent         = &clk_p,
+       .enable         = s3c64xx_pclk_ctrl,
+       .ctrlbit        = S3C6410_CLKCON_PCLK_IIS2,
+};
+#endif
+
 static struct clk init_clocks[] = {
        {
                .name           = "lcd",
@@ -660,6 +667,7 @@ static struct clksrc_sources clkset_audio1 = {
        .nr_sources     = ARRAY_SIZE(clkset_audio1_list),
 };
 
+#ifdef CONFIG_CPU_S3C6410
 static struct clk *clkset_audio2_list[] = {
        [0] = &clk_mout_epll.clk,
        [1] = &clk_dout_mpll,
@@ -672,6 +680,7 @@ static struct clksrc_sources clkset_audio2 = {
        .sources        = clkset_audio2_list,
        .nr_sources     = ARRAY_SIZE(clkset_audio2_list),
 };
+#endif
 
 static struct clksrc_clk clksrcs[] = {
        {
@@ -683,36 +692,6 @@ static struct clksrc_clk clksrcs[] = {
                .reg_src        = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
                .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
                .sources        = &clkset_uhost,
-       }, {
-               .clk    = {
-                       .name           = "audio-bus",
-                       .devname        = "samsung-i2s.0",
-                       .ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
-                       .enable         = s3c64xx_sclk_ctrl,
-               },
-               .reg_src        = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
-               .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
-               .sources        = &clkset_audio0,
-       }, {
-               .clk    = {
-                       .name           = "audio-bus",
-                       .devname        = "samsung-i2s.1",
-                       .ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
-                       .enable         = s3c64xx_sclk_ctrl,
-               },
-               .reg_src        = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
-               .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
-               .sources        = &clkset_audio1,
-       }, {
-               .clk    = {
-                       .name           = "audio-bus",
-                       .devname        = "samsung-i2s.2",
-                       .ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
-                       .enable         = s3c64xx_sclk_ctrl,
-               },
-               .reg_src        = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
-               .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
-               .sources        = &clkset_audio2,
        }, {
                .clk    = {
                        .name           = "irda-bus",
@@ -805,6 +784,43 @@ static struct clksrc_clk clk_sclk_spi1 = {
        .sources = &clkset_spi_mmc,
 };
 
+static struct clksrc_clk clk_audio_bus0 = {
+       .clk    = {
+               .name           = "audio-bus",
+               .devname        = "samsung-i2s.0",
+               .ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
+               .enable         = s3c64xx_sclk_ctrl,
+       },
+       .reg_src        = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
+       .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
+       .sources        = &clkset_audio0,
+};
+
+static struct clksrc_clk clk_audio_bus1 = {
+       .clk    = {
+               .name           = "audio-bus",
+               .devname        = "samsung-i2s.1",
+               .ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
+               .enable         = s3c64xx_sclk_ctrl,
+       },
+       .reg_src        = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
+       .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
+       .sources        = &clkset_audio1,
+};
+
+#ifdef CONFIG_CPU_S3C6410
+static struct clksrc_clk clk_audio_bus2 = {
+       .clk    = {
+               .name           = "audio-bus",
+               .devname        = "samsung-i2s.2",
+               .ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
+               .enable         = s3c64xx_sclk_ctrl,
+       },
+       .reg_src        = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
+       .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
+       .sources        = &clkset_audio2,
+};
+#endif
 /* Clock initialisation code */
 
 static struct clksrc_clk *init_parents[] = {
@@ -820,6 +836,8 @@ static struct clksrc_clk *clksrc_cdev[] = {
        &clk_sclk_mmc2,
        &clk_sclk_spi0,
        &clk_sclk_spi1,
+       &clk_audio_bus0,
+       &clk_audio_bus1,
 };
 
 static struct clk *clk_cdev[] = {
@@ -828,6 +846,8 @@ static struct clk *clk_cdev[] = {
        &clk_hsmmc2,
        &clk_48m_spi0,
        &clk_48m_spi1,
+       &clk_i2s0,
+       &clk_i2s1,
 };
 
 static struct clk_lookup s3c64xx_clk_lookup[] = {
@@ -844,6 +864,14 @@ static struct clk_lookup s3c64xx_clk_lookup[] = {
        CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
        CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus0.clk),
+       CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
+       CLKDEV_INIT("samsung-i2s.1", "i2s_opclk1", &clk_audio_bus1.clk),
+#ifdef CONFIG_CPU_S3C6410
+       CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
+       CLKDEV_INIT("samsung-i2s.2", "i2s_opclk1", &clk_audio_bus2.clk),
+#endif
 };
 
 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
index 35f3e07eaccc494729b82582c82062cd4bea0a6a..e367e87bbc2966d039eba15bcf90224d0010e105 100644 (file)
 #include <linux/platform_data/asoc-s3c.h>
 #include <plat/gpio-cfg.h>
 
-static const char *rclksrc[] = {
-       [0] = "iis",
-       [1] = "audio-bus",
-};
-
 static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
 {
        unsigned int base;
@@ -64,11 +59,6 @@ static struct resource s3c64xx_iis0_resource[] = {
 
 static struct s3c_audio_pdata i2sv3_pdata = {
        .cfg_gpio = s3c64xx_i2s_cfg_gpio,
-       .type = {
-               .i2s = {
-                       .src_clk = rclksrc,
-               },
-       },
 };
 
 struct platform_device s3c64xx_device_iis0 = {
@@ -110,7 +100,6 @@ static struct s3c_audio_pdata i2sv4_pdata = {
        .type = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN,
-                       .src_clk = rclksrc,
                },
        },
 };
index c6d8dba9062330f181e6fb03719295cb691587f1..755c0bb119f4c1e195c61281d776dcb92a50e6d8 100644 (file)
@@ -47,7 +47,7 @@ static struct spi_board_info wm1253_devs[] = {
                .bus_num        = 0,
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
-               .irq            = S3C_EINT(5),
+               .irq            = S3C_EINT(4),
                .controller_data = &wm0010_spi_csinfo,
                .platform_data = &wm0010_pdata,
        },
@@ -290,7 +290,7 @@ static const struct i2c_board_info wm2200_i2c[] = {
          .platform_data = &wm2200_pdata, },
 };
 
-static __devinitdata const struct {
+static const struct {
        u8 id;
        u8 rev;
        const char *name;
@@ -343,8 +343,8 @@ static __devinitdata const struct {
          .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
 };
 
-static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
-                                        const struct i2c_device_id *i2c_id)
+static int wlf_gf_module_probe(struct i2c_client *i2c,
+                              const struct i2c_device_id *i2c_id)
 {
        int ret, i, j, id, rev;
 
index cdde249166b5011cb1d075fed3caa212963427d5..bf6311a28f3db1c7a014d92ac75361ca20534f8c 100644 (file)
@@ -171,7 +171,7 @@ static struct fb_videomode crag6410_lcd_timing = {
 };
 
 /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata crag6410_lcd_pdata __devinitdata = {
+static struct s3c_fb_platdata crag6410_lcd_pdata = {
        .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
        .vtiming        = &crag6410_lcd_timing,
        .win[0]         = &crag6410_fb_win0,
@@ -181,7 +181,7 @@ static struct s3c_fb_platdata crag6410_lcd_pdata __devinitdata = {
 
 /* 2x6 keypad */
 
-static uint32_t crag6410_keymap[] __devinitdata = {
+static uint32_t crag6410_keymap[] = {
        /* KEY(row, col, keycode) */
        KEY(0, 0, KEY_VOLUMEUP),
        KEY(0, 1, KEY_HOME),
@@ -197,12 +197,12 @@ static uint32_t crag6410_keymap[] __devinitdata = {
        KEY(1, 5, KEY_CAMERA),
 };
 
-static struct matrix_keymap_data crag6410_keymap_data __devinitdata = {
+static struct matrix_keymap_data crag6410_keymap_data = {
        .keymap         = crag6410_keymap,
        .keymap_size    = ARRAY_SIZE(crag6410_keymap),
 };
 
-static struct samsung_keypad_platdata crag6410_keypad_data __devinitdata = {
+static struct samsung_keypad_platdata crag6410_keypad_data = {
        .keymap_data    = &crag6410_keymap_data,
        .rows           = 2,
        .cols           = 6,
@@ -407,11 +407,11 @@ static struct wm831x_buckv_pdata vddarm_pdata = {
        .dvs_gpio = S3C64XX_GPK(0),
 };
 
-static struct regulator_consumer_supply vddarm_consumers[] __devinitdata = {
+static struct regulator_consumer_supply vddarm_consumers[] = {
        REGULATOR_SUPPLY("vddarm", NULL),
 };
 
-static struct regulator_init_data vddarm __devinitdata = {
+static struct regulator_init_data vddarm = {
        .constraints = {
                .name = "VDDARM",
                .min_uV = 1000000,
@@ -425,11 +425,11 @@ static struct regulator_init_data vddarm __devinitdata = {
        .driver_data = &vddarm_pdata,
 };
 
-static struct regulator_consumer_supply vddint_consumers[] __devinitdata = {
+static struct regulator_consumer_supply vddint_consumers[] = {
        REGULATOR_SUPPLY("vddint", NULL),
 };
 
-static struct regulator_init_data vddint __devinitdata = {
+static struct regulator_init_data vddint = {
        .constraints = {
                .name = "VDDINT",
                .min_uV = 1000000,
@@ -442,27 +442,27 @@ static struct regulator_init_data vddint __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem __devinitdata = {
+static struct regulator_init_data vddmem = {
        .constraints = {
                .name = "VDDMEM",
                .always_on = 1,
        },
 };
 
-static struct regulator_init_data vddsys __devinitdata = {
+static struct regulator_init_data vddsys = {
        .constraints = {
                .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
                .always_on = 1,
        },
 };
 
-static struct regulator_consumer_supply vddmmc_consumers[] __devinitdata = {
+static struct regulator_consumer_supply vddmmc_consumers[] = {
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
 };
 
-static struct regulator_init_data vddmmc __devinitdata = {
+static struct regulator_init_data vddmmc = {
        .constraints = {
                .name = "VDDMMC,UH",
                .always_on = 1,
@@ -472,7 +472,7 @@ static struct regulator_init_data vddmmc __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotgi __devinitdata = {
+static struct regulator_init_data vddotgi = {
        .constraints = {
                .name = "VDDOTGi",
                .always_on = 1,
@@ -480,7 +480,7 @@ static struct regulator_init_data vddotgi __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotg __devinitdata = {
+static struct regulator_init_data vddotg = {
        .constraints = {
                .name = "VDDOTG",
                .always_on = 1,
@@ -488,7 +488,7 @@ static struct regulator_init_data vddotg __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddhi __devinitdata = {
+static struct regulator_init_data vddhi = {
        .constraints = {
                .name = "VDDHI",
                .always_on = 1,
@@ -496,7 +496,7 @@ static struct regulator_init_data vddhi __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddadc __devinitdata = {
+static struct regulator_init_data vddadc = {
        .constraints = {
                .name = "VDDADC,VDDDAC",
                .always_on = 1,
@@ -504,7 +504,7 @@ static struct regulator_init_data vddadc __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem0 __devinitdata = {
+static struct regulator_init_data vddmem0 = {
        .constraints = {
                .name = "VDDMEM0",
                .always_on = 1,
@@ -512,7 +512,7 @@ static struct regulator_init_data vddmem0 __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddpll __devinitdata = {
+static struct regulator_init_data vddpll = {
        .constraints = {
                .name = "VDDPLL",
                .always_on = 1,
@@ -520,7 +520,7 @@ static struct regulator_init_data vddpll __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddlcd __devinitdata = {
+static struct regulator_init_data vddlcd = {
        .constraints = {
                .name = "VDDLCD",
                .always_on = 1,
@@ -528,7 +528,7 @@ static struct regulator_init_data vddlcd __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddalive __devinitdata = {
+static struct regulator_init_data vddalive = {
        .constraints = {
                .name = "VDDALIVE",
                .always_on = 1,
@@ -536,28 +536,28 @@ static struct regulator_init_data vddalive __devinitdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct wm831x_backup_pdata banff_backup_pdata __devinitdata = {
+static struct wm831x_backup_pdata banff_backup_pdata = {
        .charger_enable = 1,
        .vlim = 2500,  /* mV */
        .ilim = 200,   /* uA */
 };
 
-static struct wm831x_status_pdata banff_red_led __devinitdata = {
+static struct wm831x_status_pdata banff_red_led = {
        .name = "banff:red:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_status_pdata banff_green_led __devinitdata = {
+static struct wm831x_status_pdata banff_green_led = {
        .name = "banff:green:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_touch_pdata touch_pdata __devinitdata = {
+static struct wm831x_touch_pdata touch_pdata = {
        .data_irq = S3C_EINT(26),
        .pd_irq = S3C_EINT(27),
 };
 
-static struct wm831x_pdata crag_pmic_pdata __devinitdata = {
+static struct wm831x_pdata crag_pmic_pdata = {
        .wm831x_num = 1,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
@@ -601,7 +601,7 @@ static struct wm831x_pdata crag_pmic_pdata __devinitdata = {
        .touch = &touch_pdata,
 };
 
-static struct i2c_board_info i2c_devs0[] __devinitdata = {
+static struct i2c_board_info i2c_devs0[] = {
        { I2C_BOARD_INFO("24c08", 0x50), },
        { I2C_BOARD_INFO("tca6408", 0x20),
          .platform_data = &crag6410_pca_data,
@@ -616,13 +616,13 @@ static struct s3c2410_platform_i2c i2c0_pdata = {
        .frequency = 400000,
 };
 
-static struct regulator_consumer_supply pvdd_1v2_consumers[] __devinitdata = {
+static struct regulator_consumer_supply pvdd_1v2_consumers[] = {
        REGULATOR_SUPPLY("DCVDD", "spi0.0"),
        REGULATOR_SUPPLY("AVDD", "spi0.0"),
        REGULATOR_SUPPLY("AVDD", "spi0.1"),
 };
 
-static struct regulator_init_data pvdd_1v2 __devinitdata = {
+static struct regulator_init_data pvdd_1v2 = {
        .constraints = {
                .name = "PVDD_1V2",
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -632,7 +632,7 @@ static struct regulator_init_data pvdd_1v2 __devinitdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v2_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
+static struct regulator_consumer_supply pvdd_1v8_consumers[] = {
        REGULATOR_SUPPLY("LDOVDD", "1-001a"),
        REGULATOR_SUPPLY("PLLVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "1-001a"),
@@ -664,7 +664,7 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("CPVDD", "wm5110-codec"),
 };
 
-static struct regulator_init_data pvdd_1v8 __devinitdata = {
+static struct regulator_init_data pvdd_1v8 = {
        .constraints = {
                .name = "PVDD_1V8",
                .always_on = 1,
@@ -674,12 +674,12 @@ static struct regulator_init_data pvdd_1v8 __devinitdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_3v3_consumers[] __devinitdata = {
+static struct regulator_consumer_supply pvdd_3v3_consumers[] = {
        REGULATOR_SUPPLY("MICVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD1", "1-001a"),
 };
 
-static struct regulator_init_data pvdd_3v3 __devinitdata = {
+static struct regulator_init_data pvdd_3v3 = {
        .constraints = {
                .name = "PVDD_3V3",
                .always_on = 1,
@@ -689,7 +689,7 @@ static struct regulator_init_data pvdd_3v3 __devinitdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
 };
 
-static struct wm831x_pdata glenfarclas_pmic_pdata __devinitdata = {
+static struct wm831x_pdata glenfarclas_pmic_pdata = {
        .wm831x_num = 2,
        .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
        .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
@@ -721,7 +721,7 @@ static struct wm1250_ev1_pdata wm1250_ev1_pdata = {
        },
 };
 
-static struct i2c_board_info i2c_devs1[] __devinitdata = {
+static struct i2c_board_info i2c_devs1[] = {
        { I2C_BOARD_INFO("wm8311", 0x34),
          .irq = S3C_EINT(0),
          .platform_data = &glenfarclas_pmic_pdata },
index 7feb426fc202d10be8f74a8992b5de212b6e4ba0..d2e1a16690bd5807f961d6804b61dddfeb029fc7 100644 (file)
@@ -338,8 +338,10 @@ int __init s3c64xx_pm_init(void)
        for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++)
                pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false);
 
+#ifdef CONFIG_S3C_DEV_FB
        if (dev_get_platdata(&s3c_device_fb.dev))
                pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev);
+#endif
 
        return 0;
 }
index 000445596ec4ff5a3577e0d034e40c3574a882ae..5112371079d0a3f27f30c044758424d7486ee3be 100644 (file)
@@ -242,12 +242,6 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 25),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.0",
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p64x0_pclk_ctrl,
-               .ctrlbit        = (1 << 26),
        }, {
                .name           = "dsim",
                .parent         = &clk_pclk_low.clk,
@@ -405,15 +399,6 @@ static struct clksrc_clk clksrcs[] = {
                .sources = &clkset_group1,
                .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
                .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_audio2",
-                       .ctrlbit        = (1 << 11),
-                       .enable         = s5p64x0_sclk_ctrl,
-               },
-               .sources = &clkset_audio,
-               .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
-               .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
        },
 };
 
@@ -464,6 +449,26 @@ static struct clksrc_clk clk_sclk_uclk = {
        .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
 };
 
+static struct clk clk_i2s0 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.0",
+       .parent         = &clk_pclk_low.clk,
+       .enable         = s5p64x0_pclk_ctrl,
+       .ctrlbit        = (1 << 26),
+};
+
+static struct clksrc_clk clk_audio_bus2 = {
+       .clk    = {
+               .name           = "sclk_audio2",
+               .devname        = "samsung-i2s.0",
+               .ctrlbit        = (1 << 11),
+               .enable         = s5p64x0_sclk_ctrl,
+       },
+       .sources = &clkset_audio,
+       .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
+       .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
+};
+
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
@@ -506,13 +511,18 @@ static struct clk dummy_apb_pclk = {
        .id             = -1,
 };
 
+static struct clk *clk_cdev[] = {
+       &clk_i2s0,
+};
+
 static struct clksrc_clk *clksrc_cdev[] = {
        &clk_sclk_uclk,
        &clk_sclk_spi0,
        &clk_sclk_spi1,
        &clk_sclk_mmc0,
        &clk_sclk_mmc1,
-       &clk_sclk_mmc2
+       &clk_sclk_mmc2,
+       &clk_audio_bus2,
 };
 
 static struct clk_lookup s5p6440_clk_lookup[] = {
@@ -524,6 +534,8 @@ static struct clk_lookup s5p6440_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus2.clk),
 };
 
 void __init_or_cpufreq s5p6440_setup_clocks(void)
@@ -596,12 +608,17 @@ static struct clk *clks[] __initdata = {
 void __init s5p6440_register_clocks(void)
 {
        int ptr;
+       unsigned int cnt;
 
        s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+       s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
+       for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
+               s3c_disable_clocks(clk_cdev[cnt], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
        for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
index f3e0ef3d27c9f3d3ba60cc5d053066b0e3af1092..154dea702d70a935901a078e8d67c487b6ca4b27 100644 (file)
@@ -246,24 +246,6 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 22),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.0",
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p64x0_pclk_ctrl,
-               .ctrlbit        = (1 << 26),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.1",
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p64x0_pclk_ctrl,
-               .ctrlbit        = (1 << 15),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.2",
-               .parent         = &clk_pclk_low.clk,
-               .enable         = s5p64x0_pclk_ctrl,
-               .ctrlbit        = (1 << 16),
        }, {
                .name           = "i2c",
                .devname        = "s3c2440-i2c.1",
@@ -402,6 +384,7 @@ static struct clksrc_sources clkset_sclk_audio0 = {
 static struct clksrc_clk clk_sclk_audio0 = {
        .clk            = {
                .name           = "audio-bus",
+               .devname        = "samsung-i2s.0",
                .enable         = s5p64x0_sclk_ctrl,
                .ctrlbit        = (1 << 8),
                .parent         = &clk_dout_epll.clk,
@@ -549,6 +532,36 @@ static struct clksrc_clk clk_sclk_spi1 = {
        .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
 };
 
+static struct clk clk_i2s0 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.0",
+       .parent         = &clk_pclk_low.clk,
+       .enable         = s5p64x0_pclk_ctrl,
+       .ctrlbit        = (1 << 26),
+};
+
+static struct clk clk_i2s1 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.1",
+       .parent         = &clk_pclk_low.clk,
+       .enable         = s5p64x0_pclk_ctrl,
+       .ctrlbit        = (1 << 15),
+};
+
+static struct clk clk_i2s2 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.2",
+       .parent         = &clk_pclk_low.clk,
+       .enable         = s5p64x0_pclk_ctrl,
+       .ctrlbit        = (1 << 16),
+};
+
+static struct clk *clk_cdev[] = {
+       &clk_i2s0,
+       &clk_i2s1,
+       &clk_i2s2,
+};
+
 static struct clksrc_clk *clksrc_cdev[] = {
        &clk_sclk_uclk,
        &clk_sclk_spi0,
@@ -556,6 +569,7 @@ static struct clksrc_clk *clksrc_cdev[] = {
        &clk_sclk_mmc0,
        &clk_sclk_mmc1,
        &clk_sclk_mmc2,
+       &clk_sclk_audio0,
 };
 
 static struct clk_lookup s5p6450_clk_lookup[] = {
@@ -567,6 +581,10 @@ static struct clk_lookup s5p6450_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_sclk_audio0.clk),
+       CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
+       CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 };
 
 /* Clock initialization code */
@@ -584,7 +602,6 @@ static struct clksrc_clk *sysclks[] = {
        &clk_pclk,
        &clk_hclk_low,
        &clk_pclk_low,
-       &clk_sclk_audio0,
 };
 
 static struct clk dummy_apb_pclk = {
@@ -661,10 +678,16 @@ void __init_or_cpufreq s5p6450_setup_clocks(void)
 void __init s5p6450_register_clocks(void)
 {
        int ptr;
+       unsigned int cnt;
 
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+
+       s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
+       for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
+               s3c_disable_clocks(clk_cdev[cnt], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
        for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
index a0d6edfd23a07f39ed5a28cfdadeba918fafeebb..723d4773c3238050467b4f2defbb15d283ee731d 100644 (file)
 #include <mach/dma.h>
 #include <mach/irqs.h>
 
-static const char *rclksrc[] = {
-       [0] = "iis",
-       [1] = "sclk_audio2",
-};
-
 static int s5p6440_cfg_i2s(struct platform_device *pdev)
 {
        switch (pdev->id) {
@@ -45,7 +40,6 @@ static struct s3c_audio_pdata s5p6440_i2s_pdata = {
        .type = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN,
-                       .src_clk = rclksrc,
                },
        },
 };
@@ -93,7 +87,6 @@ static struct s3c_audio_pdata s5p6450_i2s0_pdata = {
        .type = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN,
-                       .src_clk = rclksrc,
                },
        },
 };
@@ -110,11 +103,6 @@ struct platform_device s5p6450_device_iis0 = {
 
 static struct s3c_audio_pdata s5p6450_i2s_pdata = {
        .cfg_gpio = s5p6450_cfg_i2s,
-       .type = {
-               .i2s = {
-                       .src_clk = rclksrc,
-               },
-       },
 };
 
 static struct resource s5p6450_i2s1_resource[] = {
index 926219791f0dcd1bbaba3b49f5b690f89ab70975..a206dc35eff1d8e7c0da7928048182ab7d0119a2 100644 (file)
@@ -605,24 +605,6 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 13),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.0",
-               .parent         = &clk_div_pclkd1.clk,
-               .enable         = s5pc100_d1_5_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.1",
-               .parent         = &clk_div_pclkd1.clk,
-               .enable         = s5pc100_d1_5_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.2",
-               .parent         = &clk_div_pclkd1.clk,
-               .enable         = s5pc100_d1_5_ctrl,
-               .ctrlbit        = (1 << 2),
        }, {
                .name           = "ac97",
                .parent         = &clk_div_pclkd1.clk,
@@ -724,6 +706,30 @@ static struct clk clk_48m_spi2 = {
        .ctrlbit        = (1 << 9),
 };
 
+static struct clk clk_i2s0 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.0",
+       .parent         = &clk_div_pclkd1.clk,
+       .enable         = s5pc100_d1_5_ctrl,
+       .ctrlbit        = (1 << 0),
+};
+
+static struct clk clk_i2s1 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.1",
+       .parent         = &clk_div_pclkd1.clk,
+       .enable         = s5pc100_d1_5_ctrl,
+       .ctrlbit        = (1 << 1),
+};
+
+static struct clk clk_i2s2 = {
+       .name           = "iis",
+       .devname        = "samsung-i2s.2",
+       .parent         = &clk_div_pclkd1.clk,
+       .enable         = s5pc100_d1_5_ctrl,
+       .ctrlbit        = (1 << 2),
+};
+
 static struct clk clk_vclk54m = {
        .name           = "vclk_54m",
        .rate           = 54000000,
@@ -1154,6 +1160,9 @@ static struct clk *clk_cdev[] = {
        &clk_48m_spi0,
        &clk_48m_spi1,
        &clk_48m_spi2,
+       &clk_i2s0,
+       &clk_i2s1,
+       &clk_i2s2,
 };
 
 static struct clksrc_clk *clksrc_cdev[] = {
@@ -1321,6 +1330,9 @@ static struct clk_lookup s5pc100_clk_lookup[] = {
        CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
        CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
+       CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+       CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
+       CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 };
 
 void __init s5pc100_register_clocks(void)
index 1cc252cef26843a133251ce0ff703fa5ed599ecd..46f488b093916699a5571862206293350cf19f1d 100644 (file)
@@ -39,18 +39,12 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev)
        return 0;
 }
 
-static const char *rclksrc_v5[] = {
-       [0] = "iis",
-       [1] = "i2sclkd2",
-};
-
 static struct s3c_audio_pdata i2sv5_pdata = {
        .cfg_gpio = s5pc100_cfg_i2s,
        .type = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
                                         | QUIRK_NEED_RSTCLR,
-                       .src_clk = rclksrc_v5,
                },
        },
 };
@@ -72,18 +66,8 @@ struct platform_device s5pc100_device_iis0 = {
        },
 };
 
-static const char *rclksrc_v3[] = {
-       [0] = "iis",
-       [1] = "sclk_audio",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
        .cfg_gpio = s5pc100_cfg_i2s,
-       .type = {
-               .i2s = {
-                       .src_clk = rclksrc_v3,
-               },
-       },
 };
 
 static struct resource s5pc100_iis1_resource[] = {
index 0a5480bbcbd596962c94bea2397698b01ada482e..addfb165c13d050da4bc48a6c08a57c342b36c78 100644 (file)
 #include <mach/irqs.h>
 #include <mach/regs-audss.h>
 
-static const char *rclksrc[] = {
-       [0] = "busclk",
-       [1] = "i2sclk",
-};
-
 static int s5pv210_cfg_i2s(struct platform_device *pdev)
 {
        /* configure GPIO for i2s port */
@@ -52,7 +47,6 @@ static struct s3c_audio_pdata i2sv5_pdata = {
                .i2s = {
                        .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
                                         | QUIRK_NEED_RSTCLR,
-                       .src_clk = rclksrc,
                        .idma_addr = S5PV210_AUDSS_INT_MEM,
                },
        },
@@ -75,18 +69,8 @@ struct platform_device s5pv210_device_iis0 = {
        },
 };
 
-static const char *rclksrc_v3[] = {
-       [0] = "iis",
-       [1] = "audio-bus",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
        .cfg_gpio = s5pv210_cfg_i2s,
-       .type = {
-               .i2s = {
-                       .src_clk = rclksrc_v3,
-               },
-       },
 };
 
 static struct resource s5pv210_iis1_resource[] = {
index 7f07f08d896804c71ae161aad4ad6b5d1588e48f..b143c4659346d841d7249fc358b12272061e71af 100644 (file)
@@ -130,7 +130,7 @@ void jornada_ssp_end(void)
 };
 EXPORT_SYMBOL(jornada_ssp_end);
 
-static int __devinit jornada_ssp_probe(struct platform_device *dev)
+static int jornada_ssp_probe(struct platform_device *dev)
 {
        int ret;
 
index 88be0474f3d720a0ba2384536bd01516c2f451de..400f803320461320dbbe1fc65635f977355966c7 100644 (file)
@@ -154,7 +154,7 @@ static u_int neponset_get_mctrl(struct uart_port *port)
        return ret;
 }
 
-static struct sa1100_port_fns neponset_port_fns __devinitdata = {
+static struct sa1100_port_fns neponset_port_fns = {
        .set_mctrl      = neponset_set_mctrl,
        .get_mctrl      = neponset_get_mctrl,
 };
@@ -233,7 +233,7 @@ static struct sa1111_platform_data sa1111_info = {
        .disable_devs   = SA1111_DEVID_PS2_MSE,
 };
 
-static int __devinit neponset_probe(struct platform_device *dev)
+static int neponset_probe(struct platform_device *dev)
 {
        struct neponset_drvdata *d;
        struct resource *nep_res, *sa1111_res, *smc91x_res;
@@ -368,7 +368,7 @@ static int __devinit neponset_probe(struct platform_device *dev)
        return ret;
 }
 
-static int __devexit neponset_remove(struct platform_device *dev)
+static int neponset_remove(struct platform_device *dev)
 {
        struct neponset_drvdata *d = platform_get_drvdata(dev);
        int irq = platform_get_irq(dev, 0);
@@ -420,7 +420,7 @@ static const struct dev_pm_ops neponset_pm_ops = {
 
 static struct platform_driver neponset_device_driver = {
        .probe          = neponset_probe,
-       .remove         = __devexit_p(neponset_remove),
+       .remove         = neponset_remove,
        .driver         = {
                .name   = "neponset",
                .owner  = THIS_MODULE,
index 9be910f7920b9d464f49bcb0e40c08f9ddf8e5cb..1dc8a92e5a5fd4d4d5ba76b67cdeab0f58d81b23 100644 (file)
@@ -80,8 +80,8 @@ static void __init sunxi_dt_init(void)
 }
 
 static const char * const sunxi_board_dt_compat[] = {
-       "allwinner,sun4i",
-       "allwinner,sun5i",
+       "allwinner,sun4i-a10",
+       "allwinner,sun5i-a13",
        NULL,
 };
 
index 53d085871798ef62afca5f3905dfc288f8ca8f34..bffcd643d7a3eb14ef094d537444271344280a93 100644 (file)
@@ -331,7 +331,7 @@ static struct pci_ops tegra_pcie_ops = {
        .write  = tegra_pcie_write_conf,
 };
 
-static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev)
+static void tegra_pcie_fixup_bridge(struct pci_dev *dev)
 {
        u16 reg;
 
@@ -345,7 +345,7 @@ static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge);
 
 /* Tegra PCIE root complex wrongly reports device class */
-static void __devinit tegra_pcie_fixup_class(struct pci_dev *dev)
+static void tegra_pcie_fixup_class(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
@@ -353,7 +353,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
 
 /* Tegra PCIE requires relaxed ordering */
-static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
+static void tegra_pcie_relax_enable(struct pci_dev *dev)
 {
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
 }
index 837c7b9ea63b1c6561a6fbb13397f36da2ff75a3..e18aa2f83ebf3041cd12d31a06c5bb027820df53 100644 (file)
@@ -268,7 +268,7 @@ static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
 }
 #endif
 
-static struct tegra_emc_pdata __devinit *tegra_emc_fill_pdata(struct platform_device *pdev)
+static struct tegra_emc_pdata *tegra_emc_fill_pdata(struct platform_device *pdev)
 {
        struct clk *c = clk_get_sys(NULL, "emc");
        struct tegra_emc_pdata *pdata;
@@ -296,7 +296,7 @@ static struct tegra_emc_pdata __devinit *tegra_emc_fill_pdata(struct platform_de
        return pdata;
 }
 
-static int __devinit tegra_emc_probe(struct platform_device *pdev)
+static int tegra_emc_probe(struct platform_device *pdev)
 {
        struct tegra_emc_pdata *pdata;
        struct resource *res;
@@ -333,7 +333,7 @@ static int __devinit tegra_emc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_emc_of_match[] __devinitdata = {
+static struct of_device_id tegra_emc_of_match[] = {
        { .compatible = "nvidia,tegra20-emc", },
        { },
 };
index 03f79361259400596a790949073e1ce617e99bff..2785cb67b5e81025a55b387d96b9bc0ae64f9d34 100644 (file)
@@ -222,7 +222,7 @@ static ssize_t dummy_looptest(struct device *dev,
 
 static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL);
 
-static int __devinit pl022_dummy_probe(struct spi_device *spi)
+static int pl022_dummy_probe(struct spi_device *spi)
 {
        struct dummy *p_dummy;
        int status;
@@ -251,7 +251,7 @@ out_dev_create_looptest_failed:
        return status;
 }
 
-static int __devexit pl022_dummy_remove(struct spi_device *spi)
+static int pl022_dummy_remove(struct spi_device *spi)
 {
        struct dummy *p_dummy = dev_get_drvdata(&spi->dev);
 
@@ -269,7 +269,7 @@ static struct spi_driver pl022_dummy_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = pl022_dummy_probe,
-       .remove = __devexit_p(pl022_dummy_remove),
+       .remove = pl022_dummy_remove,
 };
 
 static int __init pl022_init_dummy(void)
index db0bb75e2c7620e9a7964c40d6a428cd66f9d4a8..5b286e06474ce481ff019f302bf1a66aec635687 100644 (file)
@@ -285,7 +285,8 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
        OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
        /* Requires device name bindings. */
-       OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
+       OF_DEV_AUXDATA("stericsson,nmk_pinctrl", U8500_PRCMU_BASE,
+               "pinctrl-db8500", NULL),
        /* Requires clock name and DMA bindings. */
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
                "ux500-msp-i2s.0", &msp0_platform_data),
index bf44c61bd1f682f203d1169528542a93b6482404..0fd771ca617b00ddf71bd676e7e3834ec87b0b6b 100644 (file)
@@ -25,7 +25,7 @@
  *  IRQ interrupts definitions are the same as the INT definitions
  *  held within platform.h
  */
-#define IRQ_VIC_START          0
+#define IRQ_VIC_START          32
 #define IRQ_WDOGINT            (IRQ_VIC_START + INT_WDOGINT)
 #define IRQ_SOFTINT            (IRQ_VIC_START + INT_SOFTINT)
 #define IRQ_COMMRx             (IRQ_VIC_START + INT_COMMRx)
 /*
  * Secondary interrupt controller
  */
-#define IRQ_SIC_START          32
+#define IRQ_SIC_START          64
 #define IRQ_SIC_MMCI0B                 (IRQ_SIC_START + SIC_INT_MMCI0B)
 #define IRQ_SIC_MMCI1B                 (IRQ_SIC_START + SIC_INT_MMCI1B)
 #define IRQ_SIC_KMI0           (IRQ_SIC_START + SIC_INT_KMI0)
 #define IRQ_SIC_PCI1           (IRQ_SIC_START + SIC_INT_PCI1)
 #define IRQ_SIC_PCI2           (IRQ_SIC_START + SIC_INT_PCI2)
 #define IRQ_SIC_PCI3           (IRQ_SIC_START + SIC_INT_PCI3)
-#define IRQ_SIC_END            63
+#define IRQ_SIC_END            95
 
 #define IRQ_GPIO0_START                (IRQ_SIC_END + 1)
 #define IRQ_GPIO0_END          (IRQ_GPIO0_START + 31)
index 99e63f5f99d179eeeafbae428bd82444adbee747..52d315b792c8e8bb1561b4ae703194a724e865e0 100644 (file)
@@ -42,7 +42,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
        bool "Enable A5 and A9 only errata work-arounds"
        default y
        select ARM_ERRATA_720789
-       select ARM_ERRATA_751472
        select PL310_ERRATA_753970 if CACHE_PL310
        help
          Provides common dependencies for Versatile Express platforms
index 6911b8b2745c5345ca2a5f4498c702ddd1bc6aad..c2f37390308a20b835d653dfbb0f64f28cc8ce40 100644 (file)
@@ -352,7 +352,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
                /* Unmapped register. */
                sync_reg_offset = L2X0_DUMMY_REG;
 #endif
-               outer_cache.set_debug = pl310_set_debug;
+               if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
+                       outer_cache.set_debug = pl310_set_debug;
                break;
        case L2X0_CACHE_ID_PART_L210:
                ways = (aux >> 13) & 0xf;
@@ -459,8 +460,8 @@ static void aurora_pa_range(unsigned long start, unsigned long end,
        unsigned long flags;
 
        raw_spin_lock_irqsave(&l2x0_lock, flags);
-       writel(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
-       writel(end, l2x0_base + offset);
+       writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
+       writel_relaxed(end, l2x0_base + offset);
        raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 
        cache_sync();
@@ -505,15 +506,21 @@ static void aurora_clean_range(unsigned long start, unsigned long end)
 
 static void aurora_flush_range(unsigned long start, unsigned long end)
 {
-       if (!l2_wt_override) {
-               start &= ~(CACHE_LINE_SIZE - 1);
-               end = ALIGN(end, CACHE_LINE_SIZE);
-               while (start != end) {
-                       unsigned long range_end = calc_range_end(start, end);
+       start &= ~(CACHE_LINE_SIZE - 1);
+       end = ALIGN(end, CACHE_LINE_SIZE);
+       while (start != end) {
+               unsigned long range_end = calc_range_end(start, end);
+               /*
+                * If L2 is forced to WT, the L2 will always be clean and we
+                * just need to invalidate.
+                */
+               if (l2_wt_override)
                        aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
-                                       AURORA_FLUSH_RANGE_REG);
-                       start = range_end;
-               }
+                                                       AURORA_INVAL_RANGE_REG);
+               else
+                       aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+                                                       AURORA_FLUSH_RANGE_REG);
+               start = range_end;
        }
 }
 
@@ -668,8 +675,9 @@ static void pl310_resume(void)
 static void aurora_resume(void)
 {
        if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
-               writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
-               writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
+               writel_relaxed(l2x0_saved_regs.aux_ctrl,
+                               l2x0_base + L2X0_AUX_CTRL);
+               writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
        }
 }
 
index cd956647c21a800d69ed3215a774b086fed008a1..7539ec27506585f3dd42b04f785c5edba39d1614 100644 (file)
@@ -44,8 +44,10 @@ ENDPROC(v7_flush_icache_all)
 ENTRY(v7_flush_dcache_louis)
        dmb                                     @ ensure ordering with previous memory accesses
        mrc     p15, 1, r0, c0, c0, 1           @ read clidr, r0 = clidr
-       ands    r3, r0, #0xe00000               @ extract LoUIS from clidr
-       mov     r3, r3, lsr #20                 @ r3 = LoUIS * 2
+       ALT_SMP(ands    r3, r0, #(7 << 21))     @ extract LoUIS from clidr
+       ALT_UP(ands     r3, r0, #(7 << 27))     @ extract LoUU from clidr
+       ALT_SMP(mov     r3, r3, lsr #20)        @ r3 = LoUIS * 2
+       ALT_UP(mov      r3, r3, lsr #26)        @ r3 = LoUU * 2
        moveq   pc, lr                          @ return if level == 0
        mov     r10, #0                         @ r10 (starting level) = 0
        b       flush_levels                    @ start flushing cache levels
index 6b2fb87c8698a99254bdd56c0e4c2bf146994da5..dda3904dc64c1cb3f7681cf20998397c1e103f76 100644 (file)
@@ -640,7 +640,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 
        if (is_coherent || nommu())
                addr = __alloc_simple_buffer(dev, size, gfp, &page);
-       else if (gfp & GFP_ATOMIC)
+       else if (!(gfp & __GFP_WAIT))
                addr = __alloc_from_pool(size, &page);
        else if (!IS_ENABLED(CONFIG_CMA))
                addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
@@ -774,25 +774,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
        size_t size, enum dma_data_direction dir,
        void (*op)(const void *, size_t, int))
 {
+       unsigned long pfn;
+       size_t left = size;
+
+       pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+       offset %= PAGE_SIZE;
+
        /*
         * A single sg entry may refer to multiple physically contiguous
         * pages.  But we still need to process highmem pages individually.
         * If highmem is not configured then the bulk of this loop gets
         * optimized out.
         */
-       size_t left = size;
        do {
                size_t len = left;
                void *vaddr;
 
+               page = pfn_to_page(pfn);
+
                if (PageHighMem(page)) {
-                       if (len + offset > PAGE_SIZE) {
-                               if (offset >= PAGE_SIZE) {
-                                       page += offset / PAGE_SIZE;
-                                       offset %= PAGE_SIZE;
-                               }
+                       if (len + offset > PAGE_SIZE)
                                len = PAGE_SIZE - offset;
-                       }
                        vaddr = kmap_high_get(page);
                        if (vaddr) {
                                vaddr += offset;
@@ -809,7 +811,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
                        op(vaddr, len, dir);
                }
                offset = 0;
-               page++;
+               pfn++;
                left -= len;
        } while (left);
 }
index 9f0610243bd6cd3357c847a5e5d392353579f471..ce328c7f5c94556cdda6021e8aef1b950aba5aa2 100644 (file)
@@ -283,7 +283,7 @@ static struct mem_type mem_types[] = {
        },
        [MT_MEMORY_SO] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_MT_UNCACHED,
+                               L_PTE_MT_UNCACHED | L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
                                PMD_SECT_UNCACHED | PMD_SECT_XN,
index 350f6a74992b9200618e52ed07a2ec9dd1bde407..3a3c015f8d5c33cb99357995b6d35790037e7f94 100644 (file)
@@ -169,6 +169,7 @@ __v7_ca15mp_setup:
        orreq   r0, r0, r10                     @ Enable CPU-specific SMP bits
        mcreq   p15, 0, r0, c1, c0, 1
 #endif
+       b       __v7_setup
 
 __v7_pj4b_setup:
 #ifdef CONFIG_CPU_PJ4B
@@ -245,7 +246,8 @@ __v7_setup:
        ldr     r10, =0x00000c08                @ Cortex-A8 primary part number
        teq     r0, r10
        bne     2f
-#ifdef CONFIG_ARM_ERRATA_430973
+#if defined(CONFIG_ARM_ERRATA_430973) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+
        teq     r5, #0x00100000                 @ only present in r1p*
        mrceq   p15, 0, r10, c1, c0, 1          @ read aux control register
        orreq   r10, r10, #(1 << 6)             @ set IBE to 1
index 9d9aa2f5512942af5b493bbfd3afae041b6be615..a14a78a2f149fa76e0167af8ec420c8152fe744f 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := sram.o dma.o fb.o counter_32k.o
+obj-y := sram.o dma.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
index f3771cdb98385917f95526e1fa0b69f443620f13..5b0b86bb34bb8d8ab22466e9f7a54c4937fddd5e 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
+#include <plat/counter-32k.h>
+
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
 #define OMAP2_32KSYNCNT_REV_OFF                0x0
 #define OMAP2_32KSYNCNT_REV_SCHEME     (0x3 << 30)
index 37a488aaa2ba95dffef6c017988df5fbb4769af5..4136b20cba3cc257534900894a1a8767baab585e 100644 (file)
@@ -2000,7 +2000,7 @@ void omap_dma_global_context_restore(void)
                        omap_clear_dma(ch);
 }
 
-static int __devinit omap_system_dma_probe(struct platform_device *pdev)
+static int omap_system_dma_probe(struct platform_device *pdev)
 {
        int ch, ret = 0;
        int dma_irq;
@@ -2116,7 +2116,7 @@ exit_dma_lch_fail:
        return ret;
 }
 
-static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+static int omap_system_dma_remove(struct platform_device *pdev)
 {
        int dma_irq;
 
@@ -2140,7 +2140,7 @@ static int __devexit omap_system_dma_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_system_dma_driver = {
        .probe          = omap_system_dma_probe,
-       .remove         = __devexit_p(omap_system_dma_remove),
+       .remove         = omap_system_dma_remove,
        .driver         = {
                .name   = "omap_dma_system"
        },
index 89585c2935549129fe8f8c72994a203fcdc77601..7b433f3bddca180102fb729bca15cd47317da3a6 100644 (file)
@@ -777,7 +777,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timers_active);
  * Called by driver framework at the end of device registration for all
  * timer devices.
  */
-static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
+static int omap_dm_timer_probe(struct platform_device *pdev)
 {
        unsigned long flags;
        struct omap_dm_timer *timer;
@@ -864,7 +864,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
  * In addition to freeing platform resources it also deletes the timer
  * entry from the local list.
  */
-static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+static int omap_dm_timer_remove(struct platform_device *pdev)
 {
        struct omap_dm_timer *timer;
        unsigned long flags;
@@ -891,26 +891,15 @@ MODULE_DEVICE_TABLE(of, omap_timer_match);
 
 static struct platform_driver omap_dm_timer_driver = {
        .probe  = omap_dm_timer_probe,
-       .remove = __devexit_p(omap_dm_timer_remove),
+       .remove = omap_dm_timer_remove,
        .driver = {
                .name   = "omap_timer",
                .of_match_table = of_match_ptr(omap_timer_match),
        },
 };
 
-static int __init omap_dm_timer_driver_init(void)
-{
-       return platform_driver_register(&omap_dm_timer_driver);
-}
-
-static void __exit omap_dm_timer_driver_exit(void)
-{
-       platform_driver_unregister(&omap_dm_timer_driver);
-}
-
 early_platform_init("earlytimer", &omap_dm_timer_driver);
-module_init(omap_dm_timer_driver_init);
-module_exit(omap_dm_timer_driver_exit);
+module_platform_driver(omap_dm_timer_driver);
 
 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
 MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
deleted file mode 100644 (file)
index a3367b7..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * File: arch/arm/plat-omap/fb.c
- *
- * Framebuffer device registration for TI OMAP platforms
- *
- * Copyright (C) 2006 Nokia Corporation
- * Author: Imre Deak <imre.deak@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 (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/memblock.h>
-#include <linux/io.h>
-#include <linux/omapfb.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach/map.h>
-
-#include <plat/cpu.h>
-
-#ifdef CONFIG_OMAP2_VRFB
-
-/*
- * The first memory resource is the register region for VRFB,
- * the rest are VRFB virtual memory areas for each VRFB context.
- */
-
-static const struct resource omap2_vrfb_resources[] = {
-       DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
-       DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
-       DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
-       DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
-       DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
-};
-
-static const struct resource omap3_vrfb_resources[] = {
-       DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
-       DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
-       DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
-       DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
-       DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
-       DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
-       DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
-       DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
-       DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
-       DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
-       DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
-       DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
-       DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
-};
-
-static int __init omap_init_vrfb(void)
-{
-       struct platform_device *pdev;
-       const struct resource *res;
-       unsigned int num_res;
-
-       if (cpu_is_omap24xx()) {
-               res = omap2_vrfb_resources;
-               num_res = ARRAY_SIZE(omap2_vrfb_resources);
-       } else if (cpu_is_omap34xx()) {
-               res = omap3_vrfb_resources;
-               num_res = ARRAY_SIZE(omap3_vrfb_resources);
-       } else {
-               return 0;
-       }
-
-       pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
-                       res, num_res, NULL, 0);
-
-       if (IS_ERR(pdev))
-               return PTR_ERR(pdev);
-       else
-               return 0;
-}
-
-arch_initcall(omap_init_vrfb);
-#endif
-
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static bool omapfb_lcd_configured;
-static struct omapfb_platform_data omapfb_config;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
-       .name           = "omapfb",
-       .id             = -1,
-       .dev = {
-               .dma_mask               = &omap_fb_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = &omapfb_config,
-       },
-       .num_resources = 0,
-};
-
-void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
-{
-       omapfb_config.lcd = *config;
-       omapfb_lcd_configured = true;
-}
-
-static int __init omap_init_fb(void)
-{
-       /*
-        * If the board file has not set the lcd config with
-        * omapfb_set_lcd_config(), don't bother registering the omapfb device
-        */
-       if (!omapfb_lcd_configured)
-               return 0;
-
-       return platform_device_register(&omap_fb_device);
-}
-
-arch_initcall(omap_init_fb);
-
-#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-static struct omapfb_platform_data omapfb_config;
-
-static struct platform_device omap_fb_device = {
-       .name           = "omapfb",
-       .id             = -1,
-       .dev = {
-               .dma_mask               = &omap_fb_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = &omapfb_config,
-       },
-       .num_resources = 0,
-};
-
-static int __init omap_init_fb(void)
-{
-       return platform_device_register(&omap_fb_device);
-}
-
-arch_initcall(omap_init_fb);
-
-#else
-
-void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
-{
-}
-
-#endif
index b4516aba67ed5fd32687de5d9f94660bf21003c6..c9a66bf36c9a4506f190186666dee325c1dbf3c3 100644 (file)
@@ -32,8 +32,4 @@
 #include <mach/soc.h>
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-#include "../../mach-omap2/soc.h"
-#endif
-
 #endif
index 743fc2836f7aaa8877349cd47fe98669351e11d2..a5bc92d7e4765b81315379c41618fff7f84cbec2 100644 (file)
@@ -26,6 +26,8 @@
 
 #include <asm/mach/map.h>
 
+#include <plat/sram.h>
+
 #define ROUND_DOWN(value,boundary)     ((value) & (~((boundary)-1)))
 
 static void __iomem *omap_sram_base;
index 584c9bf8ed2d0feed3894fa1b672f26ab70365a5..8e11e96eab5ef6dbb07f79c3dd747252401d5a52 100644 (file)
@@ -72,7 +72,7 @@ void pxa_ssp_free(struct ssp_device *ssp)
 }
 EXPORT_SYMBOL(pxa_ssp_free);
 
-static int __devinit pxa_ssp_probe(struct platform_device *pdev)
+static int pxa_ssp_probe(struct platform_device *pdev)
 {
        const struct platform_device_id *id = platform_get_device_id(pdev);
        struct resource *res;
@@ -164,7 +164,7 @@ err_free:
        return ret;
 }
 
-static int __devexit pxa_ssp_remove(struct platform_device *pdev)
+static int pxa_ssp_remove(struct platform_device *pdev)
 {
        struct resource *res;
        struct ssp_device *ssp;
@@ -199,7 +199,7 @@ static const struct platform_device_id ssp_id_table[] = {
 
 static struct platform_driver pxa_ssp_driver = {
        .probe          = pxa_ssp_probe,
-       .remove         = __devexit_p(pxa_ssp_remove),
+       .remove         = pxa_ssp_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "pxa2xx-ssp",
index 37542c2689a2763968bad6d040ae010c3ac61ac1..2d676ab50f7300c15dd3753fdde2edb1f5570ee6 100644 (file)
@@ -416,7 +416,7 @@ static int s3c_adc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit s3c_adc_remove(struct platform_device *pdev)
+static int s3c_adc_remove(struct platform_device *pdev)
 {
        struct adc_device *adc = platform_get_drvdata(pdev);
 
@@ -516,7 +516,7 @@ static struct platform_driver s3c_adc_driver = {
                .pm     = &adc_pm_ops,
        },
        .probe          = s3c_adc_probe,
-       .remove         = __devexit_p(s3c_adc_remove),
+       .remove         = s3c_adc_remove,
 };
 
 static int __init adc_init(void)
index e0072ce8d6e9c016d78d89c23cba639fa6732186..b69e11dc679da60d8c800c0658a30c84b47437e8 100644 (file)
@@ -43,7 +43,7 @@ extern unsigned long samsung_cpu_id;
 #define EXYNOS4_CPU_MASK       0xFFFE0000
 
 #define EXYNOS5250_SOC_ID      0x43520000
-#define EXYNOS5440_SOC_ID      0x54400000
+#define EXYNOS5440_SOC_ID      0xE5440000
 #define EXYNOS5_SOC_MASK       0xFFFFF000
 
 #define IS_SAMSUNG_CPU(name, id, mask)         \
index dfd8b7af8c7ac93db4bf6d3d28371a072793c1d9..f7a3ea2c498aa852b2b72d2d8baf79f32f2ac417 100644 (file)
@@ -11,6 +11,9 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __PLAT_SAMSUNG_GPIO_CORE_H
+#define __PLAT_SAMSUNG_GPIO_CORE_H
+
 #define GPIOCON_OFF    (0x00)
 #define GPIODAT_OFF    (0x04)
 
@@ -124,3 +127,5 @@ extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
 /* locking wrappers to deal with multiple access to the same gpio bank */
 #define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
 #define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
+
+#endif /* __PLAT_SAMSUNG_GPIO_CORE_H */
index dd703ef09b8d9d623d83e4a131c12e87e329e838..b178d44e9eaa897c8f8a3a4bb017198cb7014cae 100644 (file)
@@ -20,7 +20,7 @@
  */
 ENTRY(versatile_secondary_startup)
        mrc     p15, 0, r0, c0, c0, 5
-       and     r0, r0, #15
+       bic     r0, #0xff000000
        adr     r4, 1f
        ldmia   r4, {r5, r6}
        sub     r4, r4, r5
index cc926c98598141a2fbcdb762148ec17782982d06..323ce1a62bbfa3465230632d5d7d35c458f380fa 100644 (file)
@@ -22,7 +22,7 @@
 @  IRQs disabled.
 @
 ENTRY(do_vfp)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        add     r11, r4, #1             @ increment it
        str     r11, [r10, #TI_PREEMPT]
@@ -35,7 +35,7 @@ ENTRY(do_vfp)
 ENDPROC(do_vfp)
 
 ENTRY(vfp_null_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
@@ -53,7 +53,7 @@ ENDPROC(vfp_null_entry)
 
        __INIT
 ENTRY(vfp_testing_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
index ea0349f6358658065b52aa1473e877ee4fa8f5ba..dd5e56f95f3fbe3d03f7be90f1201a78a93ed568 100644 (file)
@@ -168,7 +168,7 @@ vfp_hw_state_valid:
                                        @ else it's one 32-bit instruction, so
                                        @ always subtract 4 from the following
                                        @ instruction address.
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
@@ -192,7 +192,7 @@ look_for_VFP_exceptions:
        @ not recognised by VFP
 
        DBGSTR  "not VFP"
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
index f9ccff915918fad21f622284e6f456747ac5143f..75e915b72471d3a77047a75186198fddaba2fec9 100644 (file)
@@ -2,14 +2,14 @@ config ARM64
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
+       select ARM_AMBA
+       select CLONE_BACKWARDS
        select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IOMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
-       select GENERIC_KERNEL_EXECVE
-       select GENERIC_KERNEL_THREAD
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL
        select HARDIRQS_SW_RESEND
@@ -21,7 +21,6 @@ config ARM64
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_GENERIC_HARDIRQS
        select HAVE_HW_BREAKPOINT if PERF_EVENTS
-       select HAVE_IRQ_WORK
        select HAVE_MEMBLOCK
        select HAVE_PERF_EVENTS
        select IRQ_DOMAIN
@@ -33,7 +32,6 @@ config ARM64
        select RTC_LIB
        select SPARSE_IRQ
        select SYSCTL_EXCEPTION_TRACE
-       select CLONE_BACKWARDS
        help
          ARM 64-bit (AArch64) Linux support.
 
@@ -92,6 +90,9 @@ config SWIOTLB
 config IOMMU_HELPER
        def_bool SWIOTLB
 
+config GENERIC_GPIO
+       def_bool y
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 801e2d7fcbc6e9bd0e4795faea842604c0c57afc..32ac0aef006879cb57b9c6bfbc25c072924b8076 100644 (file)
@@ -1,4 +1,5 @@
 targets += dtbs
+targets += $(dtb-y)
 
 dtbs: $(addprefix $(obj)/, $(dtb-y))
 
index 37e610dc084ed76b532f0647f07d6c2085b69798..618b450e5a1d5e009f30784b11e66a3fbc6468c5 100644 (file)
@@ -23,6 +23,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/ptrace.h>
 
 #define COMPAT_USER_HZ         100
 #define COMPAT_UTS_MACHINE     "armv8l\0\0"
@@ -209,10 +210,11 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
+#define compat_user_stack_pointer() (current_pt_regs()->compat_sp)
+
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
-       struct pt_regs *regs = task_pt_regs(current);
-       return (void __user *)regs->compat_sp - len;
+       return (void __user *)compat_user_stack_pointer() - len;
 }
 
 struct compat_ipc64_perm {
index 07fea290d7c15b211e881856bb48d943a80c337a..fe32c0e4ac010d4460184d7c8ddca2317b9d151e 100644 (file)
 
 typedef unsigned long elf_greg_t;
 
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#define ELF_CORE_COPY_REGS(dest, regs) \
+       *(struct user_pt_regs *)&(dest) = (regs)->user_regs;
+
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 typedef struct user_fpsimd_state elf_fpregset_t;
 
index 64b13394950266308093f67bce6ddb7e55391428..e333a243bfccf4f6e1547ea2543e5a3fa3abd32b 100644 (file)
@@ -24,7 +24,8 @@
 /*
  * Software defined PTE bits definition.
  */
-#define PTE_VALID              (_AT(pteval_t, 1) << 0) /* pte_present() check */
+#define PTE_VALID              (_AT(pteval_t, 1) << 0)
+#define PTE_PROT_NONE          (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */
 #define PTE_FILE               (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
 #define PTE_DIRTY              (_AT(pteval_t, 1) << 55)
 #define PTE_SPECIAL            (_AT(pteval_t, 1) << 56)
@@ -60,9 +61,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 
 extern pgprot_t pgprot_default;
 
-#define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
+#define __pgprot_modify(prot,mask,bits) \
+       __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
+
+#define _MOD_PROT(p, b)                __pgprot_modify(p, 0, b)
 
-#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_NONE              __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE)
 #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)
@@ -72,7 +76,7 @@ extern pgprot_t pgprot_default;
 #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_NONE            __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE)
 #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)
@@ -125,16 +129,15 @@ extern struct page *empty_zero_page;
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
-#define pte_present(pte)       (pte_val(pte) & PTE_VALID)
+#define pte_present(pte)       (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
 #define pte_dirty(pte)         (pte_val(pte) & PTE_DIRTY)
 #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_UXN))
 
-#define pte_present_exec_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
-        (PTE_VALID | PTE_USER))
+#define pte_valid_user(pte) \
+       ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
@@ -157,10 +160,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t pte)
 {
-       if (pte_present_exec_user(pte))
-               __sync_icache_dcache(pte, addr);
-       if (!pte_dirty(pte))
-               pte = pte_wrprotect(pte);
+       if (pte_valid_user(pte)) {
+               if (pte_exec(pte))
+                       __sync_icache_dcache(pte, addr);
+               if (!pte_dirty(pte))
+                       pte = pte_wrprotect(pte);
+       }
+
        set_pte(ptep, pte);
 }
 
@@ -170,9 +176,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 #define pte_huge(pte)          ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
 #define pte_mkhuge(pte)                (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
 
-#define __pgprot_modify(prot,mask,bits)                \
-       __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
-
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /*
@@ -264,7 +267,8 @@ 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_PXN | PTE_UXN | PTE_RDONLY;
+       const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
+                             PTE_PROT_NONE | PTE_VALID;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index 76fb7dd3350aef410b3946095ae98665e5e6a92c..744087fb521cca4cd0fcb2111fe37194f38b5921 100644 (file)
@@ -28,6 +28,5 @@
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #endif
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
index 58432625fdb36922fa48831142e5bdf3a08d7875..5ef47ba3ed459f9f786cb79abddc2ecf762e5aaf 100644 (file)
@@ -395,8 +395,13 @@ __SYSCALL(370, sys_name_to_handle_at)
 __SYSCALL(371, compat_sys_open_by_handle_at)
 __SYSCALL(372, compat_sys_clock_adjtime)
 __SYSCALL(373, sys_syncfs)
+__SYSCALL(374, compat_sys_sendmmsg)
+__SYSCALL(375, sys_setns)
+__SYSCALL(376, compat_sys_process_vm_readv)
+__SYSCALL(377, compat_sys_process_vm_writev)
+__SYSCALL(378, sys_ni_syscall)                 /* 378 for kcmp */
 
-#define __NR_compat_syscalls           374
+#define __NR_compat_syscalls           379
 
 /*
  * Compat syscall numbers used by the AArch64 kernel.
index c76c7241125b66d8ee762b13bdae3f73328f8fe7..f7073c7b1ca91de056f5ca80f13aad12e3383e91 100644 (file)
@@ -1221,7 +1221,7 @@ static struct of_device_id armpmu_of_device_ids[] = {
        {},
 };
 
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
+static int armpmu_device_probe(struct platform_device *pdev)
 {
        if (!cpu_pmu)
                return -ENODEV;
index c958cb84d75fd4c488d585a6bec5233aa839b21c..6a389dc1bd499c5de57c1a572bb22fb1a81c1494 100644 (file)
@@ -252,10 +252,6 @@ void update_vsyscall(struct timekeeper *tk)
 
 void update_vsyscall_tz(void)
 {
-       ++vdso_data->tb_seq_count;
-       smp_wmb();
        vdso_data->tz_minuteswest       = sys_tz.tz_minuteswest;
        vdso_data->tz_dsttime           = sys_tz.tz_dsttime;
-       smp_wmb();
-       ++vdso_data->tb_seq_count;
 }
index 8bf658d974f947da714eb5e7a6812552173fe140..f0a6d10b52114953dcfd818c66ad85f6cccccbd8 100644 (file)
@@ -73,8 +73,6 @@ ENTRY(__kernel_gettimeofday)
        /* If tz is NULL, return 0. */
        cbz     x1, 3f
        ldp     w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
-       seqcnt_read w9
-       seqcnt_check w9, 1b
        stp     w4, w5, [x1, #TZ_MINWEST]
 3:
        mov     x0, xzr
index e40c9bd7914341a4381b06b8d13f2a0162f1cfbc..2ae6591b3a55353789bedf11cc5c11faa58ad34b 100644 (file)
@@ -17,8 +17,6 @@ config AVR32
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        help
          AVR32 is a high-performance 32-bit RISC microprocessor core,
          designed for cost-sensitive embedded applications, with particular
index aaf5199d8fcbfb69ddca12e7d48fd816f791e341..b3d18f9f3e8d466a66c44fc665e2d04f58492d4a 100644 (file)
@@ -336,4 +336,14 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif /* __ASM_AVR32_DMA_MAPPING_H */
index 8d3c412fc65ff7b86037b6230d953f3feee63b19..630e4f9bf5f084be7a2942126d3e71666482f383 100644 (file)
@@ -21,6 +21,7 @@
 #define user_mode(regs)                 (((regs)->sr & MODE_MASK) == MODE_USER)
 #define instruction_pointer(regs)       ((regs)->pc)
 #define profile_pc(regs)                instruction_pointer(regs)
+#define user_stack_pointer(regs)       ((regs)->sp)
 
 static __inline__ int valid_user_regs(struct pt_regs *regs)
 {
index f05a9804e8e22f929d2d9f0e61808f9f436b8eba..0bdf6371574e76eeaebfd821cbff2dbdb94dd16d 100644 (file)
@@ -39,7 +39,6 @@
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index eb46f61adb7d12727d4b54ad47c571ca79f780ac..1b77a93eff500c14ac9594c9f6098007353c8a78 100644 (file)
@@ -89,12 +89,6 @@ typedef unsigned long sigset_t;
 #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
 
index 9aa8800830f396b8ef4fb79a4186b1f9b95dc60a..c2f4a07dcda182d446ae49ed122b570f1a173efe 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
-int __devinit read_current_timer(unsigned long *timer_value)
+int read_current_timer(unsigned long *timer_value)
 {
        *timer_value = sysreg_read(COUNT);
        return 0;
index ab9ff4075f4d3b075692882234bb118a9d9b0349..67e4aaad78f5cda89302901f80c1227f28862336 100644 (file)
@@ -24,7 +24,6 @@ config BLACKFIN
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
        select HAVE_IDE
-       select HAVE_IRQ_WORK
        select HAVE_KERNEL_GZIP if RAMKERNEL
        select HAVE_KERNEL_BZIP2 if RAMKERNEL
        select HAVE_KERNEL_LZMA if RAMKERNEL
@@ -38,15 +37,12 @@ config BLACKFIN
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
        select GENERIC_IRQ_PROBE
-       select IRQ_PER_CPU if SMP
        select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
        select GENERIC_SMP_IDLE_THREAD
        select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config GENERIC_CSUM
        def_bool y
index bbf461076a0a2107ddc6ea932bc615fe74fdc7a1..054d9ec57d9dc1cea3eba24655a8e24349c06cef 100644 (file)
@@ -154,4 +154,14 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        _dma_sync((dma_addr_t)vaddr, size, dir);
 }
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif                         /* _BLACKFIN_DMA_MAPPING_H */
index 14ea93388c058d99fe576a0c1084284f64912678..c00491594b46d8b4adf2e75621090187bf778b5b 100644 (file)
@@ -17,6 +17,7 @@
 #define arch_has_single_step() (1)
 /* common code demands this function */
 #define ptrace_disable(child) user_disable_single_step(child)
+#define current_user_stack_pointer() rdusp()
 
 extern int is_user_addr_valid(struct task_struct *child,
                              unsigned long start, unsigned long len);
index 17eb748e9c54ff2d4cbff09e44204f85a3a7b8ef..e943cb1300482b69d3da8577fc9cc47cf6985e3a 100644 (file)
@@ -20,7 +20,6 @@
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_VFORK
 
 /*
index 978bb400be062a350dbe1281ed8c658f0f86b476..724a8c5f5578d14a69f3dcda0933e165f379d21c 100644 (file)
@@ -129,7 +129,7 @@ static struct notifier_block vreg_cpufreq_notifier_block = {
  *     bfin_dpmc_probe -
  *
  */
-static int __devinit bfin_dpmc_probe(struct platform_device *pdev)
+static int bfin_dpmc_probe(struct platform_device *pdev)
 {
        if (pdev->dev.platform_data)
                pdata = pdev->dev.platform_data;
@@ -143,7 +143,7 @@ static int __devinit bfin_dpmc_probe(struct platform_device *pdev)
 /**
  *     bfin_dpmc_remove -
  */
-static int __devexit bfin_dpmc_remove(struct platform_device *pdev)
+static int bfin_dpmc_remove(struct platform_device *pdev)
 {
        pdata = NULL;
        return cpufreq_unregister_notifier(&vreg_cpufreq_notifier_block,
@@ -152,7 +152,7 @@ static int __devexit bfin_dpmc_remove(struct platform_device *pdev)
 
 struct platform_driver bfin_dpmc_device_driver = {
        .probe   = bfin_dpmc_probe,
-       .remove  = __devexit_p(bfin_dpmc_remove),
+       .remove  = bfin_dpmc_remove,
        .driver  = {
                .name = DRIVER_NAME,
        }
index 66eab3703c7571e77d608609c4e401ffce0ffd77..f6a3648f5ec3c7030a8c4294be4e3bee54a25b6c 100644 (file)
@@ -17,8 +17,6 @@ config C6X
        select OF
        select OF_EARLY_FLATTREE
        select GENERIC_CLOCKEVENTS
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select MODULES_USE_ELF_RELA
 
 config MMU
index eae7b5963e860962fef1c91f3db98f150400b67b..4258b088aa93af29c550405b62a2b36ad4ec9a29 100644 (file)
@@ -25,6 +25,7 @@ generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local.h
 generic-y += mman.h
+generic-y += mmu.h
 generic-y += mmu_context.h
 generic-y += msgbuf.h
 generic-y += param.h
index 3c694065030f506708a9717ef7bbb5faf94f6bc1..88bd0d899bdbedfac95bfc99450f9f6fbcc00ca0 100644 (file)
@@ -89,4 +89,19 @@ extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f))
 #define dma_free_noncoherent(d, s, v, h)  dma_free_coherent((d), (s), (v), (h))
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif /* _ASM_C6X_DMA_MAPPING_H */
diff --git a/arch/c6x/include/asm/mmu.h b/arch/c6x/include/asm/mmu.h
deleted file mode 100644 (file)
index 4467e77..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010 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_MMU_H
-#define _ASM_C6X_MMU_H
-
-typedef struct {
-       unsigned long           end_brk;
-#ifdef CONFIG_BINFMT_ELF_FDPIC
-       unsigned long   exec_fdpic_loadmap;
-       unsigned long   interp_fdpic_loadmap;
-#endif
-} mm_context_t;
-
-#endif /* _ASM_C6X_MMU_H */
index f3987a8703d92ba18be7cbe949b155985ee59aa3..e7d09a614d1028b4e0673f73f05d3fa0388e23f5 100644 (file)
@@ -14,7 +14,6 @@
  *   more details.
  */
 
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 
 /* Use the standard ABI for syscalls. */
index 0cac6a49f230d9e20e78bdacf7fa2ebe736a4f59..c59a01dd9c0c627ee4afc7060b90deb0606811c1 100644 (file)
@@ -49,8 +49,6 @@ config CRIS
        select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
        select GENERIC_CMOS_UPDATE
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select CLONE_BACKWARDS2
 
 config HZ
index e3dfc72d0cfd760507f42ea74355511aa134c16d..64a5fb93767d153139bacf61f007ca00c013eb7e 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/kernel.h>
 #include <arch/hwregs/intr_vect.h>
 
-void __devinit  pcibios_fixup_bus(struct pci_bus *b)
+void pcibios_fixup_bus(struct pci_bus *b)
 {
 }
 
index ebe2cb30bd11ba9f54188ba9ad39b6dfcb800c87..04a16edd540162ae3c596cd7ee2c5dc7cffe0cf5 100644 (file)
@@ -84,7 +84,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                cpumask_set_cpu(i, &phys_cpu_present_map);
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        /* PGD pointer has moved after per_cpu initialization so
         * update the MMU.
index 8588b2ccf85444206480895bb067cd8c7366a558..2f0f654f1b4407484c0a22d1b418a44e5388f04f 100644 (file)
@@ -158,5 +158,15 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 {
 }
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 
 #endif
index 2de84d7061c7015aa8adea1374671e5dcae54c33..9e788d04a4ef1b9c5d956f578fe4ee53b3bb9c2a 100644 (file)
@@ -9,5 +9,6 @@
 #define PTRACE_SETREGS            13
 
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_user_stack_pointer() rdusp()
 
 #endif /* _CRIS_PTRACE_H */
index 89680f9eac0d4e758b14d0026b4b75b4d4c43933..6d062bdf92d4a560b9ec746c434621a10694e28b 100644 (file)
@@ -32,7 +32,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 21624948a96d72d16502408cabc3b64241eb18c1..ce42fa7c32ad614ba6671a81dd1d2882588509d1 100644 (file)
@@ -83,12 +83,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER    0x04000000
 
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index df2eb4bd9fa2abbaa06c6978537fcabc88c22cf7..17df48fc8f44a419e1abd9051ccac1b4645e7ea9 100644 (file)
@@ -3,7 +3,6 @@ config FRV
        default y
        select HAVE_IDE
        select HAVE_ARCH_TRACEHOOK
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_UID16
        select HAVE_GENERIC_HARDIRQS
@@ -12,8 +11,6 @@ config FRV
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config ZONE_DMA
        bool
index dfb811002c640fcc790aaecf47727a1c5f83c5fa..1746a2b8e6e7287cd9ad612caa00af6bd9cd8a28 100644 (file)
@@ -132,4 +132,19 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        flush_write_buffers();
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif  /* _ASM_DMA_MAPPING_H */
index 1807d8ea8cb5563873dca78bdf1e42300df4aa23..d685da17f5fb9954f1517e35cf6c931024e156ef 100644 (file)
@@ -29,7 +29,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 3cb3392f799e02886e8a93b88907a2ca7a9f0215..a5136474c6fd6f95628362e8e144d82f8799c773 100644 (file)
@@ -852,7 +852,7 @@ void __init setup_arch(char **cmdline_p)
 /*
  *
  */
-static int __devinit setup_arch_serial(void)
+static int setup_arch_serial(void)
 {
        /* register those serial ports that are available */
 #ifndef CONFIG_GDBSTUB_UART0
index 71e9bcf581051a71316665b7ec0cea5d22f98b67..d186b254ce99fd87046177e8c2d15eb15529dcff 100644 (file)
@@ -268,7 +268,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d)
                d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
 
-static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
+static void pci_fixup_ide_bases(struct pci_dev *d)
 {
        int i;
 
@@ -287,7 +287,7 @@ static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
        }
 }
 
-static void __devinit pci_fixup_ide_trash(struct pci_dev *d)
+static void pci_fixup_ide_trash(struct pci_dev *d)
 {
        int i;
 
@@ -300,7 +300,7 @@ static void __devinit pci_fixup_ide_trash(struct pci_dev *d)
                d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
 }
 
-static void __devinit  pci_fixup_latency(struct pci_dev *d)
+static void pci_fixup_latency(struct pci_dev *d)
 {
        /*
         *  SiS 5597 and 5598 chipsets require latency timer set to
index 0ae44508760736bad5b8b2ed0937aea3f64c0763..2d2efb653ee0a9ecefe1b89b69e1aae08ad73ff2 100644 (file)
@@ -9,8 +9,6 @@ config H8300
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config SYMBOL_PREFIX
        string
index bebdc36ebb0a85551c19a07f7caacb0155eecb0e..995eb47e01bb5c17866f10e8e24aecf4aedacd9c 100644 (file)
@@ -1,5 +1,6 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += mmu.h
 generic-y += module.h
 generic-y += trace_clock.h
diff --git a/arch/h8300/include/asm/mmu.h b/arch/h8300/include/asm/mmu.h
deleted file mode 100644 (file)
index 3130996..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __MMU_H
-#define __MMU_H
-
-/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
-
-typedef struct {
-       unsigned long           end_brk;
-} mm_context_t;
-
-#endif
index 79c9a91e75ef6d213338ebc8a4efb2569eda3682..c1826b95c5ca1cb1d810216a4b4a12c9a869811f 100644 (file)
@@ -28,5 +28,6 @@
 #define current_pt_regs() ((struct pt_regs *) \
        (THREAD_SIZE + (unsigned long)current_thread_info()) - 1)
 #define signal_pt_regs() ((struct pt_regs *)current->thread.esp0)
+#define current_user_stack_pointer() rdusp()
 #endif /* __ASSEMBLY__ */
 #endif /* _H8300_PTRACE_H */
index 8215518b3f9fb1e8753132cff0d252732a16f40e..aa38105959fb202ee1be37addaa215c9e3594bcc 100644 (file)
@@ -31,7 +31,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 913729e581e8341e0d3ae8fd48c7a6119a0c523d..af3a6c37fee68f7ce22e43ba076d75ce46ffd2f7 100644 (file)
@@ -82,12 +82,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER    0x04000000
 
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index e418803b6c8eb71dcf838829b4beebbea835819a..e4decc6b8947e4fe68180010a524e0f7b6600084 100644 (file)
@@ -12,9 +12,7 @@ config HEXAGON
        # select ARCH_WANT_OPTIONAL_GPIOLIB
        # select ARCH_REQUIRE_GPIOLIB
        # select HAVE_CLK
-       # select IRQ_PER_CPU
        # select GENERIC_PENDING_IRQ if SMP
-       select HAVE_IRQ_WORK
        select GENERIC_ATOMIC64
        select HAVE_PERF_EVENTS
        select HAVE_GENERIC_HARDIRQS
@@ -31,8 +29,6 @@ config HEXAGON
        select GENERIC_CLOCKEVENTS
        select GENERIC_CLOCKEVENTS_BROADCAST
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        ---help---
          Qualcomm Hexagon is a processor architecture designed for high
          performance and low power across a wide variety of applications.
index 2af81533bd0ffb305e9c473f2dbf39054244f9cc..4a87cc47075c37d4f3f43997876a1383206e8cba 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #define sys_mmap2 sys_mmap_pgoff
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 
 #include <asm-generic/unistd.h>
index 6706004681280ab211e11a8836f71535d4c1bd9f..00c2e88f77559eb9bca234936819071c83a0566b 100644 (file)
@@ -29,7 +29,6 @@ config IA64
        select ARCH_DISCARD_MEMBLOCK
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
-       select IRQ_PER_CPU
        select GENERIC_IRQ_SHOW
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -42,8 +41,6 @@ config IA64
        select GENERIC_TIME_VSYSCALL_OLD
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index 301609c3fceca4099201c06ef2b4992f7a29fff2..359e68a03ca3e47ca1ea71df04b3fd04cba14e31 100644 (file)
@@ -153,7 +153,7 @@ extern int additional_cpus;
 #else
 #define MAX_PXM_DOMAINS (256)
 #endif
-extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+extern int pxm_to_nid_map[MAX_PXM_DOMAINS];
 extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
 
index 7fcf7f08ab0623ef87d62fb7ef001023b2871ed7..e2d3f5baf265408b49a201e8fa07e3b3b24fe939 100644 (file)
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in nsec.
+ * If we have CONFIG_VIRT_CPU_ACCOUNTING_NATIVE, we measure cpu time in nsec.
  * Otherwise we measure cpu time in jiffies using the generic definitions.
  */
 
 #ifndef __IA64_CPUTIME_H
 #define __IA64_CPUTIME_H
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-#include <asm-generic/cputime.h>
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
+# include <asm-generic/cputime.h>
 #else
-
-#include <linux/time.h>
-#include <linux/jiffies.h>
-#include <asm/processor.h>
-
-typedef u64 __nocast cputime_t;
-typedef u64 __nocast cputime64_t;
-
-#define cputime_one_jiffy              jiffies_to_cputime(1)
-
-/*
- * Convert cputime <-> jiffies (HZ)
- */
-#define cputime_to_jiffies(__ct)       \
-       ((__force u64)(__ct) / (NSEC_PER_SEC / HZ))
-#define jiffies_to_cputime(__jif)      \
-       (__force cputime_t)((__jif) * (NSEC_PER_SEC / HZ))
-#define cputime64_to_jiffies64(__ct)   \
-       ((__force u64)(__ct) / (NSEC_PER_SEC / HZ))
-#define jiffies64_to_cputime64(__jif)  \
-       (__force cputime64_t)((__jif) * (NSEC_PER_SEC / HZ))
-
-/*
- * Convert cputime <-> microseconds
- */
-#define cputime_to_usecs(__ct)         \
-       ((__force u64)(__ct) / NSEC_PER_USEC)
-#define usecs_to_cputime(__usecs)      \
-       (__force cputime_t)((__usecs) * NSEC_PER_USEC)
-#define usecs_to_cputime64(__usecs)    \
-       (__force cputime64_t)((__usecs) * NSEC_PER_USEC)
-
-/*
- * Convert cputime <-> seconds
- */
-#define cputime_to_secs(__ct)          \
-       ((__force u64)(__ct) / NSEC_PER_SEC)
-#define secs_to_cputime(__secs)                \
-       (__force cputime_t)((__secs) * NSEC_PER_SEC)
-
-/*
- * Convert cputime <-> timespec (nsec)
- */
-static inline cputime_t timespec_to_cputime(const struct timespec *val)
-{
-       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
-       return (__force cputime_t) ret;
-}
-static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
-{
-       val->tv_sec  = (__force u64) ct / NSEC_PER_SEC;
-       val->tv_nsec = (__force u64) ct % NSEC_PER_SEC;
-}
-
-/*
- * Convert cputime <-> timeval (msec)
- */
-static inline cputime_t timeval_to_cputime(struct timeval *val)
-{
-       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_usec * NSEC_PER_USEC;
-       return (__force cputime_t) ret;
-}
-static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
-{
-       val->tv_sec = (__force u64) ct / NSEC_PER_SEC;
-       val->tv_usec = ((__force u64) ct % NSEC_PER_SEC) / NSEC_PER_USEC;
-}
-
-/*
- * Convert cputime <-> clock (USER_HZ)
- */
-#define cputime_to_clock_t(__ct)       \
-       ((__force u64)(__ct) / (NSEC_PER_SEC / USER_HZ))
-#define clock_t_to_cputime(__x)                \
-       (__force cputime_t)((__x) * (NSEC_PER_SEC / USER_HZ))
-
-/*
- * Convert cputime64 to clock.
- */
-#define cputime64_to_clock_t(__ct)     \
-       cputime_to_clock_t((__force cputime_t)__ct)
-
+# include <asm/processor.h>
+# include <asm-generic/cputime_nsecs.h>
 extern void arch_vtime_task_switch(struct task_struct *tsk);
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
 #endif /* __IA64_CPUTIME_H */
index b9c102e15f22b196cd429d326c9cb674a9136009..94c89a2d97fe2f59421a101c64c587d7bde0c588 100644 (file)
@@ -87,18 +87,13 @@ static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
 }
 
 extern void __init iosapic_system_init (int pcat_compat);
-extern int __devinit iosapic_init (unsigned long address,
-                                   unsigned int gsi_base);
-#ifdef CONFIG_HOTPLUG
+extern int iosapic_init (unsigned long address, unsigned int gsi_base);
 extern int iosapic_remove (unsigned int gsi_base);
-#else
-#define iosapic_remove(gsi_base)                               (-EINVAL)
-#endif /* CONFIG_HOTPLUG */
 extern int gsi_to_irq (unsigned int gsi);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
                                  unsigned long trigger);
 extern void iosapic_unregister_intr (unsigned int irq);
-extern void __devinit iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
+extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
                                      unsigned long polarity,
                                      unsigned long trigger);
 extern int __init iosapic_register_platform_intr (u32 int_type,
@@ -109,7 +104,7 @@ extern int __init iosapic_register_platform_intr (u32 int_type,
                                           unsigned long trigger);
 
 #ifdef CONFIG_NUMA
-extern void __devinit map_iosapic_to_node (unsigned int, int);
+extern void map_iosapic_to_node (unsigned int, int);
 #endif
 #else
 #define iosapic_system_init(pcat_compat)                       do { } while (0)
index 67e16adfcd25dcd26da9be94bf2e93d07add8bf7..638b4d271b994b91b0481535adcf9615e4de72cd 100644 (file)
@@ -9,10 +9,9 @@
 #ifndef _ASM_IA64_PARPORT_H
 #define _ASM_IA64_PARPORT_H 1
 
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+static int parport_pc_find_isa_ports(int autoirq, int autodma);
 
-static int __devinit
-parport_pc_find_nonpci_ports (int autoirq, int autodma)
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
 {
        return parport_pc_find_isa_ports(autoirq, autodma);
 }
index b0e973649cb9f4cfdda26b5178291da9bcd0b2e0..845143990a1d66f2c5bb77b8b69225cfe7eb195f 100644 (file)
@@ -78,6 +78,11 @@ static inline long regs_return_value(struct pt_regs *regs)
        unsigned long __ip = instruction_pointer(regs);                 \
        (__ip & ~3UL) + ((__ip & 3UL) << 2);                            \
 })
+/*
+ * Why not default?  Because user_stack_pointer() on ia64 gives register
+ * stack backing store instead...
+ */
+#define current_user_stack_pointer() (current_pt_regs()->r12)
 
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define task_pt_regs(t)               (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
index 0b3b3997decd1adf397901a4ec4b4ad9d3328cfe..fea21e986022e447fe54a37d1b21f29f9c05aa4b 100644 (file)
@@ -55,7 +55,7 @@ extern struct smp_boot_data {
        int cpu_phys_id[NR_CPUS];
 } smp_boot_data __initdata;
 
-extern char no_int_routing __devinitdata;
+extern char no_int_routing;
 
 extern cpumask_t cpu_core_map[NR_CPUS];
 DECLARE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
index ff2ae41365840a616b4a7b6211aed1b2678c6e0a..020d655ed082bf9aabbf31a9091468e9045acb0d 100644 (file)
@@ -31,7 +31,7 @@ struct thread_info {
        mm_segment_t addr_limit;        /* user-level address space limit */
        int preempt_count;              /* 0=premptable, <0=BUG; will also serve as bh-counter */
        struct restart_block restart_block;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        __u64 ac_stamp;
        __u64 ac_leave;
        __u64 ac_stime;
@@ -69,7 +69,7 @@ struct thread_info {
 #define task_stack_page(tsk)   ((void *)(tsk))
 
 #define __HAVE_THREAD_FUNCTIONS
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 #define setup_thread_stack(p, org)                     \
        *task_thread_info(p) = *task_thread_info(org);  \
        task_thread_info(p)->ac_stime = 0;              \
index 1574bca86138c317ab70fa75d5e19fa3911ae6d9..c3cc42a15af157b14fc7fd55da74f75d39d21616 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    311 /* length of syscall table */
+#define NR_syscalls                    312 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
@@ -29,7 +29,6 @@
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
index c57fa910f2c937e7473a9ea63e5ac9a7be74c86c..00cf03e0cb8295c8f489107cc025bf6fd377b108 100644 (file)
@@ -1,5 +1,5 @@
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 /* read ar.itc in advance, and use it before leaving bank 0 */
 #define XEN_ACCOUNT_GET_STAMP          \
        MOV_FROM_ITC(pUStk, p6, r20, r2);
index e531c424434cf3784b7f2104982976ba01d3877c..c0ea2855e96baccec34bd781211217300a6aa363 100644 (file)
 
 #define SA_RESTORER    0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 /*
  * The minimum stack size needs to be fairly large because we want to
  * be sure that an app compiled for today's CPUs will continue to run
index b706aa54df2058eb0cb0bbd72cf543a49880313e..34fd6fe46da1e6e1659b347481f2a93ec2b5ca11 100644 (file)
 #define __NR_process_vm_readv          1332
 #define __NR_process_vm_writev         1333
 #define __NR_accept4                   1334
+#define __NR_finit_module              1335
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index e9682f5be3431b58c1dfe6d080bdb87432dea838..335eb07480fe9a89545c48d3ed273e50cfee9cb8 100644 (file)
@@ -422,7 +422,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
 #define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
 
 static int __initdata srat_num_cpus;   /* number of cpus */
-static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
+static u32 pxm_flag[PXM_FLAG_LEN];
 #define pxm_bit_set(bit)       (set_bit(bit,(void *)pxm_flag))
 #define pxm_bit_test(bit)      (test_bit(bit,(void *)pxm_flag))
 static struct acpi_table_slit __initdata *slit_table;
@@ -956,8 +956,8 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 #endif                         /* CONFIG_ACPI_HOTPLUG_CPU */
 
 #ifdef CONFIG_ACPI_NUMA
-static acpi_status __devinit
-acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
+static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
+                                   void *context, void **ret)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
index a48bd9a9927bb3b42c7b2076bb0c4b359d83a2e5..46c9e3007315dedc0ca9c7aa38f8a1e522b3ca58 100644 (file)
@@ -41,7 +41,7 @@ void foo(void)
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
        DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
        DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
        DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
        DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
index e25b784a2b72166ef27d1e7ccb66d8063f5bf31c..7a53530f22c219eb877d81d2392a85722e9503dc 100644 (file)
@@ -724,7 +724,7 @@ GLOBAL_ENTRY(__paravirt_leave_syscall)
 #endif
 .global __paravirt_work_processed_syscall;
 __paravirt_work_processed_syscall:
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        adds r2=PT(LOADRS)+16,r12
        MOV_FROM_ITC(pUStk, p9, r22, r19)       // fetch time at leave
        adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
@@ -762,7 +762,7 @@ __paravirt_work_processed_syscall:
 
        ld8 r29=[r2],16         // M0|1 load cr.ipsr
        ld8 r28=[r3],16         // M0|1 load cr.iip
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 (pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13
        ;;
        ld8 r30=[r2],16         // M0|1 load cr.ifs
@@ -793,7 +793,7 @@ __paravirt_work_processed_syscall:
        ld8.fill r1=[r3],16                     // M0|1 load r1
 (pUStk) mov r17=1                              // A
        ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 (pUStk) st1 [r15]=r17                          // M2|3
 #else
 (pUStk) st1 [r14]=r17                          // M2|3
@@ -813,7 +813,7 @@ __paravirt_work_processed_syscall:
        shr.u r18=r19,16                // I0|1 get byte size of existing "dirty" partition
        COVER                           // B    add current frame into dirty partition & set cr.ifs
        ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        mov r19=ar.bsp                  // M2   get new backing store pointer
        st8 [r14]=r22                   // M    save time at leave
        mov f10=f0                      // F    clear f10
@@ -948,7 +948,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel)
        adds r16=PT(CR_IPSR)+16,r12
        adds r17=PT(CR_IIP)+16,r12
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        .pred.rel.mutex pUStk,pKStk
        MOV_FROM_PSR(pKStk, r22, r29)   // M2 read PSR now that interrupts are disabled
        MOV_FROM_ITC(pUStk, p9, r22, r29)       // M  fetch time at leave
@@ -981,7 +981,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel)
        ;;
        ld8.fill r12=[r16],16
        ld8.fill r13=[r17],16
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 (pUStk)        adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18
 #else
 (pUStk)        adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
@@ -989,7 +989,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel)
        ;;
        ld8 r20=[r16],16        // ar.fpsr
        ld8.fill r15=[r17],16
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 (pUStk)        adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18  // deferred
 #endif
        ;;
@@ -997,7 +997,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel)
        ld8.fill r2=[r17]
 (pUStk)        mov r17=1
        ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        //  mmi_ :  ld8 st1 shr;;         mmi_ : st8 st1 shr;;
        //  mib  :  mov add br        ->  mib  : ld8 add br
        //  bbb_ :  br  nop cover;;       mbb_ : mov br  cover;;
@@ -1785,6 +1785,7 @@ sys_call_table:
        data8 sys_process_vm_readv
        data8 sys_process_vm_writev
        data8 sys_accept4
+       data8 sys_finit_module                  // 1335
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index e662f178b990ab660526154dfa505c5452d57bf6..c4cd45d97749bf610f55b8be24a04ba5b7cec107 100644 (file)
@@ -529,7 +529,7 @@ GLOBAL_ENTRY(paravirt_fsys_bubble_down)
        nop.i 0
        ;;
        mov ar.rsc=0                            // M2   set enforced lazy mode, pl 0, LE, loadrs=0
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        MOV_FROM_ITC(p0, p6, r30, r23)          // M    get cycle for accounting
 #else
        nop.m 0
@@ -555,7 +555,7 @@ GLOBAL_ENTRY(paravirt_fsys_bubble_down)
        cmp.ne pKStk,pUStk=r0,r0                // A    set pKStk <- 0, pUStk <- 1
        br.call.sptk.many b7=ia64_syscall_setup // B
        ;;
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        // mov.m r30=ar.itc is called in advance
        add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2
        add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2
index 4738ff7bd66a28e35b260ea3706058fbf56adbda..9be4e497f3d3c253aa36c87459cdb4830a9e4fa7 100644 (file)
@@ -1073,7 +1073,7 @@ END(ia64_native_sched_clock)
 sched_clock = ia64_native_sched_clock
 #endif
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 GLOBAL_ENTRY(cycle_to_cputime)
        alloc r16=ar.pfs,1,0,0,0
        addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
@@ -1091,7 +1091,7 @@ GLOBAL_ENTRY(cycle_to_cputime)
        shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
        br.ret.sptk.many rp
 END(cycle_to_cputime)
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 #ifdef CONFIG_IA64_BRL_EMU
 
index ef4b5d877cf2ed08dc2706f5da6883323219aeb9..ee33c3aaa2fca383abd28f64021a0b6cb1c4c6ba 100644 (file)
@@ -147,7 +147,7 @@ static struct iosapic_intr_info {
        unsigned char   trigger : 1;    /* trigger mode (see iosapic.h) */
 } iosapic_intr_info[NR_IRQS];
 
-static unsigned char pcat_compat __devinitdata;        /* 8259 compatibility flag */
+static unsigned char pcat_compat;      /* 8259 compatibility flag */
 
 static inline void
 iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
@@ -914,10 +914,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 /*
  * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
  */
-void __devinit
-iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
-                         unsigned long polarity,
-                         unsigned long trigger)
+void iosapic_override_isa_irq(unsigned int isa_irq, unsigned int gsi,
+                             unsigned long polarity, unsigned long trigger)
 {
        int vector, irq;
        unsigned int dest = cpu_physical_id(smp_processor_id());
@@ -1012,8 +1010,7 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
        return 0;
 }
 
-int __devinit
-iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
+int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
 {
        int num_rte, err, index;
        unsigned int isa_irq, ver;
@@ -1070,9 +1067,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
        return 0;
 }
 
-#ifdef CONFIG_HOTPLUG
-int
-iosapic_remove (unsigned int gsi_base)
+int iosapic_remove(unsigned int gsi_base)
 {
        int index, err = 0;
        unsigned long flags;
@@ -1098,11 +1093,9 @@ iosapic_remove (unsigned int gsi_base)
        spin_unlock_irqrestore(&iosapic_lock, flags);
        return err;
 }
-#endif /* CONFIG_HOTPLUG */
 
 #ifdef CONFIG_NUMA
-void __devinit
-map_iosapic_to_node(unsigned int gsi_base, int node)
+void map_iosapic_to_node(unsigned int gsi_base, int node)
 {
        int index;
 
index fa25689fc453b36e1cb455782af442bdbf8017ee..689ffcaa284e4ddbdbe1503b12d0713c7cb5c017 100644 (file)
@@ -784,7 +784,7 @@ ENTRY(break_fault)
 
 (p8)   adds r28=16,r28                         // A    switch cr.iip to next bundle
 (p9)   adds r8=1,r8                            // A    increment ei to next slot
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        ;;
        mov b6=r30                              // I0   setup syscall handler branch reg early
 #else
@@ -801,7 +801,7 @@ ENTRY(break_fault)
        //
 ///////////////////////////////////////////////////////////////////////
        st1 [r16]=r0                            // M2|3 clear current->thread.on_ustack flag
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        MOV_FROM_ITC(p0, p14, r30, r18)         // M    get cycle for accounting
 #else
        mov b6=r30                              // I0   setup syscall handler branch reg early
@@ -817,7 +817,7 @@ ENTRY(break_fault)
        cmp.eq p14,p0=r9,r0                     // A    are syscalls being traced/audited?
        br.call.sptk.many b7=ia64_syscall_setup // B
 1:
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        // mov.m r30=ar.itc is called in advance, and r13 is current
        add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13  // A
        add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13  // A
@@ -1043,7 +1043,7 @@ END(ia64_syscall_setup)
        DBG_FAULT(16)
        FAULT(16)
 
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(__IA64_ASM_PARAVIRTUALIZED_NATIVE)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(__IA64_ASM_PARAVIRTUALIZED_NATIVE)
        /*
         * There is no particular reason for this code to be here, other than
         * that there happens to be space here that would go unused otherwise.
index d56753a11636b723b402a32df60fc762af3c5e38..cc82a7d744c985ce18b0a70512cd54234d71aefa 100644 (file)
@@ -4,7 +4,7 @@
 #include "entry.h"
 #include "paravirt_inst.h"
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 /* read ar.itc in advance, and use it before leaving bank 0 */
 #define ACCOUNT_GET_STAMP                              \
 (pUStk) mov.m r20=ar.itc;
index 4265ff64219b20eade95390e8cc2f47ec7500fba..b7a5fffe0924e03c860f50afcebc5bc0fc4ea7a3 100644 (file)
@@ -672,33 +672,6 @@ ptrace_attach_sync_user_rbs (struct task_struct *child)
        read_unlock(&tasklist_lock);
 }
 
-static inline int
-thread_matches (struct task_struct *thread, unsigned long addr)
-{
-       unsigned long thread_rbs_end;
-       struct pt_regs *thread_regs;
-
-       if (ptrace_check_attach(thread, 0) < 0)
-               /*
-                * If the thread is not in an attachable state, we'll
-                * ignore it.  The net effect is that if ADDR happens
-                * to overlap with the portion of the thread's
-                * register backing store that is currently residing
-                * on the thread's kernel stack, then ptrace() may end
-                * up accessing a stale value.  But if the thread
-                * isn't stopped, that's a problem anyhow, so we're
-                * doing as well as we can...
-                */
-               return 0;
-
-       thread_regs = task_pt_regs(thread);
-       thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL);
-       if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end))
-               return 0;
-
-       return 1;       /* looks like we've got a winner */
-}
-
 /*
  * Write f32-f127 back to task->thread.fph if it has been modified.
  */
index 6a368cb2043ee9ae82388b3856fe6b0e3a7d304f..500f1e4d9f9d973aceff4143ede63b3c69a6b83e 100644 (file)
@@ -347,8 +347,7 @@ ia64_sync_itc (unsigned int master)
 /*
  * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
  */
-static inline void __devinit
-smp_setup_percpu_timer (void)
+static inline void smp_setup_percpu_timer(void)
 {
 }
 
@@ -563,7 +562,7 @@ smp_prepare_cpus (unsigned int max_cpus)
        }
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        set_cpu_online(smp_processor_id(), true);
        cpu_set(smp_processor_id(), cpu_callin_map);
@@ -713,8 +712,7 @@ smp_cpus_done (unsigned int dummy)
               (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
 }
 
-static inline void __devinit
-set_cpu_sibling_map(int cpu)
+static inline void set_cpu_sibling_map(int cpu)
 {
        int i;
 
@@ -793,8 +791,7 @@ init_smp_config(void)
  * identify_siblings(cpu) gets called from identify_cpu. This populates the 
  * information related to logical execution units in per_cpu_data structure.
  */
-void __devinit
-identify_siblings(struct cpuinfo_ia64 *c)
+void identify_siblings(struct cpuinfo_ia64 *c)
 {
        long status;
        u16 pltid;
index b1995efbfd21708f0f283f7657f16ffbb5613c83..fbaac1afb8441926d3f2fdc9eec4ed85c6122da1 100644 (file)
@@ -77,7 +77,7 @@ static struct clocksource clocksource_itc = {
 };
 static struct clocksource *itc_clocksource;
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 
 #include <linux/kernel_stat.h>
 
@@ -136,13 +136,14 @@ void vtime_account_system(struct task_struct *tsk)
 
        account_system_time(tsk, 0, delta, delta);
 }
+EXPORT_SYMBOL_GPL(vtime_account_system);
 
 void vtime_account_idle(struct task_struct *tsk)
 {
        account_idle_time(vtime_delta(tsk));
 }
 
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id)
@@ -243,8 +244,7 @@ static int __init nojitter_setup(char *str)
 __setup("nojitter", nojitter_setup);
 
 
-void __devinit
-ia64_init_itm (void)
+void ia64_init_itm(void)
 {
        unsigned long platform_base_freq, itc_freq;
        struct pal_freq_ratio itc_ratio, proc_ratio;
index 082e383c1b6f22dc8370fdac789489acbb04ffba..b755ea92aea7f23d269f4053974dbc8cba2b380e 100644 (file)
@@ -294,11 +294,10 @@ setup_gate (void)
        ia64_patch_gate();
 }
 
-void __devinit
-ia64_mmu_init (void *my_cpu_data)
+void ia64_mmu_init(void *my_cpu_data)
 {
        unsigned long pta, impl_va_bits;
-       extern void __devinit tlb_init (void);
+       extern void tlb_init(void);
 
 #ifdef CONFIG_DISABLE_VHPT
 #      define VHPT_ENABLE_BIT  0
index 7b3cdc6c6d9147d3edd422ab31b97adf90e46f6c..ed61297686814be272dbde922bf94d8977894bf5 100644 (file)
@@ -337,8 +337,7 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
 }
 EXPORT_SYMBOL(flush_tlb_range);
 
-void __devinit
-ia64_tlb_init (void)
+void ia64_tlb_init(void)
 {
        ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
        u64 tr_pgbits;
index eab28e314022e7c4456a2860d99eea70c22c8df0..5dc969dd4ac06fec04f308894bcfe27dfc324e68 100644 (file)
@@ -24,7 +24,7 @@
  * video device at this point.
  */
 
-static void __devinit pci_fixup_video(struct pci_dev *pdev)
+static void pci_fixup_video(struct pci_dev *pdev)
 {
        struct pci_dev *bridge;
        struct pci_bus *bus;
index 5faa66c5c2a8df236c098f2738fc877a0f5300c5..55b72ad573292d58af2d6eff037a46bab8d75dba 100644 (file)
@@ -116,8 +116,7 @@ struct pci_ops pci_root_ops = {
 
 /* Called by ACPI when it finds a new root bus.  */
 
-static struct pci_controller * __devinit
-alloc_pci_controller (int seg)
+static struct pci_controller *alloc_pci_controller(int seg)
 {
        struct pci_controller *controller;
 
@@ -165,8 +164,8 @@ new_space (u64 phys_base, int sparse)
        return i;
 }
 
-static u64 __devinit
-add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr)
+static u64 add_io_space(struct pci_root_info *info,
+                       struct acpi_resource_address64 *addr)
 {
        struct resource *resource;
        char *name;
@@ -226,8 +225,8 @@ out:
        return ~0;
 }
 
-static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
-       struct acpi_resource_address64 *addr)
+static acpi_status resource_to_window(struct acpi_resource *resource,
+                                     struct acpi_resource_address64 *addr)
 {
        acpi_status status;
 
@@ -249,8 +248,7 @@ static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
        return AE_ERROR;
 }
 
-static acpi_status __devinit
-count_window (struct acpi_resource *resource, void *data)
+static acpi_status count_window(struct acpi_resource *resource, void *data)
 {
        unsigned int *windows = (unsigned int *) data;
        struct acpi_resource_address64 addr;
@@ -263,7 +261,7 @@ count_window (struct acpi_resource *resource, void *data)
        return AE_OK;
 }
 
-static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
+static acpi_status add_window(struct acpi_resource *res, void *data)
 {
        struct pci_root_info *info = data;
        struct pci_window *window;
@@ -324,8 +322,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
        return AE_OK;
 }
 
-struct pci_bus * __devinit
-pci_acpi_scan_root(struct acpi_pci_root *root)
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
        struct acpi_device *device = root->device;
        int domain = root->segment;
@@ -396,7 +393,7 @@ out1:
        return NULL;
 }
 
-static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
+static int is_valid_resource(struct pci_dev *dev, int idx)
 {
        unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
        struct resource *devr = &dev->resource[idx], *busr;
@@ -414,8 +411,7 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
        return 0;
 }
 
-static void __devinit
-pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
+static void pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
 {
        int i;
 
@@ -427,13 +423,13 @@ pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
        }
 }
 
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+void pcibios_fixup_device_resources(struct pci_dev *dev)
 {
        pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
 }
 EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
 
-static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
+static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
 {
        pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES);
 }
@@ -441,8 +437,7 @@ static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
 /*
  *  Called after each bus is probed, but before its children are examined.
  */
-void __devinit
-pcibios_fixup_bus (struct pci_bus *b)
+void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
index 8630875e74b5770ce3a02e3cf32175b3cbfeb6ba..11f2275570fb552f14443d8a8ece3281f0b65874 100644 (file)
@@ -435,8 +435,7 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address)
                                                geo_slot(geoid));
 }
 
-void __devinit
-sn_pci_fixup_bus(struct pci_bus *bus)
+void sn_pci_fixup_bus(struct pci_bus *bus)
 {
 
        if (SN_ACPI_BASE_SUPPORT())
index 4554f68b786524e7df3608cbf3b105fb8edf5030..b9992571c0368a123bffd493571478af6180fde8 100644 (file)
@@ -977,7 +977,7 @@ int sn_hwperf_get_nearest_node(cnodeid_t node,
        return e;
 }
 
-static int __devinit sn_hwperf_misc_register_init(void)
+static int sn_hwperf_misc_register_init(void)
 {
        int e;
 
index 01f479ee1c4333d89f0ac57b322c544edc8c4378..efb74dafec4de299df6c41929e8b864312d584cc 100644 (file)
@@ -273,9 +273,8 @@ xen_bind_early_percpu_irq(void)
  */
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int __devinit
-unbind_evtchn_callback(struct notifier_block *nfb,
-                      unsigned long action, void *hcpu)
+static int unbind_evtchn_callback(struct notifier_block *nfb,
+                                 unsigned long action, void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
 
index 5183f43a2cf7c3efd720a82d38312bc7b49422c7..f807721e19a52ee1f5b619cd0a742328e4515f46 100644 (file)
@@ -15,8 +15,6 @@ config M32R
        select GENERIC_ATOMIC64
        select ARCH_USES_GETTIMEOFFSET
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config SBUS
        bool
index ba487c554dbb599427c45a8837b9fdb85f91897d..fa58ccfff865eb5e07527d0dd55a72d8927b542b 100644 (file)
@@ -32,6 +32,7 @@ extern void init_debug_traps(struct task_struct *);
 
 #define instruction_pointer(regs) ((regs)->bpc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define user_stack_pointer(regs) ((regs)->spu)
 
 extern void withdraw_debug_trap(struct pt_regs *regs);
 
index 1eade32082b8cd849c48cd87aef7b18db162402b..79b063caec85953d2f622b3b3f6357df8c3db41d 100644 (file)
@@ -22,7 +22,6 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
index ef9788fda2ef4723adda64e28a159ee83c16d324..54acacb1f1f7f69df43bf17006c251f09a6c1abd 100644 (file)
@@ -84,12 +84,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER    0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index a2cfc0abb05ce4de59521727c147ee6b0b23965a..13168a769f8fcaee8fd3c5af3d085c0cd60e6d75 100644 (file)
@@ -127,7 +127,7 @@ static void unmap_cpu_to_physid(int, int);
 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
 /* Boot up APs Routines : BSP                                                */
 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        bsp_phys_id = hard_smp_processor_id();
        physid_set(bsp_phys_id, phys_cpu_present_map);
index 953a7ba5d05025a776e5114b20acfbc56231bd3c..6710084e072abeb484cc00f93805352aa9d4099d 100644 (file)
@@ -15,8 +15,6 @@ config M68K
        select FPU if MMU
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
        select MODULES_USE_ELF_RELA
index a985a7e87d45a76a3f07e2c2bd849bc0a06e628c..695cd737a42e80687bcb834685c32b15bd3085ca 100644 (file)
@@ -39,7 +39,7 @@ enum {
 #define MAX_UNIT       8
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
        " S.Opichal, M.Jurik, P.Stehlik\n"
        KERN_INFO " http://aranym.org/\n";
index 17f7a45948eac7473b3afb16e86b5512d58a2c4d..292805f0762ebd100351944c0d5abe9713b07cf2 100644 (file)
@@ -21,6 +21,22 @@ extern void *dma_alloc_coherent(struct device *, size_t,
 extern void dma_free_coherent(struct device *, size_t,
                              void *, dma_addr_t);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
                                          dma_addr_t *handle, gfp_t flag)
 {
@@ -99,4 +115,14 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t handle)
 #include <asm-generic/dma-mapping-broken.h>
 #endif
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif  /* _M68K_DMA_MAPPING_H */
index 646b1872f73b412982145b4c46ed1ff27b234124..5ea75e6a7399a3a58b7837177af6cc7c2c6120f1 100644 (file)
@@ -15,8 +15,8 @@
 #define outsl(port,buf,len)  isa_outsb(port,buf,(len)<<2)
 
 /* no dma, or IRQ autoprobing */
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+static int parport_pc_find_isa_ports (int autoirq, int autodma);
+static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
         if (! (MACH_IS_Q40))
          return 0; /* count=0 */
index bf86b29fe64a2b025fe1890da80d90270e730912..037028f4ab7033c55557ade43c6a959c89f9a0b5 100644 (file)
@@ -64,6 +64,8 @@ extern unsigned int kobjsize(const void *objp);
  */
 #define        VMALLOC_START   0
 #define        VMALLOC_END     0xffffffff
+#define        KMAP_START      0
+#define        KMAP_END        0xffffffff
 
 #include <asm-generic/pgtable.h>
 
index ae700f49e51da86b8b86b8ce9ee41b0a1908d6b1..b0768a657920f63c51522f2ddb0ef22da0c8dbc3 100644 (file)
@@ -130,7 +130,6 @@ extern int handle_kernel_fault(struct pt_regs *regs);
 #define start_thread(_regs, _pc, _usp)                  \
 do {                                                    \
        (_regs)->pc = (_pc);                            \
-       ((struct switch_stack *)(_regs))[-1].a6 = 0;    \
        setframeformat(_regs);                          \
        if (current->mm)                                \
                (_regs)->d5 = current->mm->start_data;  \
index 0f717045bddef4094584fe9c5be624e9ee2d4927..a45cb6894ad36c86c663ff77798c4b419db07c1f 100644 (file)
@@ -15,6 +15,7 @@
 #define profile_pc(regs) instruction_pointer(regs)
 #define current_pt_regs() \
        (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
+#define current_user_stack_pointer() rdusp()
 
 #define arch_has_single_step() (1)
 
index a021d67cdd72202b63d86abcc74216338c1a1e06..f9337f61466050bd48aa8f993c3d59a647e262d6 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            348
+#define NR_syscalls            349
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -31,7 +31,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 
index 2b450f311bd93c88ca613881c1c382231b76c114..cba6f858bb46b90bc9a3d0f03ef8f60bdd4e59be 100644 (file)
@@ -80,12 +80,6 @@ typedef unsigned long sigset_t;
 #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
 
index b94bfbf907053953336eb0bc4e04e6cf269685fb..625f321001dc077fe13da02eb0844a50099653dc 100644 (file)
 #define __NR_process_vm_readv  345
 #define __NR_process_vm_writev 346
 #define __NR_kcmp              347
+#define __NR_finit_module      348
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 73fa0b56a06c7613523bdd5297be2da86df64647..931a31ff59ddb32de3300d494b00a8efdcba2afc 100644 (file)
@@ -87,7 +87,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return 0;
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -97,7 +97,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
-char __devinit *pcibios_setup(char *str)
+char *pcibios_setup(char *str)
 {
        return str;
 }
index c30da5b3f2dbc2418085aeb6fed2940a2c175486..3f04ea0ab802750866835fcd9c3aa75ac7b28282 100644 (file)
@@ -368,4 +368,5 @@ ENTRY(sys_call_table)
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
        .long sys_kcmp
+       .long sys_finit_module
 
index f0e05bce92f2533ee8dc78ade768595d825646df..afd8106fd83b10c2b1d51b956b178effd9a6b096 100644 (file)
 void *empty_zero_page;
 EXPORT_SYMBOL(empty_zero_page);
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+extern void init_pointer_table(unsigned long ptable);
+extern pmd_t *zero_pgtable;
+#endif
+
 #ifdef CONFIG_MMU
 
 pg_data_t pg_data_map[MAX_NUMNODES];
@@ -69,9 +74,6 @@ void __init m68k_setup_node(int node)
        node_set_online(node);
 }
 
-extern void init_pointer_table(unsigned long ptable);
-extern pmd_t *zero_pgtable;
-
 #else /* CONFIG_MMU */
 
 /*
index 4bcf89148f3cec3767373776f309d47f687b8bb3..ba3b7c8c04b8150241f115696d00bd08747ac8f7 100644 (file)
@@ -26,8 +26,6 @@ config MICROBLAZE
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select CLONE_BACKWARDS
 
 config SWAP
index b3f5eecff2a7ddd16a42aaf2d8c5579019c86c3c..d2b097a652d9193f58917f2a256b4e3af09b540c 100644 (file)
@@ -1,25 +1,22 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE="rootfs.cpio"
-CONFIG_INITRAMFS_COMPRESSION_GZIP=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_HOTPLUG is not set
 # CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_SHMEM is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
 CONFIG_OPT_LIB_ASM=y
 CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
@@ -31,39 +28,62 @@ CONFIG_HZ_100=y
 CONFIG_MMU=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE_FORCE=y
+CONFIG_HIGHMEM=y
+CONFIG_PCI=y
+CONFIG_PCI_XILINX=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+CONFIG_MTD=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
 CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_LL_TEMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_UARTLITE=y
 CONFIG_SERIAL_UARTLITE_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_XILINX_HWICAP=y
+CONFIG_I2C=y
+CONFIG_I2C_XILINX=y
+CONFIG_SPI=y
+CONFIG_SPI_XILINX=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_XILINX=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_DMEM_GENIRQ=y
 CONFIG_EXT2_FS=y
 # CONFIG_DNOTIFY is not set
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_CIFS=y
 CONFIG_CIFS_STATS=y
 CONFIG_CIFS_STATS2=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SLAB=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_EARLY_PRINTK=y
+CONFIG_KEYS=y
+CONFIG_ENCRYPTED_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 0249e4b7e1d34003ebfd138755aef15f42632079..10b5172283d727e3b15a838f4a3c67a7192efa58 100644 (file)
@@ -1,41 +1,42 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_HOTPLUG is not set
 # CONFIG_BASE_FULL is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-# CONFIG_OPT_LIB_FUNCTION is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
 CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
 CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
 CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2
 CONFIG_XILINX_MICROBLAZE0_USE_FPU=2
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_HZ_100=y
 CONFIG_CMDLINE_BOOL=y
-CONFIG_BINFMT_FLAT=y
+CONFIG_CMDLINE_FORCE=y
+CONFIG_PCI=y
+CONFIG_PCI_XILINX=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -45,41 +46,55 @@ CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_UCLINUX=y
 CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_LL_TEMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_UARTLITE=y
 CONFIG_SERIAL_UARTLITE_CONSOLE=y
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_XILINX_HWICAP=y
+CONFIG_I2C=y
+CONFIG_I2C_XILINX=y
+CONFIG_SPI=y
+CONFIG_SPI_XILINX=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
 # CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_XILINX=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_DMEM_GENIRQ=y
 CONFIG_EXT2_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SHIRQ=y
+CONFIG_NLS=y
 CONFIG_DETECT_HUNG_TASK=y
-CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_SELFTEST=y
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_SG=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_EARLY_PRINTK=y
+CONFIG_KEYS=y
+CONFIG_ENCRYPTED_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRC32 is not set
index 2446a73140acb8c74fce242de7c4f37b44cff08e..d0463893243888f47bf1e740d7ebf0e68fb087c4 100644 (file)
@@ -71,7 +71,7 @@ static inline void kunmap(struct page *page)
        kunmap_high(page);
 }
 
-static inline void *__kmap_atomic(struct page *page)
+static inline void *kmap_atomic(struct page *page)
 {
        return kmap_atomic_prot(page, kmap_prot);
 }
index 3732bcf186fd5b6a3438464b9a570a914501fdc0..5b18ec124e513b6476e2dcc8d808b25bbe1abe7a 100644 (file)
@@ -16,6 +16,7 @@
 
 #define instruction_pointer(regs)      ((regs)->pc)
 #define profile_pc(regs)               instruction_pointer(regs)
+#define user_stack_pointer(regs)       ((regs)->r1)
 
 static inline long regs_return_value(struct pt_regs *regs)
 {
index 927540d3cb7d1ee9ddb62a6b1b0915f758dc8761..a1ab5f0009efcd7bc84d4dd17aabedb915707653 100644 (file)
@@ -108,7 +108,7 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
 # define __EX_TABLE_SECTION    ".section __ex_table,\"a\"\n"
 #else
 # define __FIXUP_SECTION       ".section .discard,\"ax\"\n"
-# define __EX_TABLE_SECTION    ".section .discard,\"a\"\n"
+# define __EX_TABLE_SECTION    ".section .discard,\"ax\"\n"
 #endif
 
 extern unsigned long __copy_tofrom_user(void __user *to,
index 99e23937a31aa05c0efec1b44588584490130808..10f8ac186855300af1fba9b374ddc581717b2356 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
-#ifdef CONFIG_MMU
 #define __ARCH_WANT_SYS_FORK
-#endif
 
 /*
  * "Conditional" syscalls
index ccb6920f3b339fd2350d9c86effbad7050036672..5f7fe7582f3ae3a483a39ae6419b2867ab4db76e 100644 (file)
 #define __NR_process_vm_readv  377
 #define __NR_process_vm_writev 378
 #define __NR_kcmp              379
+#define __NR_finit_module      380
 
-#define __NR_syscalls          380
+#define __NR_syscalls          381
 
 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
index 1cbace29b5e2495f567abb04b261e4341b316cc0..4fca56cf02f6f0c43bdac35be3eadfb55b57bc2f 100644 (file)
@@ -380,3 +380,4 @@ ENTRY(sys_call_table)
        .long sys_process_vm_readv
        .long sys_process_vm_writev
        .long sys_kcmp
+       .long sys_finit_module
index a1c5b996d66d0ba4e53b869210b9d662b1e2b35a..96416553cb361a8ba4835a85c9e6bf730d8ff2ce 100644 (file)
@@ -287,7 +287,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
        unsigned long io_offset = 0;
        int i, res_bit;
 
-       if (hose == 0)
+       if (!hose)
                return NULL;            /* should never happen */
 
        /* If memory, add on the PCI bridge address offset */
@@ -655,9 +655,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
  *   - Some 32 bits platforms such as 4xx can have physical space larger than
  *     32 bits so we need to use 64 bits values for the parsing
  */
-void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev,
-                                           int primary)
+void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                 struct device_node *dev, int primary)
 {
        const u32 *ranges;
        int rlen;
@@ -822,15 +821,13 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 /* Decide whether to display the domain number in /proc */
 int pci_proc_domain(struct pci_bus *bus)
 {
-       struct pci_controller *hose = pci_bus_to_host(bus);
-
        return 0;
 }
 
 /* This header fixup will do the resource fixup for all devices as they are
  * probed, but not for bridge ranges
  */
-static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
+static void pcibios_fixup_resources(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        int i;
@@ -871,8 +868,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
  * things go more smoothly when it gets it right. It should covers cases such
  * as Apple "closed" bridge resources and bare-metal pSeries unassigned bridges
  */
-static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
-                                                          struct resource *res)
+static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
+                                                struct resource *res)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pci_dev *dev = bus->self;
@@ -933,7 +930,7 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
 }
 
 /* Fixup resources of a PCI<->PCI bridge */
-static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
+static void pcibios_fixup_bridge(struct pci_bus *bus)
 {
        struct resource *res;
        int i;
@@ -970,14 +967,14 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
        }
 }
 
-void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
+void pcibios_setup_bus_self(struct pci_bus *bus)
 {
        /* Fix up the bus resources for P2P bridges */
        if (bus->self != NULL)
                pcibios_fixup_bridge(bus);
 }
 
-void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
+void pcibios_setup_bus_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -1002,7 +999,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
        }
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        /* When called from the generic PCI probe, read PCI<->PCI bridge
         * bases. This is -not- called when generating the PCI tree from
@@ -1124,7 +1121,7 @@ static int __init reparent_resources(struct resource *parent,
  *         as well.
  */
 
-void pcibios_allocate_bus_resources(struct pci_bus *bus)
+static void pcibios_allocate_bus_resources(struct pci_bus *bus)
 {
        struct pci_bus *b;
        int i;
@@ -1179,7 +1176,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                }
                printk(KERN_WARNING "PCI: Cannot allocate resource region "
                       "%d of PCI bridge %d, will remap\n", i, bus->number);
-clear_resource:
+
                res->start = res->end = 0;
                res->flags = 0;
        }
@@ -1188,7 +1185,7 @@ clear_resource:
                pcibios_allocate_bus_resources(b);
 }
 
-static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
+static inline void alloc_resource(struct pci_dev *dev, int idx)
 {
        struct resource *pr, *r = &dev->resource[idx];
 
@@ -1351,7 +1348,7 @@ void __init pcibios_resource_survey(void)
  * rest of the code later, for now, keep it as-is as our main
  * resource allocation function doesn't deal with sub-trees yet.
  */
-void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+void pcibios_claim_one_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        struct pci_bus *child_bus;
@@ -1410,7 +1407,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return pci_enable_resources(dev, mask);
 }
 
-static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
+static void pcibios_setup_phb_resources(struct pci_controller *hose,
+                                       struct list_head *resources)
 {
        unsigned long io_offset;
        struct resource *res;
@@ -1433,7 +1431,8 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s
                res->end = res->start + IO_SPACE_LIMIT;
                res->flags = IORESOURCE_IO;
        }
-       pci_add_resource_offset(resources, res, hose->io_base_virt - _IO_BASE);
+       pci_add_resource_offset(resources, res,
+               (__force resource_size_t)(hose->io_base_virt - _IO_BASE));
 
        pr_debug("PCI: PHB IO resource    = %016llx-%016llx [%lx]\n",
                 (unsigned long long)res->start,
@@ -1477,7 +1476,7 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
        return of_node_get(hose->dn);
 }
 
-static void __devinit pcibios_scan_phb(struct pci_controller *hose)
+static void pcibios_scan_phb(struct pci_controller *hose)
 {
        LIST_HEAD(resources);
        struct pci_bus *bus;
index d971d1586f1cfa80828e16796c45ab2a4cca3844..9becc44d9d7a13b5f4df1f6871de8999d6b46932 100644 (file)
@@ -4,7 +4,6 @@ config MIPS
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IDE
        select HAVE_OPROFILE
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_ARCH_KGDB
@@ -39,10 +38,8 @@ config MIPS
        select GENERIC_CLOCKEVENTS
        select GENERIC_CMOS_UPDATE
        select HAVE_MOD_ARCH_SPECIFIC
-       select MODULES_USE_ELF_REL
-       select MODULES_USE_ELF_RELA if 64BIT
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
+       select MODULES_USE_ELF_REL if MODULES
+       select MODULES_USE_ELF_RELA if MODULES && 64BIT
 
 menu "Machine selection"
 
@@ -2163,7 +2160,6 @@ source "mm/Kconfig"
 config SMP
        bool "Multi-Processing support"
        depends on SYS_SUPPORTS_SMP
-       select IRQ_PER_CPU
        select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
index a7193ae13a5d2d6ab8df643a76c6b33cd9621421..b67930d1932510dbe90cfc64b2b937d135d162ce 100644 (file)
@@ -53,7 +53,7 @@ static struct clocksource au1x_counter1_clocksource = {
        .read           = au1x_counter1_read,
        .mask           = CLOCKSOURCE_MASK(32),
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-       .rating         = 100,
+       .rating         = 1500,
 };
 
 static int au1x_rtcmatch2_set_next_event(unsigned long delta,
@@ -84,7 +84,7 @@ static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
 static struct clock_event_device au1x_rtcmatch2_clockdev = {
        .name           = "rtcmatch2",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 100,
+       .rating         = 1500,
        .set_next_event = au1x_rtcmatch2_set_next_event,
        .set_mode       = au1x_rtcmatch2_set_mode,
        .cpumask        = cpu_all_mask,
@@ -158,20 +158,6 @@ cntr_err:
        return -1;
 }
 
-static void __init alchemy_setup_c0timer(void)
-{
-       /*
-        * MIPS kernel assigns 'au1k_wait' to 'cpu_wait' before this
-        * function is called.  Because the Alchemy counters are unusable
-        * the C0 timekeeping code is installed and use of the 'wait'
-        * instruction must be prohibited, which is done most easily by
-        * assigning NULL to cpu_wait.
-        */
-       cpu_wait = NULL;
-       r4k_clockevent_init();
-       init_r4k_clocksource();
-}
-
 static int alchemy_m2inttab[] __initdata = {
        AU1000_RTC_MATCH2_INT,
        AU1500_RTC_MATCH2_INT,
@@ -186,8 +172,7 @@ void __init plat_time_init(void)
        int t;
 
        t = alchemy_get_cputype();
-       if (t == ALCHEMY_CPU_UNKNOWN)
-               alchemy_setup_c0timer();
-       else if (alchemy_time_init(alchemy_m2inttab[t]))
-               alchemy_setup_c0timer();
+       if (t == ALCHEMY_CPU_UNKNOWN ||
+           alchemy_time_init(alchemy_m2inttab[t]))
+               cpu_wait = NULL;        /* wait doesn't work with r4k timer */
 }
index d7af29f1fcf0079c7ccdcae5af9f0add4c8c2c80..ba611927749b9f81def164126a2b2b1d00bf42c5 100644 (file)
@@ -8,8 +8,10 @@ config BCM47XX_SSB
        select SSB_DRIVER_EXTIF
        select SSB_EMBEDDED
        select SSB_B43_PCI_BRIDGE if PCI
+       select SSB_DRIVER_PCICORE if PCI
        select SSB_PCICORE_HOSTMODE if PCI
        select SSB_DRIVER_GPIO
+       select GPIOLIB
        default y
        help
         Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -25,6 +27,7 @@ config BCM47XX_BCMA
        select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
        select BCMA_DRIVER_GPIO
+       select GPIOLIB
        default y
        help
         Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
index 9f883bf769530d18c880416850060cd738bb0fa8..33b72144db3100625bd17991c1651ddd803ddf2b 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/compiler.h>
 #include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
@@ -285,22 +286,22 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
  */
 static void fault_in(uint64_t addr, int len)
 {
-       volatile char *ptr;
-       volatile char dummy;
+       char *ptr;
+
        /*
         * Adjust addr and length so we get all cache lines even for
         * small ranges spanning two cache lines.
         */
        len += addr & CVMX_CACHE_LINE_MASK;
        addr &= ~CVMX_CACHE_LINE_MASK;
-       ptr = (volatile char *)cvmx_phys_to_ptr(addr);
+       ptr = cvmx_phys_to_ptr(addr);
        /*
         * Invalidate L1 cache to make sure all loads result in data
         * being in L2.
         */
        CVMX_DCACHE_INVALIDATE;
        while (len > 0) {
-               dummy += *ptr;
+               ACCESS_ONCE(*ptr);
                len -= CVMX_CACHE_LINE_SIZE;
                ptr += CVMX_CACHE_LINE_SIZE;
        }
index 569f41bdcc466529501b4cbeb8ad4133e86e8205..f393f65f3923acd39343a65b1e50d3845d2806c6 100644 (file)
@@ -43,7 +43,7 @@ void octeon_serial_out(struct uart_port *up, int offset, int value)
        cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value);
 }
 
-static int __devinit octeon_serial_probe(struct platform_device *pdev)
+static int octeon_serial_probe(struct platform_device *pdev)
 {
        int irq, res;
        struct resource *res_mem;
diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/asm/break.h
deleted file mode 100644 (file)
index 9161e68..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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) 1995, 2003 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#ifndef __ASM_BREAK_H
-#define __ASM_BREAK_H
-
-/*
- * The following break codes are or were in use for specific purposes in
- * other MIPS operating systems.  Linux/MIPS doesn't use all of them.  The
- * unused ones are here as placeholders; we might encounter them in
- * non-Linux/MIPS object files or make use of them in the future.
- */
-#define BRK_USERBP     0       /* User bp (used by debuggers) */
-#define BRK_KERNELBP   1       /* Break in the kernel */
-#define BRK_ABORT      2       /* Sometimes used by abort(3) to SIGIOT */
-#define BRK_BD_TAKEN   3       /* For bd slot emulation - not implemented */
-#define BRK_BD_NOTTAKEN        4       /* For bd slot emulation - not implemented */
-#define BRK_SSTEPBP    5       /* User bp (used by debuggers) */
-#define BRK_OVERFLOW   6       /* Overflow check */
-#define BRK_DIVZERO    7       /* Divide by zero check */
-#define BRK_RANGE      8       /* Range error check */
-#define BRK_STACKOVERFLOW 9    /* For Ada stackchecking */
-#define BRK_NORLD      10      /* No rld found - not used by Linux/MIPS */
-#define _BRK_THREADBP  11      /* For threads, user bp (used by debuggers) */
-#define BRK_BUG                512     /* Used by BUG() */
-#define BRK_KDB                513     /* Used in KDB_ENTER() */
-#define BRK_MEMU       514     /* Used by FPU emulator */
-#define BRK_KPROBE_BP  515     /* Kprobe break */
-#define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */
-#define BRK_MULOVF     1023    /* Multiply overflow */
-
-#endif /* __ASM_BREAK_H */
index e9bfc0813c72e99a46b29dadb1c3556843fc31a1..7bfad0520e25731c548c949ccecc045e91bba002 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/mipsregs.h>
 
 #define DSP_DEFAULT    0x00000000
-#define DSP_MASK       0x3ff
+#define DSP_MASK       0x3f
 
 #define __enable_dsp_hazard()                                          \
 do {                                                                   \
index ab84064283db2c50d847d888b32e42a4d316dd7d..33c34adbecfa19ae457699d449d8242ed5a0f43c 100644 (file)
@@ -353,6 +353,7 @@ union mips_instruction {
        struct u_format u_format;
        struct c_format c_format;
        struct r_format r_format;
+       struct p_format p_format;
        struct f_format f_format;
        struct ma_format ma_format;
        struct b_format b_format;
index edaa06d9d492171090e10ee08ad370fae79bebe9..e410df4e1b3a650d99d8981c7b63c04d4218daf4 100644 (file)
@@ -21,4 +21,4 @@
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
 
-#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */
+#endif /* __ASM_MIPS_MACH_PNX833X_WAR_H */
index 31ab10f02bad555724dffa1e58556bd6508cd79b..dbaec94046dab06348eb688887b73e2513e3b666 100644 (file)
@@ -45,8 +45,6 @@
 #define HUGETLB_PAGE_ORDER     ({BUILD_BUG(); 0; })
 #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
-#ifndef __ASSEMBLY__
-
 #include <linux/pfn.h>
 #include <asm/io.h>
 
@@ -139,8 +137,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  */
 #define ptep_buddy(x)  ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
 
-#endif /* !__ASSEMBLY__ */
-
 /*
  * __pa()/__va() should be used only during mem init.
  */
@@ -202,7 +198,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #endif
 
 #define virt_to_page(kaddr)    pfn_to_page(PFN_DOWN(virt_to_phys(kaddr)))
-#define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
+
+extern int __virt_addr_valid(const volatile void *kaddr);
+#define virt_addr_valid(kaddr)                                         \
+       __virt_addr_valid((const volatile void *) (kaddr))
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
index 90bf3b3fce199cda78430b3af99770fe82de3fcd..d69ea743272bfc7cac4e559b1f93b4dc6caa5ad5 100644 (file)
@@ -145,7 +145,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 extern char * (*pcibios_plat_setup)(char *str);
 
 /* this function parses memory ranges from a device node */
-extern void __devinit pci_load_of_ranges(struct pci_controller *hose,
-                                        struct device_node *node);
+extern void pci_load_of_ranges(struct pci_controller *hose,
+                              struct device_node *node);
 
 #endif /* _ASM_PCI_H */
index c63191055e695c5a49812f3f32ed0c913d941a0a..013d5f781263e20cf3d9e93cf14b6552c4386cc8 100644 (file)
@@ -230,6 +230,7 @@ static inline void pud_clear(pud_t *pudp)
 #else
 #define pte_pfn(x)             ((unsigned long)((x).pte >> _PFN_SHIFT))
 #define pfn_pte(pfn, prot)     __pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)     __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
 #endif
 
 #define __pgd_offset(address)  pgd_index(address)
index cec5e125f7e466fceb8680f029de9ad040b9c4a3..a3186f2bb8a09aab56fcf5324c2bf7209b2c92c4 100644 (file)
@@ -49,6 +49,7 @@ static inline long regs_return_value(struct pt_regs *regs)
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define user_stack_pointer(r) ((r)->regs[29])
 
 extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
index 18806a52061c3c6869ed03c101ccabe740b64ac8..b2050b9e64b1702c6596553276626a7cd7fc09c4 100644 (file)
@@ -29,10 +29,11 @@ struct thread_info {
        __u32                   cpu;            /* current CPU */
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
 
-       mm_segment_t            addr_limit;     /* thread address space:
-                                                  0-0xBFFFFFFF for user-thead
-                                                  0-0xFFFFFFFF for kernel-thread
-                                               */
+       mm_segment_t            addr_limit;     /*
+                                                * thread address space limit:
+                                                * 0x7fffffff for user-thead
+                                                * 0xffffffff for kernel-thread
+                                                */
        struct restart_block    restart_block;
        struct pt_regs          *regs;
 };
index b306e2081cad9a4c03a66d9c82595e96581140da..9e47cc11aa263ba3991d680736bce6aeea41447e 100644 (file)
@@ -20,7 +20,6 @@
 #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
index a1a0452ac1853333b07dac4dc7495c9bdd2514a5..77d4fb33f75ad1dd765ba69f697ed771312b3e9a 100644 (file)
@@ -3,6 +3,7 @@ include include/uapi/asm-generic/Kbuild.asm
 
 header-y += auxvec.h
 header-y += bitsperlong.h
+header-y += break.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += errno.h
diff --git a/arch/mips/include/uapi/asm/break.h b/arch/mips/include/uapi/asm/break.h
new file mode 100644 (file)
index 0000000..9161e68
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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) 1995, 2003 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_BREAK_H
+#define __ASM_BREAK_H
+
+/*
+ * The following break codes are or were in use for specific purposes in
+ * other MIPS operating systems.  Linux/MIPS doesn't use all of them.  The
+ * unused ones are here as placeholders; we might encounter them in
+ * non-Linux/MIPS object files or make use of them in the future.
+ */
+#define BRK_USERBP     0       /* User bp (used by debuggers) */
+#define BRK_KERNELBP   1       /* Break in the kernel */
+#define BRK_ABORT      2       /* Sometimes used by abort(3) to SIGIOT */
+#define BRK_BD_TAKEN   3       /* For bd slot emulation - not implemented */
+#define BRK_BD_NOTTAKEN        4       /* For bd slot emulation - not implemented */
+#define BRK_SSTEPBP    5       /* User bp (used by debuggers) */
+#define BRK_OVERFLOW   6       /* Overflow check */
+#define BRK_DIVZERO    7       /* Divide by zero check */
+#define BRK_RANGE      8       /* Range error check */
+#define BRK_STACKOVERFLOW 9    /* For Ada stackchecking */
+#define BRK_NORLD      10      /* No rld found - not used by Linux/MIPS */
+#define _BRK_THREADBP  11      /* For threads, user bp (used by debuggers) */
+#define BRK_BUG                512     /* Used by BUG() */
+#define BRK_KDB                513     /* Used in KDB_ENTER() */
+#define BRK_MEMU       514     /* Used by FPU emulator */
+#define BRK_KPROBE_BP  515     /* Kprobe break */
+#define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */
+#define BRK_MULOVF     1023    /* Multiply overflow */
+
+#endif /* __ASM_BREAK_H */
index 3f1237c6c80e440c86c1cfd25784b6a79fd3f9c2..770732cb8d0387e6ce692b0eae45d205681608d1 100644 (file)
@@ -86,12 +86,6 @@ typedef unsigned long old_sigset_t;          /* at least 32 bits */
 
 #define SA_RESTORER    0x04000000      /* Only for o32 */
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index cc98a9dcb01b2b6afb766b61313ede7fc0b3ba31..0eebf3c3e03c26f2a2f310e36f1831bcdad9aec6 100644 (file)
 #define __NR_process_vm_readv          (__NR_Linux + 345)
 #define __NR_process_vm_writev         (__NR_Linux + 346)
 #define __NR_kcmp                      (__NR_Linux + 347)
+#define __NR_finit_module              (__NR_Linux + 348)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            347
+#define __NR_Linux_syscalls            348
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                347
+#define __NR_O32_Linux_syscalls                348
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_process_vm_readv          (__NR_Linux + 304)
 #define __NR_process_vm_writev         (__NR_Linux + 305)
 #define __NR_kcmp                      (__NR_Linux + 306)
+#define __NR_finit_module              (__NR_Linux + 307)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            306
+#define __NR_Linux_syscalls            307
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         306
+#define __NR_64_Linux_syscalls         307
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_process_vm_readv          (__NR_Linux + 309)
 #define __NR_process_vm_writev         (__NR_Linux + 310)
 #define __NR_kcmp                      (__NR_Linux + 311)
+#define __NR_finit_module              (__NR_Linux + 312)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            311
+#define __NR_Linux_syscalls            312
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                311
+#define __NR_N32_Linux_syscalls                312
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 9690998d4ef3e9e99b5628cbb4bf297c90158a10..50285b2c7ffe30d5a54d877f7f0cac075dd59f8c 100644 (file)
@@ -200,6 +200,9 @@ void output_mm_defines(void)
        DEFINE(_PTRS_PER_PMD, PTRS_PER_PMD);
        DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE);
        BLANK();
+       DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+       DEFINE(_PAGE_SIZE, PAGE_SIZE);
+       BLANK();
 }
 
 #ifdef CONFIG_32BIT
index 6a2d758dd8e9ed0b4a0afb043d2972869620834c..83fa1460e294e02cf602cd5d611af6d02abbba39 100644 (file)
 #define MCOUNT_OFFSET_INSNS 4
 #endif
 
+/* Arch override because MIPS doesn't need to run this from stop_machine() */
+void arch_ftrace_update_code(int command)
+{
+       ftrace_modify_all_code(command);
+}
+
 /*
  * Check if the address is in kernel space
  *
@@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
        return 0;
 }
 
+#ifndef CONFIG_64BIT
+static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
+                               unsigned int new_code2)
+{
+       int faulted;
+
+       safe_store_code(new_code1, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+       ip += 4;
+       safe_store_code(new_code2, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+       flush_icache_range(ip, ip + 8); /* original ip + 12 */
+       return 0;
+}
+#endif
+
 /*
  * The details about the calling site of mcount on MIPS
  *
@@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod,
         * needed.
         */
        new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
-
+#ifdef CONFIG_64BIT
        return ftrace_modify_code(ip, new);
+#else
+       /*
+        * On 32 bit MIPS platforms, gcc adds a stack adjust
+        * instruction in the delay slot after the branch to
+        * mcount and expects mcount to restore the sp on return.
+        * This is based on a legacy API and does nothing but
+        * waste instructions so it's being removed at runtime.
+        */
+       return ftrace_modify_code_2(ip, new, INSN_NOP);
+#endif
 }
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
index 8882e5766f27ce5b7a8a57932b4b103b7a69eaa7..8a0096d62812c07ea328bf1c78186e36019538f8 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #include <asm/war.h>
-#include <asm/page.h>
 #include <asm/thread_info.h>
 
 #define PANIC_PIC(msg)                                 \
@@ -483,8 +482,8 @@ NESTED(nmi_handler, PT_SIZE, sp)
        MFC0    k1, CP0_ENTRYHI
        andi    k1, 0xff        /* ASID_MASK */
        MFC0    k0, CP0_EPC
-       PTR_SRL k0, PAGE_SHIFT + 1
-       PTR_SLL k0, PAGE_SHIFT + 1
+       PTR_SRL k0, _PAGE_SHIFT + 1
+       PTR_SLL k0, _PAGE_SHIFT + 1
        or      k1, k0
        MTC0    k1, CP0_ENTRYHI
        mtc0_tlbw_hazard
index ea695d9605e99e1bda75ca3573722a9a3819973f..fcf97312f32812fe6935d0cff13dd7091af33633 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/asmmacro.h>
 #include <asm/irqflags.h>
 #include <asm/regdef.h>
-#include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
index 4c968e7efb747d997ec20ba8ceeb500f4c12807d..1658676733576e74867347f0f7d122df0c5a023e 100644 (file)
@@ -46,9 +46,8 @@
        PTR_L   a5, PT_R9(sp)
        PTR_L   a6, PT_R10(sp)
        PTR_L   a7, PT_R11(sp)
-       PTR_ADDIU       sp, PT_SIZE
 #else
-       PTR_ADDIU       sp, (PT_SIZE + 8)
+       PTR_ADDIU       sp, PT_SIZE
 #endif
 .endm
 
@@ -69,7 +68,9 @@ NESTED(ftrace_caller, PT_SIZE, ra)
        .globl _mcount
 _mcount:
        b       ftrace_stub
-        nop
+       addiu sp,sp,8
+
+       /* When tracing is activated, it calls ftrace_caller+8 (aka here) */
        lw      t1, function_trace_stop
        bnez    t1, ftrace_stub
         nop
index 0441f54b2a6acc9ab27a0d229c1465a8e0fa5975..207f1341578ba73abcffcd0ee7bbeda43f1e5643 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
-#include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
index b14c14d90fc2feedbb25eff71578824a7eff7440..d9c81c5a6c90cfc0800fb96984697aecee900088 100644 (file)
@@ -847,7 +847,6 @@ static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
        [PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
        [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
        [PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
-       [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
 };
 
 /* 24K/34K/1004K cores can share the same cache event map. */
@@ -1115,24 +1114,12 @@ static const struct mips_perf_event xlp_cache_map
                [C(RESULT_ACCESS)]      = { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
                [C(RESULT_MISS)]        = { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
        },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 [C(L1I)] = {
        [C(OP_READ)] = {
                [C(RESULT_ACCESS)]      = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
                [C(RESULT_MISS)]        = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
        },
-       [C(OP_WRITE)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 [C(LL)] = {
        [C(OP_READ)] = {
@@ -1143,10 +1130,6 @@ static const struct mips_perf_event xlp_cache_map
                [C(RESULT_ACCESS)]      = { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
                [C(RESULT_MISS)]        = { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
        },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 [C(DTLB)] = {
        /*
@@ -1154,45 +1137,24 @@ static const struct mips_perf_event xlp_cache_map
         * read and write.
         */
        [C(OP_READ)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
                [C(RESULT_MISS)]        = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
        },
        [C(OP_WRITE)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
                [C(RESULT_MISS)]        = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
        },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 [C(ITLB)] = {
        [C(OP_READ)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
                [C(RESULT_MISS)]        = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
        },
        [C(OP_WRITE)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
                [C(RESULT_MISS)]        = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
        },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 [C(BPU)] = {
        [C(OP_READ)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
                [C(RESULT_MISS)]        = { 0x25, CNTR_ALL },
        },
-       [C(OP_WRITE)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
-       [C(OP_PREFETCH)] = {
-               [C(RESULT_ACCESS)]      = { UNSUPPORTED_PERF_EVENT_ID },
-               [C(RESULT_MISS)]        = { UNSUPPORTED_PERF_EVENT_ID },
-       },
 },
 };
 
index 9c51be5a163a9249efa3bd74f12be62b64eba923..8d32d5a6b460a72b1d9e5b55538febb6e029e70e 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
-#include <asm/page.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/thread_info.h>
index 42d2a3938420df28e64d1f016459529b13991b7e..8decdfacb448c18540e85b8bc516ba39ecba38d9 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
-#include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
index e4142c5f7c2b6f16434275436668f7c17f67c68a..804ebb2c34a6c9cd556acf3e0048f974641eb32f 100644 (file)
@@ -9,7 +9,6 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/regdef.h>
-#include <asm/page.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #include <asm/addrspace.h>
@@ -50,7 +49,7 @@ process_entry:
        and             s3, s2, 0x8
        beq             s3, zero, process_entry
        and             s2, s2, ~0x8
-       li              s6, (1 << PAGE_SHIFT) / SZREG
+       li              s6, (1 << _PAGE_SHIFT) / SZREG
 
 copy_word:
        /* copy page word by word */
index 374f66e05f3d2ab1d59b95da33cf2465dbf1a3bb..d20a4bc9ed05c90191f82a120eb2648d75e2f846 100644 (file)
@@ -583,6 +583,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_process_vm_readv    6       /* 4345 */
        sys     sys_process_vm_writev   6
        sys     sys_kcmp                5
+       sys     sys_finit_module        3
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index 169de6a6d916549ae3e5e5cb079a022314718cbe..b64f642da073f7f7d48ab9a1d54a8f2e749032db 100644 (file)
@@ -422,4 +422,5 @@ sys_call_table:
        PTR     sys_process_vm_readv
        PTR     sys_process_vm_writev           /* 5305 */
        PTR     sys_kcmp
+       PTR     sys_finit_module
        .size   sys_call_table,.-sys_call_table
index ad3de9668da9974c74d6a002b95a3739207e95b3..c29ac197f44694821b3a411954a7d6861e0ba33c 100644 (file)
@@ -416,4 +416,5 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_process_vm_readv
        PTR     compat_sys_process_vm_writev    /* 6310 */
        PTR     sys_kcmp
+       PTR     sys_finit_module
        .size   sysn32_call_table,.-sysn32_call_table
index 9601be6afa3de3b9571215bf75d2fe6c55392a60..cf3e75e466506bc6b73e371818712580bb9d7918 100644 (file)
@@ -540,4 +540,5 @@ sys_call_table:
        PTR     compat_sys_process_vm_readv     /* 4345 */
        PTR     compat_sys_process_vm_writev
        PTR     sys_kcmp
+       PTR     sys_finit_module
        .size   sys_call_table,.-sys_call_table
index 2e6374a589ec622a85dde2ad1c9394b93bd05c68..66bf4e22d9b9451615cd8386caaf9b8016b96a34 100644 (file)
@@ -188,7 +188,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 }
 
 /* preload SMP state for boot cpu */
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        set_cpu_possible(0, true);
        set_cpu_online(0, true);
index 007ccbe1e26474a6788ef61ee046e226c480d877..0a4336b803e9e15f4b6031824849e0ade3062002 100644 (file)
@@ -1,7 +1,8 @@
 #include <asm/asm-offsets.h>
-#include <asm/page.h>
 #include <asm/thread_info.h>
 
+#define PAGE_SIZE _PAGE_SIZE
+
 /*
  * Put .bss..swapper_pg_dir as the first thing in .bss. This will
  * ensure that it has .bss alignment (64K).
index eec690af6581616957089993e2decfd91f13b4fd..147cec19621d7a433429e66433fdd993c2abd62e 100644 (file)
@@ -705,7 +705,7 @@ static int vpe_run(struct vpe * v)
 
                        printk(KERN_WARNING
                               "VPE loader: TC %d is already in use.\n",
-                               t->index);
+                              v->tc->index);
                        return -ENOEXEC;
                }
        } else {
index f36acd1b38086d341458d927c4c4db99d3a40e0f..a7935bf0fecbf789299a2547abb7b0b2e8677e2b 100644 (file)
@@ -408,7 +408,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 #endif
 
        /* tell oprofile which irq to use */
-       cp0_perfcount_irq = LTQ_PERF_IRQ;
+       cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
        /*
         * if the timer irq is not one of the mips irqs we need to
index 6453962ac898f86222587ec98184af6244a812a1..e44a1866653f10fa258df13b3656aa20750002f0 100644 (file)
@@ -210,7 +210,7 @@ ltq_dma_init_port(int p)
 }
 EXPORT_SYMBOL_GPL(ltq_dma_init_port);
 
-static int __devinit
+static int
 ltq_dma_init(struct platform_device *pdev)
 {
        struct clk *clk;
index cbb56fc022bc6817633e1b06e5f54f343a73c7b8..e30b1ed1b93633cfc2b63201f24d85a06c212cae 100644 (file)
@@ -133,7 +133,7 @@ static inline void clkdev_add_gptu(struct device *dev, const char *con,
        clkdev_add(&clk->cl);
 }
 
-static int __devinit gptu_probe(struct platform_device *pdev)
+static int gptu_probe(struct platform_device *pdev)
 {
        struct clk *clk;
        struct resource *res;
index fe808bf5366dd18deb3adcd85adcb1c07905ae02..d4d9d31f152e403ae40a8246fbc2ba665a8521ee 100644 (file)
@@ -54,7 +54,7 @@ static dma_addr_t xway_gphy_load(struct platform_device *pdev)
        return dev_addr;
 }
 
-static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
+static int xway_phy_fw_probe(struct platform_device *pdev)
 {
        dma_addr_t fw_addr;
        struct property *pp;
index dc81ca8dc0dd4b0ccd81ae2edc78b059aa8fd016..288f7954988d06ef61cc94bbf29dfeab322796b8 100644 (file)
@@ -21,7 +21,7 @@ void __delay(unsigned long loops)
        "       .set    noreorder                               \n"
        "       .align  3                                       \n"
        "1:     bnez    %0, 1b                                  \n"
-#if __SIZEOF_LONG__ == 4
+#if BITS_PER_LONG == 32
        "       subu    %0, 1                                   \n"
 #else
        "       dsubu   %0, 1                                   \n"
index d9be7540a6be7979a265a3ce32acbbe241b2b91c..7e5fe2790d8a212a8d0163989280918d26a46a3c 100644 (file)
@@ -192,3 +192,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 
        return ret;
 }
+
+int __virt_addr_valid(const volatile void *kaddr)
+{
+       return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+}
+EXPORT_SYMBOL_GPL(__virt_addr_valid);
index e99eaa1fbedcc7e7cf54e3ba045382b95c708ad4..318855eb5f80309d3e596d33c8130bdbced61bf7 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #include <asm/mipsregs.h>
-#include <asm/page.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
index 05613355627b2435faa5efe89b5c0a476dfa9d0f..1c8ac49ec72cabc7bc66583012bb3d21ac270a7c 100644 (file)
@@ -976,13 +976,6 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 #endif
        uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
        uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
-
-       if (cpu_has_mips_r2) {
-               uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT));
-               uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT));
-               return;
-       }
-
        uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
        uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
        uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1018,15 +1011,6 @@ static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx)
 
 static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
 {
-       if (cpu_has_mips_r2) {
-               /* PTE ptr offset is obtained from BadVAddr */
-               UASM_i_MFC0(p, tmp, C0_BADVADDR);
-               UASM_i_LW(p, ptr, 0, ptr);
-               uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1);
-               uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1);
-               return;
-       }
-
        /*
         * Bug workaround for the Nevada. It seems as if under certain
         * circumstances the move from cp0_context might produce a
index 0375ee66bca3086fa2e35f21999bbfba1c001d99..7aa2225e75b907e0d77b7ed0d1a4f5d66120cba2 100644 (file)
@@ -297,7 +297,7 @@ static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
                priv->base + PIC32_I2CxSTATCLR);
 }
 
-static int __devinit sead3_i2c_platform_probe(struct platform_device *pdev)
+static int sead3_i2c_platform_probe(struct platform_device *pdev)
 {
        struct pic32_i2c_platform_data *priv;
        struct resource *r;
@@ -345,7 +345,7 @@ out:
        return ret;
 }
 
-static int __devexit sead3_i2c_platform_remove(struct platform_device *pdev)
+static int sead3_i2c_platform_remove(struct platform_device *pdev)
 {
        struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
 
@@ -383,7 +383,7 @@ static struct platform_driver sead3_i2c_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = sead3_i2c_platform_probe,
-       .remove         = __devexit_p(sead3_i2c_platform_remove),
+       .remove         = sead3_i2c_platform_remove,
        .suspend        = sead3_i2c_platform_suspend,
        .resume         = sead3_i2c_platform_resume,
 };
index 46509b0a620df0acb66eefc77e4f8118f6c0feb5..514675ed0cde2e27e216da96dffe160c61588290 100644 (file)
@@ -304,8 +304,7 @@ static void i2c_platform_disable(struct i2c_platform_data *priv)
        pr_debug("i2c_platform_disable\n");
 }
 
-static int __devinit
-i2c_platform_probe(struct platform_device *pdev)
+static int i2c_platform_probe(struct platform_device *pdev)
 {
        struct i2c_platform_data *priv;
        struct resource *r;
@@ -362,8 +361,7 @@ out:
        return ret;
 }
 
-static int __devexit
-i2c_platform_remove(struct platform_device *pdev)
+static int i2c_platform_remove(struct platform_device *pdev)
 {
        struct i2c_platform_data *priv = platform_get_drvdata(pdev);
 
@@ -408,7 +406,7 @@ static struct platform_driver i2c_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = i2c_platform_probe,
-       .remove         = __devexit_p(i2c_platform_remove),
+       .remove         = i2c_platform_remove,
        .suspend        = i2c_platform_suspend,
        .resume         = i2c_platform_resume,
 };
index 4e7f49d3d5a8105c45dd09a6b86999ed0506a7d7..c5ce6992ac4c7086aea4167a7460723a5d0cb7be 100644 (file)
@@ -193,8 +193,11 @@ static void nlm_init_node(void)
 
 void __init prom_init(void)
 {
-       int i, *argv, *envp;            /* passed as 32 bit ptrs */
+       int *argv, *envp;               /* passed as 32 bit ptrs */
        struct psb_info *prom_infop;
+#ifdef CONFIG_SMP
+       int i;
+#endif
 
        /* truncate to 32 bit and sign extend all args */
        argv = (int *)(long)(int)fw_arg1;
index 3e7ce65d776c83ff32a935d38320153c913f54b9..9553b14002dda51a757cf06ccb0bca5483b86c1a 100644 (file)
@@ -37,7 +37,7 @@
 #define VIA_COBALT_BRD_ID_REG  0x94
 #define VIA_COBALT_BRD_REG_to_ID(reg)  ((unsigned char)(reg) >> 4)
 
-static void __devinit qube_raq_galileo_early_fixup(struct pci_dev *dev)
+static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
 {
        if (dev->devfn == PCI_DEVFN(0, 0) &&
                (dev->class >> 8) == PCI_CLASS_MEMORY_OTHER) {
@@ -51,7 +51,7 @@ static void __devinit qube_raq_galileo_early_fixup(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
         qube_raq_galileo_early_fixup);
 
-static void __devinit qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
+static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
 {
        unsigned short cfgword;
        unsigned char lt;
@@ -74,7 +74,7 @@ static void __devinit qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
         qube_raq_via_bmIDE_fixup);
 
-static void __devinit qube_raq_galileo_fixup(struct pci_dev *dev)
+static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
        if (dev->devfn != PCI_DEVFN(0, 0))
                return;
@@ -129,7 +129,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
 
 int cobalt_board_id;
 
-static void __devinit qube_raq_via_board_id_fixup(struct pci_dev *dev)
+static void qube_raq_via_board_id_fixup(struct pci_dev *dev)
 {
        u8 id;
        int retval;
index 0d9ccf4dfc5abc5b7263361eef22444861507a86..beaec32b02e54f3b77a2a3d01dbb0fdb5526e674 100644 (file)
@@ -52,7 +52,7 @@ static unsigned char irq_map[][5] __initdata = {
               MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,},
 };
 
-static void __devinit nec_usb_controller_fixup(struct pci_dev *dev)
+static void nec_usb_controller_fixup(struct pci_dev *dev)
 {
        if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT)
                /* on board USB controller configuration */
@@ -67,7 +67,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
  * if it is the host bridge by marking it as such.  These resources are of
  * no consequence to the PCI layer (they are handled elsewhere).
  */
-static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
+static void emma2rh_pci_host_fixup(struct pci_dev *dev)
 {
        int i;
 
index 0857ab8c3919750feb164b3649f60df502290312..63ab4a042cd6e4a4f5dec5f0beafb548000b6e0d 100644 (file)
@@ -48,7 +48,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __devinit loongson2e_nec_fixup(struct pci_dev *pdev)
+static void loongson2e_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
@@ -60,7 +60,7 @@ static void __devinit loongson2e_nec_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, 0xe4, 1 << 5);
 }
 
-static void __devinit loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+static void loongson2e_686b_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char c;
 
@@ -135,7 +135,7 @@ static void __devinit loongson2e_686b_func0_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: ISA bridge done\n");
 }
 
-static void __devinit loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+static void loongson2e_686b_func1_fixup(struct pci_dev *pdev)
 {
        printk(KERN_INFO"via686b fix: IDE\n");
 
@@ -168,19 +168,19 @@ static void __devinit loongson2e_686b_func1_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: IDE done\n");
 }
 
-static void __devinit loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+static void loongson2e_686b_func2_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
 }
 
-static void __devinit loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+static void loongson2e_686b_func3_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
 }
 
-static void __devinit loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+static void loongson2e_686b_func5_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
        unsigned char c;
index a7b917dcf604bde1ee359b20fb203356c0e4a84e..519daaebb5da6cae81e4fedd5ea76a557f8fc464 100644 (file)
@@ -96,21 +96,21 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 }
 
 /* CS5536 SPEC. fixup */
-static void __devinit loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+static void loongson_cs5536_isa_fixup(struct pci_dev *pdev)
 {
        /* the uart1 and uart2 interrupt in PIC is enabled as default */
        pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
        pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
 }
 
-static void __devinit loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+static void loongson_cs5536_ide_fixup(struct pci_dev *pdev)
 {
        /* setting the mutex pin as IDE function */
        pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
                               CS5536_IDE_FLASH_SIGNATURE);
 }
 
-static void __devinit loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+static void loongson_cs5536_acc_fixup(struct pci_dev *pdev)
 {
        /* enable the AUDIO interrupt in PIC  */
        pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
@@ -118,14 +118,14 @@ static void __devinit loongson_cs5536_acc_fixup(struct pci_dev *pdev)
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
 }
 
-static void __devinit loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+static void loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
 {
        /* enable the OHCI interrupt in PIC */
        /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
        pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
 }
 
-static void __devinit loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+static void loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
 {
        u32 hi, lo;
 
@@ -137,7 +137,7 @@ static void __devinit loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
 }
 
-static void __devinit loongson_nec_fixup(struct pci_dev *pdev)
+static void loongson_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index 9a1a2244522a10972ec20aca833f32cf1dc4dba0..75d03f6be3bde7fcc59cb65e45518384560ae5cf 100644 (file)
@@ -8,7 +8,7 @@
 #define PCID           4
 
 /* This table is filled in by interrogating the PIIX4 chip */
-static char pci_irq[5] __devinitdata = {
+static char pci_irq[5] = {
 };
 
 static char irq_tab[][5] __initdata = {
@@ -50,10 +50,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __devinit malta_piix_func0_fixup(struct pci_dev *pdev)
+static void malta_piix_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
-       static int piixirqmap[16] __devinitdata = {  /* PIIX PIRQC[A:D] irq mappings */
+       static int piixirqmap[16] = {  /* PIIX PIRQC[A:D] irq mappings */
                0,  0,  0,  3,
                4,  5,  6,  7,
                0,  9, 10, 11,
@@ -84,7 +84,7 @@ static void __devinit malta_piix_func0_fixup(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
         malta_piix_func0_fixup);
 
-static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev)
+static void malta_piix_func1_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
 
@@ -104,7 +104,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
         malta_piix_func1_fixup);
 
 /* Enable PCI 2.1 compatibility in PIIX4 */
-static void __devinit quirk_dlcsetup(struct pci_dev *dev)
+static void quirk_dlcsetup(struct pci_dev *dev)
 {
        u8 odlc, ndlc;
 
index 76bb1be99d432bc935af5ee93698093dafa42d8a..d0f6ecbf35f7486c2435dc0375312b51929450b1 100644 (file)
 #include <asm/mach-rc32434/rc32434.h>
 #include <asm/mach-rc32434/irq.h>
 
-static int __devinitdata irq_map[2][12] = {
+static int irq_map[2][12] = {
        {0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1},
        {0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3}
 };
 
-int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = 0;
 
@@ -47,7 +47,7 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return irq + GROUP4_IRQ_BASE + 4;
 }
 
-static void __devinit rc32434_pci_early_fixup(struct pci_dev *dev)
+static void rc32434_pci_early_fixup(struct pci_dev *dev)
 {
        if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) {
                /* disable prefetched memory range */
index d02900a72916869dc39a03d0dd2075a5f8e85d82..1441becdcb6c1cf32cf19c728f1b58bf8859d31f 100644 (file)
@@ -15,7 +15,7 @@
  * Set the BCM1250, etc. PCI host bridge's TRDY timeout
  * to the finite max.
  */
-static void __devinit quirk_sb1250_pci(struct pci_dev *dev)
+static void quirk_sb1250_pci(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x40, 0xff);
 }
@@ -25,7 +25,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
 /*
  * The BCM1250, etc. PCI/HT bridge reports as a host bridge.
  */
-static void __devinit quirk_sb1250_ht(struct pci_dev *dev)
+static void quirk_sb1250_ht(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
@@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
 /*
  * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
  */
-static void __devinit quirk_sp1011(struct pci_dev *dev)
+static void quirk_sp1011(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x64, 0xff);
 }
index 65c7bd1004860d3e3eb7490d98f78c4718e5be81..4a156629e958168c2060ff6d40af2ffe72c29980 100644 (file)
@@ -411,7 +411,7 @@ struct pci_ops bcm63xx_cb_ops = {
  * only one IO window, so it  cannot be shared by PCI and cardbus, use
  * fixup to choose and detect unhandled configuration
  */
-static void __devinit bcm63xx_fixup(struct pci_dev *dev)
+static void bcm63xx_fixup(struct pci_dev *dev)
 {
        static int io_window = -1;
        int i, found, new_io_window;
index bc13e29d2bb34d6f9a257322e222b943da533c1c..0d69d6f4ea44f72ec828c972e5d49a2d6c34902a 100644 (file)
@@ -191,13 +191,13 @@ static struct {
        u8 trdyto;
        u8 retryto;
        u16 gbwc;
-} tx4927_pci_opts __devinitdata = {
+} tx4927_pci_opts = {
        .trdyto = 0,
        .retryto = 0,
        .gbwc = 0xfe0,  /* 4064 GBUSCLK for CCFG.GTOT=0b11 */
 };
 
-char *__devinit tx4927_pcibios_setup(char *str)
+char *tx4927_pcibios_setup(char *str)
 {
        unsigned long val;
 
@@ -495,7 +495,7 @@ irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id)
 }
 
 #ifdef CONFIG_TOSHIBA_FPCIB0
-static void __devinit tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
+static void tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus);
 
index ec125bed721c5f616fb45493cf827d465ca2ced1..c4ea6cc55f946c9fe144c4225160be5e74b587ca 100644 (file)
@@ -356,7 +356,7 @@ static struct syscore_ops alchemy_pci_pmops = {
        .resume         = alchemy_pci_resume,
 };
 
-static int __devinit alchemy_pci_probe(struct platform_device *pdev)
+static int alchemy_pci_probe(struct platform_device *pdev)
 {
        struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
        struct alchemy_pci_context *ctx;
index 1552522b8718bffb86762229ef5279b93094df16..6eaa4f2d0e38cb8c85e31734c7e090ec9a491cb3 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/mach-ath79/pci.h>
 
 #define AR71XX_PCI_MEM_BASE    0x10000000
-#define AR71XX_PCI_MEM_SIZE    0x08000000
+#define AR71XX_PCI_MEM_SIZE    0x07000000
 
 #define AR71XX_PCI_WIN0_OFFS           0x10000000
 #define AR71XX_PCI_WIN1_OFFS           0x11000000
index 86d77a666458bae80c60f94c9fc405dca5f8459c..c11c75be2d7e06ab0b1232c35926a8ec3c5ba574 100644 (file)
@@ -21,7 +21,7 @@
 #define AR724X_PCI_CTRL_SIZE   0x100
 
 #define AR724X_PCI_MEM_BASE    0x10000000
-#define AR724X_PCI_MEM_SIZE    0x08000000
+#define AR724X_PCI_MEM_SIZE    0x04000000
 
 #define AR724X_PCI_REG_RESET           0x18
 #define AR724X_PCI_REG_INT_STATUS      0x4c
index fdc24440294c7028c6fdf7e2a655b896dbe60ef7..7f4f49b09b5b90ba62b1cae28685066b11063ff2 100644 (file)
@@ -143,7 +143,7 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid)
  * A given PCI device, in general, should be able to intr any of the cpus
  * on any one of the hubs connected to its xbow.
  */
-int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return 0;
 }
@@ -212,7 +212,7 @@ static inline void pci_enable_swapping(struct pci_dev *dev)
        bridge->b_widget.w_tflush;      /* Flush */
 }
 
-static void __devinit pci_fixup_ioc3(struct pci_dev *d)
+static void pci_fixup_ioc3(struct pci_dev *d)
 {
        pci_disable_swapping(d);
 }
index 075d87acd12ac4158e090b7918250e958f0d8c05..95681789b51e44978c5725701e889abf28da1b00 100644 (file)
@@ -95,7 +95,7 @@ static inline u32 ltq_calc_bar11mask(void)
        return bar11mask;
 }
 
-static int __devinit ltq_pci_startup(struct platform_device *pdev)
+static int ltq_pci_startup(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
        const __be32 *req_mask, *bus_clk;
@@ -201,7 +201,7 @@ static int __devinit ltq_pci_startup(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit ltq_pci_probe(struct platform_device *pdev)
+static int ltq_pci_probe(struct platform_device *pdev)
 {
        struct resource *res_cfg, *res_bridge;
 
index 4040416e060316e2fd2b1bb647e3048c89e37379..a1843448fad38de52d8a53316ade498a8a7bd5b8 100644 (file)
@@ -76,7 +76,7 @@ pcibios_align_resource(void *data, const struct resource *res,
        return start;
 }
 
-static void __devinit pcibios_scanbus(struct pci_controller *hose)
+static void pcibios_scanbus(struct pci_controller *hose)
 {
        static int next_busno;
        static int need_domain_info;
@@ -120,8 +120,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
 }
 
 #ifdef CONFIG_OF
-void __devinit pci_load_of_ranges(struct pci_controller *hose,
-                               struct device_node *node)
+void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
 {
        const __be32 *ranges;
        int rlen;
@@ -174,7 +173,7 @@ void __devinit pci_load_of_ranges(struct pci_controller *hose,
 
 static DEFINE_MUTEX(pci_scan_mutex);
 
-void __devinit register_pci_controller(struct pci_controller *hose)
+void register_pci_controller(struct pci_controller *hose)
 {
        if (request_resource(&iomem_resource, hose->mem_resource) < 0)
                goto out;
@@ -303,7 +302,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return pcibios_plat_dev_init(dev);
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev = bus->self;
 
index f8a751c032823f25f088530d53acb23fdd11d5e2..61e2558a2dcb9414a35a51ad2deecc29d7554cc7 100644 (file)
@@ -8,7 +8,6 @@
  *         Wu Zhangjin <wuzhangjin@gmail.com>
  */
 #include <asm/asm-offsets.h>
-#include <asm/page.h>
 #include <asm/regdef.h>
 #include <asm/asm.h>
 
@@ -35,7 +34,7 @@ LEAF(swsusp_arch_resume)
 0:
        PTR_L t1, PBE_ADDRESS(t0)   /* source */
        PTR_L t2, PBE_ORIG_ADDRESS(t0) /* destination */
-       PTR_ADDU t3, t1, PAGE_SIZE
+       PTR_ADDU t3, t1, _PAGE_SIZE
 1:
        REG_L t8, (t1)
        REG_S t8, (t2)
index d6c7bd4b5ab0a5c7980a6a949be8c6597c0f59bb..2e9c283b8e688a4907ad8ff674d0d14870beab67 100644 (file)
@@ -236,7 +236,7 @@ void __init plat_mem_setup(void)
 #include <video/vga.h>
 #include <video/cirrus.h>
 
-static void __devinit quirk_cirrus_ram_size(struct pci_dev *dev)
+static void quirk_cirrus_ram_size(struct pci_dev *dev)
 {
        u16 cmd;
 
index b14ee53581a9674fc53cbdef9555dbaf0513897e..ce8f8b9b930cabf88df93cf8da95df820436cd51 100644 (file)
@@ -256,8 +256,7 @@ static irqreturn_t i8259_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit
-txx9_i8259_irq_setup(int irq)
+static int txx9_i8259_irq_setup(int irq)
 {
        int err;
 
@@ -269,7 +268,7 @@ txx9_i8259_irq_setup(int irq)
        return err;
 }
 
-static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)
+static void quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        int irq;        /* PCI/ISA Bridge interrupt */
        u8 reg_64;
@@ -304,7 +303,7 @@ static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)
        smsc_fdc37m81x_config_end();
 }
 
-static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
+static void quirk_slc90e66_ide(struct pci_dev *dev)
 {
        unsigned char dat;
        int regs[2] = {0x41, 0x43};
@@ -339,7 +338,7 @@ static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
 }
 #endif /* CONFIG_TOSHIBA_FPCIB0 */
 
-static void __devinit tc35815_fixup(struct pci_dev *dev)
+static void tc35815_fixup(struct pci_dev *dev)
 {
        /* This device may have PM registers but not they are not supported. */
        if (dev->pm_cap) {
@@ -348,7 +347,7 @@ static void __devinit tc35815_fixup(struct pci_dev *dev)
        }
 }
 
-static void __devinit final_fixup(struct pci_dev *dev)
+static void final_fixup(struct pci_dev *dev)
 {
        unsigned char bist;
 
index 72471744a9124f36ca33b9f4bbd583fd96f88c2a..e70001cfa05b1ee650b132f9163e72766f2fbb5c 100644 (file)
@@ -6,10 +6,9 @@ config MN10300
        select ARCH_WANT_IPC_PARSE_VERSION
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_KGDB
+       select GENERIC_ATOMIC64
        select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
        select GENERIC_CLOCKEVENTS
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select MODULES_USE_ELF_RELA
 
 config AM33_2
index c1be4397b1edb4b059e917331c5ef8173bcf1096..a18abfc558eb1d41b99cd22798976f517196b7bd 100644 (file)
@@ -168,4 +168,19 @@ void dma_cache_sync(void *vaddr, size_t size,
        mn10300_dcache_flush_inv();
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif
index cabf8ba73b27ca050410c7c203daf9138ceac846..e6d2ed4ba68f5ac01557e4a4375da4dc016bdb04 100644 (file)
@@ -43,7 +43,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 08dcd6a856180a52f74fd5b13f897ec112336e35..f423a08d7eeb02d8e92c120731cd7d4cf5b14574 100644 (file)
@@ -92,12 +92,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER    0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index 95983cd21e77e45a47be44ea41c82b59479b9c25..5d7e152a23b7d2b03921aca402d4538b55672144 100644 (file)
@@ -905,7 +905,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
  * Set up the cpu_online_mask, cpu_callout_map and cpu_callin_map of the boot
  * processor (CPU 0).
  */
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        cpumask_set_cpu(0, &cpu_callout_map);
        cpumask_set_cpu(0, &cpu_callin_map);
@@ -930,7 +930,7 @@ void initialize_secondary(void)
  * __cpu_up - Set smp_commenced_mask for the nominated CPU
  * @cpu: The target CPU.
  */
-int __devinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int timeout;
 
index e2059486d3f84b9bbee412c809aae8acfb21056e..6911e845b8cdff49dc85f50f91d2f905c3e2f1c1 100644 (file)
@@ -282,7 +282,7 @@ static int __init pci_check_direct(void)
        return -ENODEV;
 }
 
-static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
+static int is_valid_resource(struct pci_dev *dev, int idx)
 {
        unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
        struct resource *devr = &dev->resource[idx], *busr;
@@ -302,7 +302,7 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
        return 0;
 }
 
-static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+static void pcibios_fixup_device_resources(struct pci_dev *dev)
 {
        int limit, i;
 
@@ -325,7 +325,7 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
  *  Called after each bus is probed, but before its children
  *  are examined.
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
index ec37e185d20d82333c7e4f46cce5d721b99d98c2..0ac66f67521f243024a40c850ec3c4da9995a724 100644 (file)
@@ -22,8 +22,6 @@ config OPENRISC
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config MMU
        def_bool y
index 07f5299d6c28814bb9b56e3b3af70c4770508c8f..7c691399da3f16c9b7eabe4d453a549ec611b8ee 100644 (file)
@@ -30,6 +30,7 @@
 #define PIO_MASK               0
 
 #include <asm-generic/io.h>
+#include <asm/pgtable.h>
 
 extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
                                pgprot_t prot);
index 5082b8066325e7152c0a66b31696deb6f49368c9..ce40b71df0069d8516a94141556cb37ab32819ee 100644 (file)
@@ -20,7 +20,6 @@
 
 #define sys_mmap2 sys_mmap_pgoff
 
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_CLONE
 
index c330767c921747ac089339bcf565c5151160fe7e..c82b09f4a106ce15d2a0b243f5ec40f135cd2b7d 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/timex.h>
 #include <asm/processor.h>
 
-int __devinit read_current_timer(unsigned long *timer_value)
+int read_current_timer(unsigned long *timer_value)
 {
        *timer_value = mfspr(SPR_TTCR);
        return 0;
index e688a2be30f6a78659da7a2067c82a6c1808eb52..a32e34ecda9e49f9d3ee88e8c94621d441026bd0 100644 (file)
@@ -9,21 +9,17 @@ config PARISC
        select RTC_DRV_GENERIC
        select INIT_ALL_POSSIBLE
        select BUG
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_GENERIC_HARDIRQS
        select BROKEN_RODATA
        select GENERIC_IRQ_PROBE
        select GENERIC_PCI_IOMAP
-       select IRQ_PER_CPU
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select CLONE_BACKWARDS
 
        help
index 467bbd510eac04a5bc86a3f97f70332cf636ec19..106b395688e1d167bf764a76de70d5d58e4109d7 100644 (file)
@@ -238,4 +238,19 @@ void * sba_get_iommu(struct parisc_device *dev);
 /* At the moment, we panic on error for IOMMU resource exaustion */
 #define dma_mapping_error(dev, x)      0
 
+/* This API cannot be supported on PA-RISC */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif
index 00d9cc3e7b973db94227548da49dfe48208142b2..c391d7cbc22389cf9c74591fffd64bd6c94df1a4 100644 (file)
@@ -8,7 +8,7 @@
 #define _ASM_PARPORT_H 1
 
 
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
        /* nothing ! */
        return 0;
index 1efef41659c9a570ee15e5b2bea1313f2b2b2991..3043194547cdc8d256ca5008846f836d95e6a864 100644 (file)
@@ -163,7 +163,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index b1ddaa243376e8106fd7fdfa199a1b2ecfe6f32d..a2fa297196bc19f1de4f021ebec6e5338b237313 100644 (file)
 
 #define SA_RESTORER    0x04000000 /* obsolete -- ignored */
 
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index bfb44247d7a7b023d1953d5983a110fc69966995..eb7850b46c255e98cc9c97ef873766f793398061 100644 (file)
@@ -1865,7 +1865,7 @@ syscall_restore:
 
        /* Are we being ptraced? */
        ldw     TASK_FLAGS(%r1),%r19
-       ldi     (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2
+       ldi     _TIF_SYSCALL_TRACE_MASK,%r2
        and,COND(=)     %r19,%r2,%r0
        b,n     syscall_restore_rfi
 
@@ -1978,15 +1978,23 @@ syscall_restore_rfi:
        /* sr2 should be set to zero for userspace syscalls */
        STREG   %r0,TASK_PT_SR2(%r1)
 
-pt_regs_ok:
        LDREG   TASK_PT_GR31(%r1),%r2
-       depi    3,31,2,%r2                         /* ensure return to user mode. */
-       STREG   %r2,TASK_PT_IAOQ0(%r1)
+       depi    3,31,2,%r2                 /* ensure return to user mode. */
+       STREG   %r2,TASK_PT_IAOQ0(%r1)
        ldo     4(%r2),%r2
        STREG   %r2,TASK_PT_IAOQ1(%r1)
+       b       intr_restore
        copy    %r25,%r16
+
+pt_regs_ok:
+       LDREG   TASK_PT_IAOQ0(%r1),%r2
+       depi    3,31,2,%r2                 /* ensure return to user mode. */
+       STREG   %r2,TASK_PT_IAOQ0(%r1)
+       LDREG   TASK_PT_IAOQ1(%r1),%r2
+       depi    3,31,2,%r2
+       STREG   %r2,TASK_PT_IAOQ1(%r1)
        b       intr_restore
-       nop
+       copy    %r25,%r16
 
        .import schedule,code
 syscall_do_resched:
index f48a640b55fbe553fd191eace94be5a8d66aa0cf..f7752f6af29e090e559d74e0d8d1206bd50a72ef 100644 (file)
@@ -38,7 +38,7 @@
  *     so don't reference this table after starting the init process
  */
  
-static struct hp_hardware hp_hardware_list[] __devinitdata = {
+static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
        {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
        {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
@@ -1230,7 +1230,7 @@ static struct hp_cpu_type_mask {
        unsigned short model;
        unsigned short mask;
        enum cpu_type cpu;
-} hp_cpu_type_mask_list[] __devinitdata = {
+} hp_cpu_type_mask_list[] = {
 
        { 0x0000, 0x0ff0, pcx    },  /* 0x0000 - 0x000f */
        { 0x0048, 0x0ff0, pcxl   },  /* 0x0040 - 0x004f */
@@ -1327,8 +1327,7 @@ const char * const cpu_name_version[][2] = {
        [mako2] = { "PA8900 (Shortfin)",        "2.0" }
 };
 
-const char * __devinit
-parisc_hardware_description(struct parisc_device_id *id)
+const char *parisc_hardware_description(struct parisc_device_id *id)
 {
        struct hp_hardware *listptr;
        
index c0b1affc06a8fdce9163cf06a384cc958705fa59..0299d63cd1128d9dc1e6d1877033565cf0cd672d 100644 (file)
@@ -410,11 +410,13 @@ void __init init_IRQ(void)
 {
        local_irq_disable();    /* PARANOID - should already be disabled */
        mtctl(~0UL, 23);        /* EIRR : clear all pending external intr */
-       claim_cpu_irqs();
 #ifdef CONFIG_SMP
-       if (!cpu_eiem)
+       if (!cpu_eiem) {
+               claim_cpu_irqs();
                cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
+       }
 #else
+       claim_cpu_irqs();
        cpu_eiem = EIEM_MASK(TIMER_IRQ);
 #endif
         set_eiem(cpu_eiem);    /* EIEM : enable all external intr */
index 857c2f545470522bb51345dfaacb4f31e971113e..534abd4936e1ecf96a8f872d9ba90f930c1aff9e 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/asm-offsets.h>
 
 /* PSW bits we allow the debugger to modify */
-#define USER_PSW_BITS  (PSW_N | PSW_V | PSW_CB)
+#define USER_PSW_BITS  (PSW_N | PSW_B | PSW_V | PSW_CB)
 
 /*
  * Called by kernel/ptrace.c when detaching..
index 53799695599872565f1ad8c387cbf0e1b91ceb3d..fd051705a407dd7396ee2205c1fecf5eebc34bb4 100644 (file)
@@ -190,8 +190,10 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
                        (unsigned long)ka, sp, frame_size);
        
+       /* Align alternate stack and reserve 64 bytes for the signal
+          handler's frame marker.  */
        if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-               sp = current->sas_ss_sp; /* Stacks grow up! */
+               sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
 
        DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
        return (void __user *) sp; /* Stacks grow up.  Fun. */
index 9071e093164af3ee8a7907a9b26521b8360121e8..933423fa5144aca0b32a8110d88ff20abc98b90e 100644 (file)
     Sgl_isinexact_to_fix(sgl_value,exponent)
 
 #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)  \
-  {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */           \
+  {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH;               \
     if (exponent <= 31) {                                              \
-       Dintp1(dresultA) = 0;                                           \
-       Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+       Dintp1(dresultA) = 0;                                           \
+       Dintp2(dresultB) = val >> (31 - exponent);                      \
     }                                                                  \
     else {                                                             \
-       Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);          \
-       Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);          \
+       Dintp1(dresultA) = val >> (63 - exponent);                      \
+       Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0; \
     }                                                                  \
-    Sall(sgl_value) >>= SGL_EXP_LENGTH;  /* return to original */      \
   }
 
 #define Duint_setzero(dresultA,dresultB)       \
index 951a517a1a0fbedd3d9d1ca87bbcfab24986f9a1..561ccca7b1a7aa3c36d82beeb2f764568c45fecb 100644 (file)
@@ -118,14 +118,12 @@ config PPC
        select HAVE_SYSCALL_WRAPPERS if PPC64
        select GENERIC_ATOMIC64 if PPC32
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
        select HAVE_GENERIC_HARDIRQS
        select ARCH_WANT_IPC_PARSE_VERSION
        select SPARSE_IRQ
-       select IRQ_PER_CPU
        select IRQ_DOMAIN
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
@@ -141,10 +139,8 @@ config PPC
        select GENERIC_CLOCKEVENTS
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
-       select GENERIC_KERNEL_THREAD
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_EXECVE
        select CLONE_BACKWARDS
 
 config EARLY_PRINTK
index 29bb11ec6c640677a73c3e16058897789f1fba2f..4f35fc4623856888f441489e3a43abc6750ccd50 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_PPC64=y
 CONFIG_PPC_BOOK3E_64=y
-# CONFIG_VIRT_CPU_ACCOUNTING is not set
+# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=256
 CONFIG_EXPERIMENTAL=y
index 88fa5c46f66f5481e2d62dfc0e4990fff4f782f3..f7df8362911fc80644b03badd8c639538ff59afd 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_PPC64=y
 CONFIG_PPC_BOOK3E_64=y
-# CONFIG_VIRT_CPU_ACCOUNTING is not set
+# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_EXPERIMENTAL=y
index 840a2c2d043085434b715dfffa3d4399e70f383b..bcedeea0df8934424b94fc30d7c567f0a0b611ca 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
-# CONFIG_VIRT_CPU_ACCOUNTING is not set
+# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_EXPERIMENTAL=y
index 483733bd06d4e9bda0689c4fba66849e2471b7c2..607559ab271ff98b45de1f11964416bebaf32841 100644 (file)
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in
+ * If we have CONFIG_VIRT_CPU_ACCOUNTING_NATIVE, we measure cpu time in
  * the same units as the timebase.  Otherwise we measure cpu time
  * in jiffies using the generic definitions.
  */
@@ -16,7 +16,7 @@
 #ifndef __POWERPC_CPUTIME_H
 #define __POWERPC_CPUTIME_H
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 #include <asm-generic/cputime.h>
 #ifdef __KERNEL__
 static inline void setup_cputime_one_jiffy(void) { }
@@ -231,5 +231,5 @@ static inline cputime_t clock_t_to_cputime(const unsigned long clk)
 static inline void arch_vtime_task_switch(struct task_struct *tsk) { }
 
 #endif /* __KERNEL__ */
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 #endif /* __POWERPC_CPUTIME_H */
index b0ef73882b3847763117f7b0ccb6a123a227e9a5..a8fb03e22770fe9f4f82b5fceb24db81ca7e1edc 100644 (file)
@@ -183,7 +183,7 @@ static inline void eeh_unlock(void)
 #define EEH_MAX_ALLOWED_FREEZES 5
 
 typedef void *(*eeh_traverse_func)(void *data, void *flag);
-int __devinit eeh_phb_pe_create(struct pci_controller *phb);
+int eeh_phb_pe_create(struct pci_controller *phb);
 int eeh_add_to_parent_pe(struct eeh_dev *edev);
 int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
 void *eeh_pe_dev_traverse(struct eeh_pe *root,
@@ -191,8 +191,8 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
 void eeh_pe_restore_bars(struct eeh_pe *pe);
 struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
 
-void * __devinit eeh_dev_init(struct device_node *dn, void *data);
-void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);
+void *eeh_dev_init(struct device_node *dn, void *data);
+void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
 unsigned long eeh_check_failure(const volatile void __iomem *token,
index fbae492869264f1e6d4cf94504fe8d353e35e757..f96dd096ff4e28b74c740bd582ff73989fec784b 100644 (file)
@@ -31,8 +31,8 @@ struct iowa_bus {
        void   *private;
 };
 
-void __devinit iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
-                                int (*)(struct iowa_bus *, void *), void *);
+void iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
+                      int (*)(struct iowa_bus *, void *), void *);
 struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR);
 struct iowa_bus *iowa_pio_find_bus(unsigned long);
 
index 531fe0c3108f8e157b8a255cb6a2ae8fce142059..b1e7f2af1016c82e6584731a0d0112b80a5eb277 100644 (file)
@@ -145,7 +145,7 @@ struct dtl_entry {
 extern struct kmem_cache *dtl_cache;
 
 /*
- * When CONFIG_VIRT_CPU_ACCOUNTING = y, the cpu accounting code controls
+ * When CONFIG_VIRT_CPU_ACCOUNTING_NATIVE = y, the cpu accounting code controls
  * reading from the dispatch trace log.  If other code wants to consume
  * DTL entries, it can set this pointer to a function that will get
  * called once for each DTL entry that gets processed.
index 1ca1102b4a2f0386b5ee2993588d6fb48f832a91..6dc2577932b13cc0694fa4c6b14942695a036379 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <asm/prom.h>
 
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
        struct device_node *np;
        const u32 *prop;
index 9710be3a2d1753e7fef95287d182811e5ce5a0ba..136bba62efa48775bd8b4738f675e8796b0ee0b2 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <asm/hw_irq.h>
+#include <linux/device.h>
 
 #define MAX_HWEVENTS           8
 #define MAX_EVENT_ALTERNATIVES 8
@@ -35,6 +36,7 @@ struct power_pmu {
        void            (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
        int             (*limited_pmc_event)(u64 event_id);
        u32             flags;
+       const struct attribute_group    **attr_groups;
        int             n_generic;
        int             *generic_events;
        int             (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
@@ -109,3 +111,27 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
  * If an event_id is not subject to the constraint expressed by a particular
  * field, then it will have 0 in both the mask and value for that field.
  */
+
+extern ssize_t power_events_sysfs_show(struct device *dev,
+                               struct device_attribute *attr, char *page);
+
+/*
+ * EVENT_VAR() is same as PMU_EVENT_VAR with a suffix.
+ *
+ * Having a suffix allows us to have aliases in sysfs - eg: the generic
+ * event 'cpu-cycles' can have two entries in sysfs: 'cpu-cycles' and
+ * 'PM_CYC' where the latter is the name by which the event is known in
+ * POWER CPU specification.
+ */
+#define        EVENT_VAR(_id, _suffix)         event_attr_##_id##_suffix
+#define        EVENT_PTR(_id, _suffix)         &EVENT_VAR(_id, _suffix).attr.attr
+
+#define        EVENT_ATTR(_name, _id, _suffix)                                 \
+       PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id,    \
+                       power_events_sysfs_show)
+
+#define        GENERIC_EVENT_ATTR(_name, _id)  EVENT_ATTR(_name, _id, _g)
+#define        GENERIC_EVENT_PTR(_id)          EVENT_PTR(_id, _g)
+
+#define        POWER_EVENT_ATTR(_name, _id)    EVENT_ATTR(PM_##_name, _id, _p)
+#define        POWER_EVENT_PTR(_id)            EVENT_PTR(_id, _p)
index ea2a86e8ff95bf731a399850cf2c8934b3fa8a19..2d0e1f5d83394a60544cc3a3fa003973c868596b 100644 (file)
@@ -24,7 +24,7 @@
  * user_time and system_time fields in the paca.
  */
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 #define ACCOUNT_CPU_USER_ENTRY(ra, rb)
 #define ACCOUNT_CPU_USER_EXIT(ra, rb)
 #define ACCOUNT_STOLEN_TIME
@@ -70,7 +70,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 
 #endif /* CONFIG_PPC_SPLPAR */
 
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 /*
  * Macros for storing registers into and loading registers from
index 5a4e437c238d814ad421c4c0c3eff12391cf316f..195ce2ac569157f47e80814f66dc897420a52d2a 100644 (file)
@@ -54,8 +54,8 @@ struct smp_ops_t {
 
 extern void smp_send_debugger_break(void);
 extern void start_secondary_resume(void);
-extern void __devinit smp_generic_give_timebase(void);
-extern void __devinit smp_generic_take_timebase(void);
+extern void smp_generic_give_timebase(void);
+extern void smp_generic_take_timebase(void);
 
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
index 29365e15ed7c1d3425a906459344fedd06ddb766..1d4864a40e3560fa4a61f2b7f5d22eb5607dcdc1 100644 (file)
@@ -56,7 +56,6 @@
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index df81cb72d1e08a805a94fe267b9dcc712a199459..68d0cc998b1baa5cee49b2a735f394354819492c 100644 (file)
@@ -139,7 +139,7 @@ extern void vio_unregister_driver(struct vio_driver *drv);
 extern int vio_cmo_entitlement_update(size_t);
 extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
 
-extern void __devinit vio_unregister_device(struct vio_dev *dev);
+extern void vio_unregister_device(struct vio_dev *dev);
 
 extern int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op);
 
index ed0e0254b47f2b3ae67940e15d151b58dddc7462..e3af3286a06801643a760fcbfa2afd116ad01053 100644 (file)
@@ -78,7 +78,7 @@ struct kvm_vcpu_arch_shared {
 
 #define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
 
-#include <uapi/asm/epapr_hcalls.h>
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
index 48fa8d3f2f9a56b5855b61feab313d4889cbed4f..e079fb39d5bcfc3952301b0f78b700b3d1988bbf 100644 (file)
@@ -85,12 +85,6 @@ typedef struct {
 
 #define SA_RESTORER    0x04000000U
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index d22e73e4618b7924879517f1f59cb99dcd63b43e..e514de57a125333a4ce174cb399070b6cc62e3b4 100644 (file)
@@ -439,6 +439,8 @@ ret_from_fork:
 ret_from_kernel_thread:
        REST_NVGPRS(r1)
        bl      schedule_tail
+       li      r3,0
+       stw     r3,0(r1)
        mtlr    r14
        mr      r3,r15
        PPC440EP_ERR42
index b310a0573625dec8a672c267ab6158f8e90b37a6..ac057013f9fdaa5c0c64323df0a68c271de49a2f 100644 (file)
@@ -94,7 +94,7 @@ system_call_common:
        addi    r9,r1,STACK_FRAME_OVERHEAD
        ld      r11,exception_marker@toc(r2)
        std     r11,-16(r9)             /* "regshere" marker */
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC_SPLPAR)
 BEGIN_FW_FTR_SECTION
        beq     33f
        /* if from user, see if there are any DTL entries to process */
@@ -110,7 +110,7 @@ BEGIN_FW_FTR_SECTION
        addi    r9,r1,STACK_FRAME_OVERHEAD
 33:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE && CONFIG_PPC_SPLPAR */
 
        /*
         * A syscall should always be called with interrupts enabled
@@ -664,6 +664,19 @@ resume_kernel:
        ld      r4,TI_FLAGS(r9)
        andi.   r0,r4,_TIF_NEED_RESCHED
        bne     1b
+
+       /*
+        * arch_local_irq_restore() from preempt_schedule_irq above may
+        * enable hard interrupt but we really should disable interrupts
+        * when we return from the interrupt, and so that we don't get
+        * interrupted after loading SRR0/1.
+        */
+#ifdef CONFIG_PPC_BOOK3E
+       wrteei  0
+#else
+       ld      r10,PACAKMSR(r13) /* Get kernel MSR without EE */
+       mtmsrd  r10,1             /* Update machine state */
+#endif /* CONFIG_PPC_BOOK3E */
 #endif /* CONFIG_PREEMPT */
 
        .globl  fast_exc_return_irq
index 12d329bcbb9825cbad17618460e22d4c2b0d5cdf..50e90b7e713993109022db1f7b4d4bf0905ded1f 100644 (file)
@@ -118,7 +118,7 @@ static void iowa_##name at                                  \
 #undef DEF_PCI_AC_RET
 #undef DEF_PCI_AC_NORET
 
-static const struct ppc_pci_io __devinitconst iowa_pci_io = {
+static const struct ppc_pci_io iowa_pci_io = {
 
 #define DEF_PCI_AC_RET(name, ret, at, al, space, aa)   .name = iowa_##name,
 #define DEF_PCI_AC_NORET(name, at, al, space, aa)      .name = iowa_##name,
@@ -146,7 +146,7 @@ static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
 }
 
 /* Enable IO workaround */
-static void __devinit io_workaround_init(void)
+static void io_workaround_init(void)
 {
        static int io_workaround_inited;
 
@@ -158,9 +158,8 @@ static void __devinit io_workaround_init(void)
 }
 
 /* Register new bus to support workaround */
-void __devinit iowa_register_bus(struct pci_controller *phb,
-                       struct ppc_pci_io *ops,
-                       int (*initfunc)(struct iowa_bus *, void *), void *data)
+void iowa_register_bus(struct pci_controller *phb, struct ppc_pci_io *ops,
+                      int (*initfunc)(struct iowa_bus *, void *), void *data)
 {
        struct iowa_bus *bus;
        struct device_node *np = phb->dn;
index d45ec58703cec58553d02de52baab00152fcad72..0f19970979608208b385aa0606c5461747673238 100644 (file)
@@ -41,8 +41,8 @@ EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
 #define ISA_SPACE_MASK 0x1
 #define ISA_SPACE_IO 0x1
 
-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
-                                               unsigned long phb_io_base_phys)
+static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
+                                     unsigned long phb_io_base_phys)
 {
        /* We should get some saner parsing here and remove these structs */
        struct pci_address {
@@ -170,8 +170,8 @@ void __init isa_bridge_find_early(struct pci_controller *hose)
  * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
  *                        a new ISA bridge
  */
-static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
-                                          struct device_node *devnode)
+static void isa_bridge_find_late(struct pci_dev *pdev,
+                                struct device_node *devnode)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
 
@@ -215,8 +215,8 @@ static void isa_bridge_remove(void)
 /**
  * isa_bridge_notify - Get notified of PCI devices addition/removal
  */
-static int __devinit isa_bridge_notify(struct notifier_block *nb,
-                                      unsigned long action, void *data)
+static int isa_bridge_notify(struct notifier_block *nb, unsigned long action,
+                            void *data)
 {
        struct device *dev = data;
        struct pci_dev *pdev = to_pci_dev(dev);
index c470a40b29f5d4937883cfcd8a40dd1c6bbdcfd1..a7bc7521c0645c6eb697308f039fb74eaad6b4af 100644 (file)
@@ -154,12 +154,12 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)
 static int kgdb_singlestep(struct pt_regs *regs)
 {
        struct thread_info *thread_info, *exception_thread_info;
-       struct thread_info *backup_current_thread_info = \
-               (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
+       struct thread_info *backup_current_thread_info;
 
        if (user_mode(regs))
                return 0;
 
+       backup_current_thread_info = (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
        /*
         * On Book E and perhaps other processors, singlestep is handled on
         * the critical exception stack.  This causes current_thread_info()
@@ -185,6 +185,7 @@ static int kgdb_singlestep(struct pt_regs *regs)
                /* Restore current_thread_info lastly. */
                memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
 
+       kfree(backup_current_thread_info);
        return 1;
 }
 
index 9db8ec07ec94ff4d953bb7277d1698304e39190c..07c12697d7083cb0645a3f4eb90cd0d94725d108 100644 (file)
@@ -37,7 +37,7 @@
  * lacking some bits needed here.
  */
 
-static int __devinit of_pci_phb_probe(struct platform_device *dev)
+static int of_pci_phb_probe(struct platform_device *dev)
 {
        struct pci_controller *phb;
 
index abc0d08569948f43bfad024df8a5b9fc85bdf94d..7c37379ea9b1334446eda1d318fb0b46a210ac3e 100644 (file)
@@ -673,9 +673,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
  *   - Some 32 bits platforms such as 4xx can have physical space larger than
  *     32 bits so we need to use 64 bits values for the parsing
  */
-void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev,
-                                           int primary)
+void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                 struct device_node *dev, int primary)
 {
        const u32 *ranges;
        int rlen;
@@ -848,7 +847,7 @@ int pci_proc_domain(struct pci_bus *bus)
 /* This header fixup will do the resource fixup for all devices as they are
  * probed, but not for bridge ranges
  */
-static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
+static void pcibios_fixup_resources(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        int i;
@@ -902,8 +901,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
  * things go more smoothly when it gets it right. It should covers cases such
  * as Apple "closed" bridge resources and bare-metal pSeries unassigned bridges
  */
-static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
-                                                          struct resource *res)
+static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
+                                                struct resource *res)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pci_dev *dev = bus->self;
@@ -967,7 +966,7 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
 }
 
 /* Fixup resources of a PCI<->PCI bridge */
-static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
+static void pcibios_fixup_bridge(struct pci_bus *bus)
 {
        struct resource *res;
        int i;
@@ -1007,7 +1006,7 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
        }
 }
 
-void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
+void pcibios_setup_bus_self(struct pci_bus *bus)
 {
        /* Fix up the bus resources for P2P bridges */
        if (bus->self != NULL)
@@ -1024,7 +1023,7 @@ void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
                ppc_md.pci_dma_bus_setup(bus);
 }
 
-void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
+void pcibios_setup_bus_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -1063,7 +1062,7 @@ void pcibios_set_master(struct pci_dev *dev)
        /* No special bus mastering setup handling */
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        /* When called from the generic PCI probe, read PCI<->PCI bridge
         * bases. This is -not- called when generating the PCI tree from
@@ -1080,7 +1079,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-void __devinit pci_fixup_cardbus(struct pci_bus *bus)
+void pci_fixup_cardbus(struct pci_bus *bus)
 {
        /* Now fixup devices on that bus */
        pcibios_setup_bus_devices(bus);
@@ -1264,7 +1263,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                pcibios_allocate_bus_resources(b);
 }
 
-static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
+static inline void alloc_resource(struct pci_dev *dev, int idx)
 {
        struct resource *pr, *r = &dev->resource[idx];
 
@@ -1500,7 +1499,8 @@ resource_size_t pcibios_io_space_offset(struct pci_controller *hose)
        return (unsigned long) hose->io_base_virt - _IO_BASE;
 }
 
-static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
+static void pcibios_setup_phb_resources(struct pci_controller *hose,
+                                       struct list_head *resources)
 {
        struct resource *res;
        int i;
@@ -1639,7 +1639,7 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
  * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
  * @hose: Pointer to the PCI host controller instance structure
  */
-void __devinit pcibios_scan_phb(struct pci_controller *hose)
+void pcibios_scan_phb(struct pci_controller *hose)
 {
        LIST_HEAD(resources);
        struct pci_bus *bus;
index 64f526a321f5f82e2fc094dd10e674668844296a..e37c2152acf4d96eaed43e70cb40a1ea06c85edb 100644 (file)
@@ -213,7 +213,7 @@ pci_create_OF_bus_map(void)
        }
 }
 
-void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
+void pcibios_setup_phb_io_space(struct pci_controller *hose)
 {
        unsigned long io_offset;
        struct resource *res = &hose->io_resource;
index 2cbe6768fddd7c545370738a10f4a55232da7578..51a133a78a09daaf2f8147134ac7136065bb7920 100644 (file)
@@ -122,7 +122,7 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
 
-static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
+static int pcibios_map_phb_io_space(struct pci_controller *hose)
 {
        struct vm_struct *area;
        unsigned long phys_page;
@@ -173,7 +173,7 @@ static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
        return 0;
 }
 
-int __devinit pcibios_map_io_space(struct pci_bus *bus)
+int pcibios_map_io_space(struct pci_bus *bus)
 {
        WARN_ON(bus == NULL);
 
@@ -193,7 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
+void pcibios_setup_phb_io_space(struct pci_controller *hose)
 {
        pcibios_map_phb_io_space(hose);
 }
index dd9e4a04bf795b0529da827738d2fe8484f46be6..e7af165f8b9d402add808fc5ce3760b9674d7c7a 100644 (file)
@@ -36,7 +36,7 @@
  * Traverse_func that inits the PCI fields of the device node.
  * NOTE: this *must* be done before read/write config to the device.
  */
-void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
+void *update_dn_pci_info(struct device_node *dn, void *data)
 {
        struct pci_controller *phb = data;
        const int *type =
@@ -129,7 +129,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
  * subsystem is set up, before kmalloc is valid) and during the 
  * dynamic lpar operation of adding a PHB to a running system.
  */
-void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
+void pci_devs_phb_init_dynamic(struct pci_controller *phb)
 {
        struct device_node *dn = phb->dn;
        struct pci_dn *pdn;
index 30378a19f65d03f43ab671c004e2027a793359ae..2a67e9baa59f80200f4a25b5a75471c04f04c776 100644 (file)
@@ -204,7 +204,7 @@ EXPORT_SYMBOL(of_create_pci_dev);
  * this routine in turn call of_scan_bus() recusively to scan for more child
  * devices.
  */
-void __devinit of_scan_pci_bridge(struct pci_dev *dev)
+void of_scan_pci_bridge(struct pci_dev *dev)
 {
        struct device_node *node = dev->dev.of_node;
        struct pci_bus *bus;
@@ -299,8 +299,8 @@ EXPORT_SYMBOL(of_scan_pci_bridge);
  * @bus: pci_bus structure for the PCI bus
  * @rescan_existing: Flag indicating bus has already been set up
  */
-static void __devinit __of_scan_bus(struct device_node *node,
-                                   struct pci_bus *bus, int rescan_existing)
+static void __of_scan_bus(struct device_node *node, struct pci_bus *bus,
+                         int rescan_existing)
 {
        struct device_node *child;
        const u32 *reg;
@@ -348,8 +348,7 @@ static void __devinit __of_scan_bus(struct device_node *node,
  * @node: device tree node for the PCI bus
  * @bus: pci_bus structure for the PCI bus
  */
-void __devinit of_scan_bus(struct device_node *node,
-                          struct pci_bus *bus)
+void of_scan_bus(struct device_node *node, struct pci_bus *bus)
 {
        __of_scan_bus(node, bus, 0);
 }
@@ -363,8 +362,7 @@ EXPORT_SYMBOL_GPL(of_scan_bus);
  * Same as of_scan_bus, but for a pci_bus structure that has already been
  * setup.
  */
-void __devinit of_rescan_bus(struct device_node *node,
-                            struct pci_bus *bus)
+void of_rescan_bus(struct device_node *node, struct pci_bus *bus)
 {
        __of_scan_bus(node, bus, 1);
 }
index 6de63e3250bb1af364e1b412ed511d1f50092f9c..71cb20d6ec61a42b58934b95b0dcdc13948ab29a 100644 (file)
@@ -209,7 +209,7 @@ void __init init_pci_config_tokens (void)
        ibm_write_pci_config = rtas_token("ibm,write-pci-config");
 }
 
-unsigned long __devinit get_phb_buid (struct device_node *phb)
+unsigned long get_phb_buid (struct device_node *phb)
 {
        struct resource r;
 
@@ -237,7 +237,7 @@ static int phb_set_bus_ranges(struct device_node *dev,
        return 0;
 }
 
-int __devinit rtas_setup_phb(struct pci_controller *phb)
+int rtas_setup_phb(struct pci_controller *phb)
 {
        struct device_node *dev = phb->dn;
 
index 640de836e466eebd697acad630ed1d04f35a2f82..e68fd1ae727a56c2edd9f79a21fcf9dd467b4f04 100644 (file)
@@ -36,13 +36,13 @@ static struct {
 
 static volatile int            running;
 
-static void __devinit enter_contest(u64 mark, long add)
+static void enter_contest(u64 mark, long add)
 {
        while (get_tb() < mark)
                tbsync->race_result = add;
 }
 
-void __devinit smp_generic_take_timebase(void)
+void smp_generic_take_timebase(void)
 {
        int cmd;
        u64 tb;
@@ -75,7 +75,7 @@ void __devinit smp_generic_take_timebase(void)
        local_irq_restore(flags);
 }
 
-static int __devinit start_contest(int cmd, long offset, int num)
+static int start_contest(int cmd, long offset, int num)
 {
        int i, score=0;
        u64 tb;
@@ -110,7 +110,7 @@ static int __devinit start_contest(int cmd, long offset, int num)
        return score;
 }
 
-void __devinit smp_generic_give_timebase(void)
+void smp_generic_give_timebase(void)
 {
        int i, score, score2, old, min=0, max=5000, offset=1000;
 
index e5b133ebd8a57820bb65ff0ad5243afb85fa8fdd..793401e65088763dd9d9e5deaead0f8888c8209b 100644 (file)
@@ -82,7 +82,7 @@ int smt_enabled_at_boot = 1;
 static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
 
 #ifdef CONFIG_PPC64
-int __devinit smp_generic_kick_cpu(int nr)
+int smp_generic_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
 
@@ -311,7 +311,7 @@ void smp_send_stop(void)
 
 struct thread_info *current_set[NR_CPUS];
 
-static void __devinit smp_store_cpu_info(int id)
+static void smp_store_cpu_info(int id)
 {
        per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
 #ifdef CONFIG_PPC_FSL_BOOK3E
@@ -355,7 +355,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                max_cpus = 1;
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
        BUG_ON(smp_processor_id() != boot_cpuid);
 #ifdef CONFIG_PPC64
@@ -610,7 +610,7 @@ static struct device_node *cpu_to_l2cache(int cpu)
 }
 
 /* Activate a secondary processor. */
-void __devinit start_secondary(void *unused)
+void start_secondary(void *unused)
 {
        unsigned int cpu = smp_processor_id();
        struct device_node *l2_cache;
index b3b14352b05ec3e460ca554c2475134d9185b978..f77fa22754bcde0d9024f5365e1fa8ac7885a3a6 100644 (file)
@@ -143,7 +143,7 @@ EXPORT_SYMBOL_GPL(ppc_proc_freq);
 unsigned long ppc_tb_freq;
 EXPORT_SYMBOL_GPL(ppc_tb_freq);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 /*
  * Factors for converting from cputime_t (timebase ticks) to
  * jiffies, microseconds, seconds, and clock_t (1/USER_HZ seconds).
@@ -347,6 +347,7 @@ void vtime_account_system(struct task_struct *tsk)
        if (stolen)
                account_steal_time(stolen);
 }
+EXPORT_SYMBOL_GPL(vtime_account_system);
 
 void vtime_account_idle(struct task_struct *tsk)
 {
@@ -377,7 +378,7 @@ void vtime_account_user(struct task_struct *tsk)
        account_user_time(tsk, utime, utimescaled);
 }
 
-#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
+#else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 #define calc_cputime_factors()
 #endif
 
@@ -494,10 +495,15 @@ void timer_interrupt(struct pt_regs * regs)
        set_dec(DECREMENTER_MAX);
 
        /* Some implementations of hotplug will get timer interrupts while
-        * offline, just ignore these
+        * offline, just ignore these and we also need to set
+        * decrementers_next_tb as MAX to make sure __check_irq_replay
+        * don't replay timer interrupt when return, otherwise we'll trap
+        * here infinitely :(
         */
-       if (!cpu_online(smp_processor_id()))
+       if (!cpu_online(smp_processor_id())) {
+               *next_tb = ~(u64)0;
                return;
+       }
 
        /* Conditionally hard-enable interrupts now that the DEC has been
         * bumped to its maximum value
@@ -663,7 +669,7 @@ int update_persistent_clock(struct timespec now)
        struct rtc_time tm;
 
        if (!ppc_md.set_rtc_time)
-               return 0;
+               return -ENODEV;
 
        to_tm(now.tv_sec + 1 + timezone_offset, &tm);
        tm.tm_year -= 1900;
@@ -770,13 +776,8 @@ void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
 
 void update_vsyscall_tz(void)
 {
-       /* Make userspace gettimeofday spin until we're done. */
-       ++vdso_data->tb_update_count;
-       smp_mb();
        vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
        vdso_data->tz_dsttime = sys_tz.tz_dsttime;
-       smp_mb();
-       ++vdso_data->tb_update_count;
 }
 
 static void __init clocksource_init(void)
index 201ba59738be93fefc95786336a7ebe57c0a1ed6..536016d792baf8a8a7208c4cd2f300c1672d49f2 100644 (file)
@@ -1289,7 +1289,7 @@ void vio_unregister_driver(struct vio_driver *viodrv)
 EXPORT_SYMBOL(vio_unregister_driver);
 
 /* vio_dev refcount hit 0 */
-static void __devinit vio_dev_release(struct device *dev)
+static void vio_dev_release(struct device *dev)
 {
        struct iommu_table *tbl = get_iommu_table_base(dev);
 
@@ -1545,7 +1545,7 @@ static struct device_attribute vio_dev_attrs[] = {
        __ATTR_NULL
 };
 
-void __devinit vio_unregister_device(struct vio_dev *viodev)
+void vio_unregister_device(struct vio_dev *viodev)
 {
        device_unregister(&viodev->dev);
 }
index 35f3cf0269b3100fff55aaee62f0c2ea5fc507fa..a353c485808c6ea203eac428106b5fdf41943b36 100644 (file)
@@ -79,7 +79,9 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu)
 static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
 {
        unsigned long srr1 = vcpu->arch.shregs.msr;
+#ifdef CONFIG_PPC_POWERNV
        struct opal_machine_check_event *opal_evt;
+#endif
        long handled = 1;
 
        if (srr1 & SRR1_MC_LDSTERR) {
@@ -117,6 +119,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
                handled = 0;
        }
 
+#ifdef CONFIG_PPC_POWERNV
        /*
         * See if OPAL has already handled the condition.
         * We assume that if the condition is recovered then OPAL
@@ -131,6 +134,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
 
        if (handled)
                opal_evt->in_use = 0;
+#endif
 
        return handled;
 }
index b0855e5d8905ee50e6422ca9edfc37aa952f6b21..9d9cddc5b346ff9518009539c08804b1cf0f9682 100644 (file)
@@ -39,6 +39,7 @@
 #define OP_31_XOP_TRAP      4
 #define OP_31_XOP_LWZX      23
 #define OP_31_XOP_TRAP_64   68
+#define OP_31_XOP_DCBF      86
 #define OP_31_XOP_LBZX      87
 #define OP_31_XOP_STWX      151
 #define OP_31_XOP_STBX      215
@@ -374,6 +375,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
                        break;
 
+               case OP_31_XOP_DCBF:
                case OP_31_XOP_DCBI:
                        /* Do nothing. The guest is performing dcbi because
                         * hardware DMA is not snooped by the dcache, but
index 56585086413a4f9876c70eb6b6ea9f3cf1c1ef69..7443481a315c4922063a5f8801c62ee9bfb7691f 100644 (file)
@@ -115,11 +115,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        sldi    r29,r5,SID_SHIFT - VPN_SHIFT
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
-
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-12,48          /* (ea >> 12) & 0xffff */
-       xor     r28,r5,r0
+       /*
+        * Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
+        */
+       rldicl  r0,r3,64-12,48
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
@@ -130,11 +132,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        /*
         * calculate hash value for primary slot and
         * store it in r28 for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 =  (va >> 12) & ((1ul << (40 - 12)) -1) */
+       rldicl  r0,r3,64-12,36
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -407,11 +410,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
         */
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
-
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-12,48          /* (ea >> 12) & 0xffff */
-       xor     r28,r5,r0
+       /*
+        * Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
+        */
+       rldicl  r0,r3,64-12,48
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
@@ -426,11 +431,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        /*
         * Calculate hash value for primary slot and
         * store it in r28  for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
+       rldicl  r0,r3,64-12,36
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -752,25 +758,27 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
 
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-16,52          /* (ea >> 16) & 0xfff */
-       xor     r28,r5,r0
+       /* Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 16) & ((1ul << (28 - 16)) -1)
+        */
+       rldicl  r0,r3,64-16,52
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
        sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
        or      r29,r28,r29
-
        /*
         * calculate hash value for primary slot and
         * store it in r28 for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-16,40          /* (ea >> 16) & 0xffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 = (va >> 16) & ((1ul << (40 - 16)) -1) */
+       rldicl  r0,r3,64-16,40
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
index ae758b3ff72cef57d702ac74f416116b752f44ec..0d82ef50dc3faf9269042bb09001320fbdacdaad 100644 (file)
@@ -186,8 +186,6 @@ void tlb_flush(struct mmu_gather *tlb)
  * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
  * and is implemented for small size rather than speed.
  */
-#ifdef CONFIG_HOTPLUG
-
 void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
                              unsigned long end)
 {
@@ -221,5 +219,3 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
        arch_leave_lazy_mmu_mode();
        local_irq_restore(flags);
 }
-
-#endif /* CONFIG_HOTPLUG */
index 315f9495e9b2b5aa42a6c9aaba5a6307ac03ddde..f444b94935f560f6a7abf1a1de46d88cd32e71d5 100644 (file)
@@ -52,7 +52,7 @@ static int power7_marked_instr_event(u64 mmcr1)
        for (pmc = 0; pmc < 4; pmc++) {
                psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK
                                << (OPROFILE_MAX_PMC_NUM - pmc)
-                               * OPROFILE_MAX_PMC_NUM);
+                               * OPROFILE_PMSEL_FIELD_WIDTH);
                psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc)
                                 * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL;
                unit = mmcr1 & (OPROFILE_PM_UNIT_MSK
index aa2465e21f1a87b989e49eae2027fee72dc4948f..fa476d50791f28f690d77a236defafbe17896526 100644 (file)
@@ -1305,6 +1305,16 @@ static int power_pmu_event_idx(struct perf_event *event)
        return event->hw.idx;
 }
 
+ssize_t power_events_sysfs_show(struct device *dev,
+                               struct device_attribute *attr, char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
+       return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
 struct pmu power_pmu = {
        .pmu_enable     = power_pmu_enable,
        .pmu_disable    = power_pmu_disable,
@@ -1537,6 +1547,8 @@ int __cpuinit register_power_pmu(struct power_pmu *pmu)
        pr_info("%s performance monitor hardware support registered\n",
                pmu->name);
 
+       power_pmu.attr_groups = ppmu->attr_groups;
+
 #ifdef MSR_HV
        /*
         * Use FCHV to ignore kernel events if MSR.HV is set.
index 2ee01e38d5e256b9a92f0ee678e08a19e768f572..b554879bd31e4c48cc6769092695c7f32a899af4 100644 (file)
 #define MMCR1_PMCSEL_SH(n)     (MMCR1_PMC1SEL_SH - (n) * 8)
 #define MMCR1_PMCSEL_MSK       0xff
 
+/*
+ * Power7 event codes.
+ */
+#define        PME_PM_CYC                      0x1e
+#define        PME_PM_GCT_NOSLOT_CYC           0x100f8
+#define        PME_PM_CMPLU_STALL              0x4000a
+#define        PME_PM_INST_CMPL                0x2
+#define        PME_PM_LD_REF_L1                0xc880
+#define        PME_PM_LD_MISS_L1               0x400f0
+#define        PME_PM_BRU_FIN                  0x10068
+#define        PME_PM_BRU_MPRED                0x400f6
+
 /*
  * Layout of constraint bits:
  * 6666555555555544444444443333333333222222222211111111110000000000
@@ -307,14 +319,14 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 }
 
 static int power7_generic_events[] = {
-       [PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
-       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
-       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
-       [PERF_COUNT_HW_INSTRUCTIONS] = 2,
-       [PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,      /* LD_REF_L1_LSU*/
-       [PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,         /* LD_MISS_L1   */
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x10068,  /* BRU_FIN      */
-       [PERF_COUNT_HW_BRANCH_MISSES] = 0x400f6,        /* BR_MPRED     */
+       [PERF_COUNT_HW_CPU_CYCLES] =                    PME_PM_CYC,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =       PME_PM_GCT_NOSLOT_CYC,
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =        PME_PM_CMPLU_STALL,
+       [PERF_COUNT_HW_INSTRUCTIONS] =                  PME_PM_INST_CMPL,
+       [PERF_COUNT_HW_CACHE_REFERENCES] =              PME_PM_LD_REF_L1,
+       [PERF_COUNT_HW_CACHE_MISSES] =                  PME_PM_LD_MISS_L1,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =           PME_PM_BRU_FIN,
+       [PERF_COUNT_HW_BRANCH_MISSES] =                 PME_PM_BRU_MPRED,
 };
 
 #define C(x)   PERF_COUNT_HW_CACHE_##x
@@ -362,6 +374,57 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        },
 };
 
+
+GENERIC_EVENT_ATTR(cpu-cycles,                 CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-frontend,    GCT_NOSLOT_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-backend,     CMPLU_STALL);
+GENERIC_EVENT_ATTR(instructions,               INST_CMPL);
+GENERIC_EVENT_ATTR(cache-references,           LD_REF_L1);
+GENERIC_EVENT_ATTR(cache-misses,               LD_MISS_L1);
+GENERIC_EVENT_ATTR(branch-instructions,                BRU_FIN);
+GENERIC_EVENT_ATTR(branch-misses,              BRU_MPRED);
+
+POWER_EVENT_ATTR(CYC,                          CYC);
+POWER_EVENT_ATTR(GCT_NOSLOT_CYC,               GCT_NOSLOT_CYC);
+POWER_EVENT_ATTR(CMPLU_STALL,                  CMPLU_STALL);
+POWER_EVENT_ATTR(INST_CMPL,                    INST_CMPL);
+POWER_EVENT_ATTR(LD_REF_L1,                    LD_REF_L1);
+POWER_EVENT_ATTR(LD_MISS_L1,                   LD_MISS_L1);
+POWER_EVENT_ATTR(BRU_FIN,                      BRU_FIN)
+POWER_EVENT_ATTR(BRU_MPRED,                    BRU_MPRED);
+
+static struct attribute *power7_events_attr[] = {
+       GENERIC_EVENT_PTR(CYC),
+       GENERIC_EVENT_PTR(GCT_NOSLOT_CYC),
+       GENERIC_EVENT_PTR(CMPLU_STALL),
+       GENERIC_EVENT_PTR(INST_CMPL),
+       GENERIC_EVENT_PTR(LD_REF_L1),
+       GENERIC_EVENT_PTR(LD_MISS_L1),
+       GENERIC_EVENT_PTR(BRU_FIN),
+       GENERIC_EVENT_PTR(BRU_MPRED),
+
+       POWER_EVENT_PTR(CYC),
+       POWER_EVENT_PTR(GCT_NOSLOT_CYC),
+       POWER_EVENT_PTR(CMPLU_STALL),
+       POWER_EVENT_PTR(INST_CMPL),
+       POWER_EVENT_PTR(LD_REF_L1),
+       POWER_EVENT_PTR(LD_MISS_L1),
+       POWER_EVENT_PTR(BRU_FIN),
+       POWER_EVENT_PTR(BRU_MPRED),
+       NULL
+};
+
+
+static struct attribute_group power7_pmu_events_group = {
+       .name = "events",
+       .attrs = power7_events_attr,
+};
+
+static const struct attribute_group *power7_pmu_attr_groups[] = {
+       &power7_pmu_events_group,
+       NULL,
+};
+
 static struct power_pmu power7_pmu = {
        .name                   = "POWER7",
        .n_counter              = 6,
@@ -373,6 +436,7 @@ static struct power_pmu power7_pmu = {
        .get_alternatives       = power7_get_alternatives,
        .disable_pmc            = power7_disable_pmc,
        .flags                  = PPMU_ALT_SIPR,
+       .attr_groups            = power7_pmu_attr_groups,
        .n_generic              = ARRAY_SIZE(power7_generic_events),
        .generic_events         = power7_generic_events,
        .cache_events           = &power7_cache_events,
index 969dddcf33203aab139798f4b5f3dcdf99804f67..8f3920e5a046c4df771ecd30371154a84e813d82 100644 (file)
@@ -57,7 +57,8 @@ static const char * const board[] __initconst = {
        "amcc,makalu",
        "apm,klondike",
        "est,hotfoot",
-       "plathome,obs600"
+       "plathome,obs600",
+       NULL
 };
 
 static int __init ppc40x_probe(void)
index 6bd89a0e0dead4dcf112baca8aca5a0380f84a8c..ecd3890c40d72f11147a642fdb39c3389a6a7a38 100644 (file)
@@ -46,7 +46,7 @@ static __initdata struct of_device_id ppc47x_of_bus[] = {
 
 /* The EEPROM is missing and the default values are bogus.  This forces USB in
  * to EHCI mode */
-static void __devinit quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
+static void quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
 {
        if (of_machine_is_compatible("ibm,currituck")) {
                pci_write_config_dword(dev, 0xe0, 0x0114231f);
index ba4a6e388a461fdb5a32ce6a78262680453e83c6..1fdb8748638d6322a4eed241f4157f5bb36bcf01 100644 (file)
@@ -5,7 +5,7 @@
 /**
  * ml510_ail_quirk
  */
-static void __devinit ml510_ali_quirk(struct pci_dev *dev)
+static void ml510_ali_quirk(struct pci_dev *dev)
 {
        /* Enable the IDE controller */
        pci_write_config_byte(dev, 0x58, 0x4c);
index a51cb07bd663debc0b9f9fb17211e0a57cbed1f1..692998244d2c316d54880b262653fe21c66c9e35 100644 (file)
@@ -669,7 +669,7 @@ static struct miscdevice mpc52xx_wdt_miscdev = {
        .fops           = &mpc52xx_wdt_fops,
 };
 
-static int __devinit mpc52xx_gpt_wdt_init(void)
+static int mpc52xx_gpt_wdt_init(void)
 {
        int err;
 
@@ -704,7 +704,7 @@ static int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt,
 
 #else
 
-static int __devinit mpc52xx_gpt_wdt_init(void)
+static int mpc52xx_gpt_wdt_init(void)
 {
        return 0;
 }
@@ -720,7 +720,7 @@ static inline int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt,
 /* ---------------------------------------------------------------------
  * of_platform bus binding code
  */
-static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev)
+static int mpc52xx_gpt_probe(struct platform_device *ofdev)
 {
        struct mpc52xx_gpt_priv *gpt;
 
index 16150fa430f931713231497b15421ab50cafd636..f9f4537f546dfc7380b73ed002b17cf924339e7c 100644 (file)
@@ -470,7 +470,7 @@ void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req)
 }
 EXPORT_SYMBOL(mpc52xx_lpbfifo_abort);
 
-static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
+static int mpc52xx_lpbfifo_probe(struct platform_device *op)
 {
        struct resource res;
        int rc = -ENOMEM;
@@ -540,7 +540,7 @@ static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
 }
 
 
-static int __devexit mpc52xx_lpbfifo_remove(struct platform_device *op)
+static int mpc52xx_lpbfifo_remove(struct platform_device *op)
 {
        if (lpbfifo.dev != &op->dev)
                return 0;
@@ -564,7 +564,7 @@ static int __devexit mpc52xx_lpbfifo_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = {
+static struct of_device_id mpc52xx_lpbfifo_match[] = {
        { .compatible = "fsl,mpc5200-lpbfifo", },
        {},
 };
@@ -576,6 +576,6 @@ static struct platform_driver mpc52xx_lpbfifo_driver = {
                .of_match_table = mpc52xx_lpbfifo_match,
        },
        .probe = mpc52xx_lpbfifo_probe,
-       .remove = __devexit_p(mpc52xx_lpbfifo_remove),
+       .remove = mpc52xx_lpbfifo_remove,
 };
 module_platform_driver(mpc52xx_lpbfifo_driver);
index 10ff526cd0467a6ecee78acc30e1d1350922c2e5..79799b29ffe21912dfa437885d2affaf8e916912 100644 (file)
@@ -111,7 +111,7 @@ static struct mdiobb_ctrl ep8248e_mdio_ctrl = {
        .ops = &ep8248e_mdio_ops,
 };
 
-static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev)
+static int ep8248e_mdio_probe(struct platform_device *ofdev)
 {
        struct mii_bus *bus;
        struct resource res;
index ef6537b8ed330185393aa92f54ffc2151d6c255a..624cb51d19c92c58b9821b2e511a6dc8089ff93e 100644 (file)
@@ -145,8 +145,7 @@ static int mcu_gpiochip_remove(struct mcu *mcu)
        return gpiochip_remove(&mcu->gc);
 }
 
-static int __devinit mcu_probe(struct i2c_client *client,
-                              const struct i2c_device_id *id)
+static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct mcu *mcu;
        int ret;
@@ -188,7 +187,7 @@ err:
        return ret;
 }
 
-static int __devexit mcu_remove(struct i2c_client *client)
+static int mcu_remove(struct i2c_client *client)
 {
        struct mcu *mcu = i2c_get_clientdata(client);
        int ret;
@@ -216,7 +215,7 @@ static const struct i2c_device_id mcu_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mcu_ids);
 
-static struct of_device_id mcu_of_match_table[] __devinitdata = {
+static struct of_device_id mcu_of_match_table[] = {
        { .compatible = "fsl,mcu-mpc8349emitx", },
        { },
 };
@@ -228,7 +227,7 @@ static struct i2c_driver mcu_driver = {
                .of_match_table = mcu_of_match_table,
        },
        .probe = mcu_probe,
-       .remove = __devexit_p(mcu_remove),
+       .remove = mcu_remove,
        .id_table = mcu_ids,
 };
 
index ed69c9250717d19721924a50e7a6b3934bf5a1a5..6f355d8c92f62ebb426cd051632c042755120d7c 100644 (file)
@@ -64,7 +64,7 @@ void __init corenet_ds_setup_arch(void)
        pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
 }
 
-static const struct of_device_id of_device_ids[] __devinitconst = {
+static const struct of_device_id of_device_ids[] = {
        {
                .compatible     = "simple-bus"
        },
index c474505ad0d06c39ec340d8373c507eba509b1ac..7a31a0e1df2987b0bf33bd33c90b971676c57f5e 100644 (file)
@@ -154,7 +154,7 @@ static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)
        }
 }
 
-static void __devinit skip_fake_bridge(struct pci_dev *dev)
+static void skip_fake_bridge(struct pci_dev *dev)
 {
        /* Make it an error to skip the fake bridge
         * in pci_setup_device() in probe.c */
index b4e58cdc09a53cc3cd9e998a2a1efe0443457eb2..ec0b7272fae25bcc5af5570fd75e5a567ff7d3b9 100644 (file)
@@ -85,7 +85,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev)
+static void tqm85xx_ti1520_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index bf5338754c5a301d83d8dbd9fc652fa482912b9f..c23f3443880ac96d138c1483120802559a5ee75b 100644 (file)
@@ -159,7 +159,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
                gef_ppc9a_get_vme_is_syscon() ? "yes" : "no");
 }
 
-static void __devinit gef_ppc9a_nec_fixup(struct pci_dev *pdev)
+static void gef_ppc9a_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index 0b7851330a07aebb9f9f1f5e83252347d4901c57..8a6ac20686ea2b0218c89059521788b7377a0ad9 100644 (file)
@@ -146,7 +146,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m)
 
 }
 
-static void __devinit gef_sbc310_nec_fixup(struct pci_dev *pdev)
+static void gef_sbc310_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index b9eb174897b16c621c3cee6fa8dcabd911f12744..06c72636f2992d5ac3a632cc28ab05ccb8b6048f 100644 (file)
@@ -136,7 +136,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 }
 
-static void __devinit gef_sbc610_nec_fixup(struct pci_dev *pdev)
+static void gef_sbc610_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index 4ab08767118534c780b1136adf909024c7893414..6ae25fb620158fee8386d4f7ef5352f7170ac58b 100644 (file)
@@ -117,7 +117,7 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
 
-static int __devinit cell_setup_phb(struct pci_controller *phb)
+static int cell_setup_phb(struct pci_controller *phb)
 {
        const char *model;
        struct device_node *np;
index 49a65e2dfc71ab2392692a810da0b984c067f37e..d35dbbc8ec7919fe12287ad075b12c40312b4ffc 100644 (file)
@@ -67,7 +67,7 @@ static cpumask_t of_spin_map;
  *     0       - failure
  *     1       - success
  */
-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+static inline int smp_startup_cpu(unsigned int lcpu)
 {
        int status;
        unsigned long start_here = __pa((u32)*((unsigned long *)
@@ -108,7 +108,7 @@ static int __init smp_iic_probe(void)
        return cpumask_weight(cpu_possible_mask);
 }
 
-static void __devinit smp_cell_setup_cpu(int cpu)
+static void smp_cell_setup_cpu(int cpu)
 {
        if (cpu != boot_cpuid)
                iic_setup_cpu();
@@ -119,7 +119,7 @@ static void __devinit smp_cell_setup_cpu(int cpu)
        mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
 }
 
-static int __devinit smp_cell_kick_cpu(int nr)
+static int smp_cell_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
 
index 25db92a8e1cf919db8a919232805fb71ad480b7f..49318385d4fac71e6122588da95c895a18d9198d 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
index 5b7d8ffbf8907933b21f9be8e4e4333c81a02e9d..baee994fe810cd494d2ab51750d880c611a318ff 100644 (file)
@@ -66,7 +66,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
        struct dentry *dentry;
        int ret;
 
-       dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
+       dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
        ret = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
                ret = spufs_create(&path, dentry, flags, mode, neighbor);
index 83285c5a2049eb69ed7c35d8f14c4b470d3527da..1b87e198faa78c059fb853532564e55cf985a737 100644 (file)
@@ -323,7 +323,7 @@ chrp_find_bridges(void)
  * ATA controller to be set to fully native mode or bad things
  * will happen.
  */
-static void __devinit chrp_pci_fixup_winbond_ata(struct pci_dev *sl82c105)
+static void chrp_pci_fixup_winbond_ata(struct pci_dev *sl82c105)
 {
        u8 progif;
 
index feab30bbae233b27ff9ed9f2a84a008af770b0f4..dead91b177b9df702e236d9abba5a379a5aa793d 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 
-static int __devinit smp_chrp_kick_cpu(int nr)
+static int smp_chrp_kick_cpu(int nr)
 {
        *(unsigned long *)KERNELBASE = nr;
        asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
@@ -38,7 +38,7 @@ static int __devinit smp_chrp_kick_cpu(int nr)
        return 0;
 }
 
-static void __devinit smp_chrp_setup_cpu(int cpu_nr)
+static void smp_chrp_setup_cpu(int cpu_nr)
 {
        mpic_setup_this_cpu();
 }
index 64fde058e54570d812de8501631e4ebb03863584..92ac9b52b32dfcfb6a469db4f90e07529042aa25 100644 (file)
@@ -59,7 +59,7 @@ static inline bool is_quirk_valid(void)
 }
 
 /* Bridge */
-static void __devinit early_uli5249(struct pci_dev *dev)
+static void early_uli5249(struct pci_dev *dev)
 {
        unsigned char temp;
 
@@ -82,7 +82,7 @@ static void __devinit early_uli5249(struct pci_dev *dev)
 }
 
 
-static void __devinit quirk_uli1575(struct pci_dev *dev)
+static void quirk_uli1575(struct pci_dev *dev)
 {
        int i;
 
@@ -139,7 +139,7 @@ static void __devinit quirk_uli1575(struct pci_dev *dev)
        pci_write_config_byte(dev, 0x75, ULI_8259_IRQ15);
 }
 
-static void __devinit quirk_final_uli1575(struct pci_dev *dev)
+static void quirk_final_uli1575(struct pci_dev *dev)
 {
        /* Set i8259 interrupt trigger
         * IRQ 3:  Level
@@ -175,7 +175,7 @@ static void __devinit quirk_final_uli1575(struct pci_dev *dev)
 }
 
 /* SATA */
-static void __devinit quirk_uli5288(struct pci_dev *dev)
+static void quirk_uli5288(struct pci_dev *dev)
 {
        unsigned char c;
        unsigned int d;
@@ -200,7 +200,7 @@ static void __devinit quirk_uli5288(struct pci_dev *dev)
 }
 
 /* PATA */
-static void __devinit quirk_uli5229(struct pci_dev *dev)
+static void quirk_uli5229(struct pci_dev *dev)
 {
        unsigned short temp;
 
@@ -216,7 +216,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
 }
 
 /* We have to do a dummy read on the P2P for the RTC to work, WTF */
-static void __devinit quirk_final_uli5249(struct pci_dev *dev)
+static void quirk_final_uli5249(struct pci_dev *dev)
 {
        int i;
        u8 *dummy;
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
 
-static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
+static void hpcd_quirk_uli1575(struct pci_dev *dev)
 {
        u32 temp32;
 
@@ -269,7 +269,7 @@ static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
        pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
 }
 
-static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
+static void hpcd_quirk_uli5288(struct pci_dev *dev)
 {
        unsigned char c;
 
@@ -295,7 +295,7 @@ static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
  * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
  * as the interrupt for IDE device.
  */
-static void __devinit hpcd_quirk_uli5229(struct pci_dev *dev)
+static void hpcd_quirk_uli5229(struct pci_dev *dev)
 {
        unsigned char c;
 
@@ -317,7 +317,7 @@ static void __devinit hpcd_quirk_uli5229(struct pci_dev *dev)
  * bug by re-assigning a correct irq to 5288.
  *
  */
-static void __devinit hpcd_final_uli5288(struct pci_dev *dev)
+static void hpcd_final_uli5288(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct device_node *hosenode = hose ? hose->dn : NULL;
index 465ee8f5c0868070d9ea8364a340a5aa1a5b6bda..f7136aae8bbf9d5ca51c33a2fd46e61a73aeaea4 100644 (file)
@@ -543,7 +543,7 @@ static int __init maple_add_bridge(struct device_node *dev)
 }
 
 
-void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
+void maple_pci_irq_fixup(struct pci_dev *dev)
 {
        DBG(" -> maple_pci_irq_fixup\n");
 
@@ -648,7 +648,7 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
        return irq;
 }
 
-static void __devinit quirk_ipr_msi(struct pci_dev *dev)
+static void quirk_ipr_msi(struct pci_dev *dev)
 {
        /* Something prevents MSIs from the IPR from working on Bimini,
         * and the driver has no smarts to recover. So disable MSI
index 95d00173029f52c498902a586a24917f09e99d4b..890f30e70f98fc52a39f063172cfbadc5e8713b4 100644 (file)
@@ -236,6 +236,13 @@ out:
 
 static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
+       /*
+        * We don't support CPU hotplug. Don't unmap after the system
+        * has already made it to a running state.
+        */
+       if (system_state != SYSTEM_BOOTING)
+               return 0;
+
        if (sdcasr_mapbase)
                iounmap(sdcasr_mapbase);
        if (sdcpwr_mapbase)
index 9886296e08dac7d32ad0bdf89f8911a3cf134720..0237ab782fb8ba45c3791e8df598f4b9147f1c3e 100644 (file)
@@ -216,7 +216,7 @@ static int gpio_mdio_reset(struct mii_bus *bus)
 }
 
 
-static int __devinit gpio_mdio_probe(struct platform_device *ofdev)
+static int gpio_mdio_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
        struct device_node *np = ofdev->dev.of_node;
index b1e524f7489dadb41028777d97bbd9b2854025c4..ea65bf0eb89755b7239b1ba5968164ed4b8a4c76 100644 (file)
@@ -3,8 +3,8 @@
 
 extern unsigned long pas_get_boot_time(void);
 extern void pas_pci_init(void);
-extern void __devinit pas_pci_irq_fixup(struct pci_dev *dev);
-extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev);
+extern void pas_pci_irq_fixup(struct pci_dev *dev);
+extern void pas_pci_dma_dev_setup(struct pci_dev *dev);
 
 extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset);
 
index 2ed9212d7d59a56aec67df3e631288c0864b5a78..8c54de6d8ec426e11e7a84ee7193159176f0b482 100644 (file)
@@ -76,7 +76,7 @@ static void pas_restart(char *cmd)
 static arch_spinlock_t timebase_lock;
 static unsigned long timebase;
 
-static void __devinit pas_give_timebase(void)
+static void pas_give_timebase(void)
 {
        unsigned long flags;
 
@@ -94,7 +94,7 @@ static void __devinit pas_give_timebase(void)
        local_irq_restore(flags);
 }
 
-static void __devinit pas_take_timebase(void)
+static void pas_take_timebase(void)
 {
        while (!timebase)
                smp_rmb();
index 43bbe1bda9391ad5801112bd4135b6dd813e69c1..2b8af75abc232eb7055abe4ba92bf26f30f0bbba 100644 (file)
@@ -561,7 +561,7 @@ static struct pci_ops u4_pcie_pci_ops =
        .write = u4_pcie_write_config,
 };
 
-static void __devinit pmac_pci_fixup_u4_of_node(struct pci_dev *dev)
+static void pmac_pci_fixup_u4_of_node(struct pci_dev *dev)
 {
        /* Apple's device-tree "hides" the root complex virtual P2P bridge
         * on U4. However, Linux sees it, causing the PCI <-> OF matching
@@ -988,7 +988,7 @@ static int __init pmac_add_bridge(struct device_node *dev)
        return 0;
 }
 
-void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
+void pmac_pci_irq_fixup(struct pci_dev *dev)
 {
 #ifdef CONFIG_PPC32
        /* Fixup interrupt for the modem/ethernet combo controller.
@@ -1138,7 +1138,7 @@ int pmac_pci_enable_device_hook(struct pci_dev *dev)
        return 0;
 }
 
-void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
+void pmac_pci_fixup_ohci(struct pci_dev *dev)
 {
        struct device_node *node = pci_device_to_OF_node(dev);
 
index b4ddaa3fbb298eccc37044f61222d38a688c9f8c..bdb738a69e41890b5bec785ee44257f26cb6f987 100644 (file)
@@ -484,7 +484,7 @@ static void smp_core99_give_timebase(void)
 }
 
 
-static void __devinit smp_core99_take_timebase(void)
+static void smp_core99_take_timebase(void)
 {
        unsigned long flags;
 
@@ -669,7 +669,7 @@ static void smp_core99_gpio_tb_freeze(int freeze)
 volatile static long int core99_l2_cache;
 volatile static long int core99_l3_cache;
 
-static void __devinit core99_init_caches(int cpu)
+static void core99_init_caches(int cpu)
 {
 #ifndef CONFIG_PPC64
        if (!cpu_has_feature(CPU_FTR_L2CR))
@@ -801,7 +801,7 @@ static int __init smp_core99_probe(void)
        return ncpus;
 }
 
-static int __devinit smp_core99_kick_cpu(int nr)
+static int smp_core99_kick_cpu(int nr)
 {
        unsigned int save_vector;
        unsigned long target, flags;
@@ -844,7 +844,7 @@ static int __devinit smp_core99_kick_cpu(int nr)
        return 0;
 }
 
-static void __devinit smp_core99_setup_cpu(int cpu_nr)
+static void smp_core99_setup_cpu(int cpu_nr)
 {
        /* Setup L2/L3 */
        if (cpu_nr != 0)
index 53d052e95cfcb043b339d7d110dc730cae1df9b7..8e90e8906df305b422b7f47b02772c9eb6c552d0 100644 (file)
@@ -76,7 +76,7 @@ static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
        return PCI_DN(np);
 }
 
-static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
+static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
        unsigned long pe;
 
@@ -91,7 +91,7 @@ static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
        return pe;
 }
 
-static void __devinit pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
+static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
 {
        WARN_ON(phb->ioda.pe_array[pe].pdev);
 
@@ -103,7 +103,7 @@ static void __devinit pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
  * but in the meantime, we need to protect them to avoid warnings
  */
 #ifdef CONFIG_PCI_MSI
-static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
+static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
@@ -117,8 +117,7 @@ static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
 }
 #endif /* CONFIG_PCI_MSI */
 
-static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
-                                          struct pnv_ioda_pe *pe)
+static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
 {
        struct pci_dev *parent;
        uint8_t bcomp, dcomp, fcomp;
@@ -207,8 +206,8 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
        return 0;
 }
 
-static void __devinit pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
-                                                struct pnv_ioda_pe *pe)
+static void pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
+                                      struct pnv_ioda_pe *pe)
 {
        struct pnv_ioda_pe *lpe;
 
@@ -246,7 +245,7 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
 }
 
 #if 0
-static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
+static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
@@ -343,7 +342,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
  * subordinate PCI devices and buses. The second type of PE is normally
  * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports.
  */
-static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
+static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pnv_phb *phb = hose->private_data;
@@ -399,7 +398,7 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
        pnv_ioda_link_pe_by_weight(phb, pe);
 }
 
-static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus)
+static void pnv_ioda_setup_PEs(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -423,7 +422,7 @@ static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus)
  * port to PE# here. The game rule here is expected to be changed
  * as soon as we can detected PLX bridge correctly.
  */
-static void __devinit pnv_pci_ioda_setup_PEs(void)
+static void pnv_pci_ioda_setup_PEs(void)
 {
        struct pci_controller *hose, *tmp;
 
@@ -432,14 +431,12 @@ static void __devinit pnv_pci_ioda_setup_PEs(void)
        }
 }
 
-static void __devinit pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb,
-                                                struct pci_dev *dev)
+static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *dev)
 {
        /* We delay DMA setup after we have assigned all PE# */
 }
 
-static void __devinit pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
-                                            struct pci_bus *bus)
+static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -450,10 +447,9 @@ static void __devinit pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
        }
 }
 
-static void __devinit pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
-                                               struct pnv_ioda_pe *pe,
-                                               unsigned int base,
-                                               unsigned int segs)
+static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
+                                     struct pnv_ioda_pe *pe, unsigned int base,
+                                     unsigned int segs)
 {
 
        struct page *tce_mem = NULL;
@@ -541,7 +537,7 @@ static void __devinit pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
                __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs));
 }
 
-static void __devinit pnv_ioda_setup_dma(struct pnv_phb *phb)
+static void pnv_ioda_setup_dma(struct pnv_phb *phb)
 {
        struct pci_controller *hose = phb->hose;
        unsigned int residual, remaining, segs, tw, base;
@@ -684,8 +680,8 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { }
  * to bottom style. So the the I/O or MMIO segment assigned to
  * parent PE could be overrided by its child PEs if necessary.
  */
-static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose,
-                               struct pnv_ioda_pe *pe)
+static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
+                                 struct pnv_ioda_pe *pe)
 {
        struct pnv_phb *phb = hose->private_data;
        struct pci_bus_region region;
@@ -753,7 +749,7 @@ static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose,
        }
 }
 
-static void __devinit pnv_pci_ioda_setup_seg(void)
+static void pnv_pci_ioda_setup_seg(void)
 {
        struct pci_controller *tmp, *hose;
        struct pnv_phb *phb;
@@ -767,7 +763,7 @@ static void __devinit pnv_pci_ioda_setup_seg(void)
        }
 }
 
-static void __devinit pnv_pci_ioda_setup_DMA(void)
+static void pnv_pci_ioda_setup_DMA(void)
 {
        struct pci_controller *hose, *tmp;
        struct pnv_phb *phb;
@@ -781,7 +777,7 @@ static void __devinit pnv_pci_ioda_setup_DMA(void)
        }
 }
 
-static void __devinit pnv_pci_ioda_fixup(void)
+static void pnv_pci_ioda_fixup(void)
 {
        pnv_pci_ioda_setup_PEs();
        pnv_pci_ioda_setup_seg();
@@ -829,7 +825,7 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
 /* Prevent enabling devices for which we couldn't properly
  * assign a PE
  */
-static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
+static int pnv_pci_enable_device_hook(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
index 6b4bef4e9d821aa2519cf2a4eecdb7ada4d5f57a..7db8771a40f5e53ab8ea017431ed904f09cb46e2 100644 (file)
@@ -84,8 +84,8 @@ static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
 static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
 #endif /* CONFIG_PCI_MSI */
 
-static void __devinit pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
-                                                  struct pci_dev *pdev)
+static void pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
+                                        struct pci_dev *pdev)
 {
        if (phb->p5ioc2.iommu_table.it_map == NULL)
                iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node);
index c01688a1a741f40ff423fe40761d2fd783a46799..b8b8e0bd9897fb92b08961e79e78584c94599ce2 100644 (file)
@@ -464,8 +464,7 @@ void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
        tbl->it_type = TCE_PCI;
 }
 
-static struct iommu_table * __devinit
-pnv_pci_setup_bml_iommu(struct pci_controller *hose)
+static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose)
 {
        struct iommu_table *tbl;
        const __be64 *basep, *swinvp;
@@ -496,8 +495,8 @@ pnv_pci_setup_bml_iommu(struct pci_controller *hose)
        return tbl;
 }
 
-static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
-                                                struct pci_dev *pdev)
+static void pnv_pci_dma_fallback_setup(struct pci_controller *hose,
+                                      struct pci_dev *pdev)
 {
        struct device_node *np = pci_bus_to_OF_node(hose->bus);
        struct pci_dn *pdn;
@@ -512,7 +511,7 @@ static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
        set_iommu_table_base(&pdev->dev, pdn->iommu_table);
 }
 
-static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
+static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
@@ -527,7 +526,7 @@ static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
 }
 
 /* Fixup wrong class code in p7ioc root complex */
-static void __devinit pnv_p7ioc_rc_quirk(struct pci_dev *dev)
+static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
index 7698b6e13c57f6312a7505a3610fbf6b27271991..0bdc735db16f41e27d1d2b3e58320060a5b9cc03 100644 (file)
@@ -62,7 +62,7 @@ static int pnv_smp_cpu_bootable(unsigned int nr)
        return 1;
 }
 
-int __devinit pnv_smp_kick_cpu(int nr)
+int pnv_smp_kick_cpu(int nr)
 {
        unsigned int pcpu = get_hard_smp_processor_id(nr);
        unsigned long start_here = __pa(*((unsigned long *)
index 9b47ba7a5de774864f65163da84f31dbd54b5333..bfccdc7cb85f99af8128b5821b0aad0650fb46d7 100644 (file)
@@ -437,7 +437,7 @@ found_dev:
        return 0;
 }
 
-int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
        int (*callback)(const struct ps3_repository_device *repo))
 {
        int result = 0;
index a7648543c59e05435eac37c5099eeda84db9584d..0cc0ac07a55dc661e0e0ad3acceaa55d33818800 100644 (file)
@@ -57,7 +57,7 @@ static u8 dtl_event_mask = 0x7;
  */
 static int dtl_buf_entries = N_DISPATCH_LOG;
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 struct dtl_ring {
        u64     write_index;
        struct dtl_entry *write_ptr;
@@ -142,7 +142,7 @@ static u64 dtl_current_index(struct dtl *dtl)
        return per_cpu(dtl_rings, dtl->cpu).write_index;
 }
 
-#else /* CONFIG_VIRT_CPU_ACCOUNTING */
+#else /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 static int dtl_start(struct dtl *dtl)
 {
@@ -188,7 +188,7 @@ static u64 dtl_current_index(struct dtl *dtl)
 {
        return lppaca_of(dtl->cpu).dtl_idx;
 }
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 static int dtl_enable(struct dtl *dtl)
 {
index 66442341d3a6009882c0039b2049d1f7e3af1800..1efa28f5fc54c9e4234eef5439b0137f39654b1d 100644 (file)
@@ -49,7 +49,7 @@
  * It will create EEH device according to the given OF node. The function
  * might be called by PCI emunation, DR, PHB hotplug.
  */
-void * __devinit eeh_dev_init(struct device_node *dn, void *data)
+void *eeh_dev_init(struct device_node *dn, void *data)
 {
        struct pci_controller *phb = data;
        struct eeh_dev *edev;
@@ -77,7 +77,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
  * Scan the PHB OF node and its child association, then create the
  * EEH devices accordingly
  */
-void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
+void eeh_dev_phb_init_dynamic(struct pci_controller *phb)
 {
        struct device_node *dn = phb->dn;
 
index d16c8ded10847ce19d67f26a39179587707ddbf0..fe43d1aa2cf1cafcf0b1ef2cae3f9222be7bdce8 100644 (file)
@@ -66,7 +66,7 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
  * The function should be called while the PHB is detected during
  * system boot or PCI hotplug in order to create PHB PE.
  */
-int __devinit eeh_phb_pe_create(struct pci_controller *phb)
+int eeh_phb_pe_create(struct pci_controller *phb)
 {
        struct eeh_pe *pe;
 
index 261a577a3dd2db2d3e651648368ec72ef52628fd..c91b22be92889bb742569d500db73373eb5331a3 100644 (file)
@@ -149,7 +149,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
 
-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+struct pci_controller *init_phb_dynamic(struct device_node *dn)
 {
        struct pci_controller *phb;
 
index ca55882465d6b0d027ef785f941c64a342985f99..527e12c9573be178757b8eb7920b94654224e589 100644 (file)
@@ -281,7 +281,7 @@ static struct notifier_block pci_dn_reconfig_nb = {
 
 struct kmem_cache *dtl_cache;
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 /*
  * Allocate space for the dispatch trace log for all possible cpus
  * and register the buffers with the hypervisor.  This is used for
@@ -332,12 +332,12 @@ static int alloc_dispatch_logs(void)
 
        return 0;
 }
-#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
+#else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 static inline int alloc_dispatch_logs(void)
 {
        return 0;
 }
-#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 static int alloc_dispatch_log_kmem_cache(void)
 {
index 9fc0a4941908589aa334a96d47f5b6bb96bfe460..80cd0be71e06dcba2241a9162e73d229a7e5267e 100644 (file)
@@ -87,7 +87,7 @@ int smp_query_cpu_stopped(unsigned int pcpu)
  *     0       - failure
  *     1       - success
  */
-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+static inline int smp_startup_cpu(unsigned int lcpu)
 {
        int status;
        unsigned long start_here = __pa((u32)*((unsigned long *)
@@ -133,7 +133,7 @@ out:
        return 1;
 }
 
-static void __devinit smp_xics_setup_cpu(int cpu)
+static void smp_xics_setup_cpu(int cpu)
 {
        if (cpu != boot_cpuid)
                xics_setup_cpu();
@@ -148,7 +148,7 @@ static void __devinit smp_xics_setup_cpu(int cpu)
 #endif
 }
 
-static int __devinit smp_pSeries_kick_cpu(int nr)
+static int smp_pSeries_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
 
index 141e78032097326fc9c17742ea3d67023e6d8238..b56b70aeb4971c6f68a9c0815bfcadce906947ac 100644 (file)
@@ -337,8 +337,7 @@ scom_fail:
        return rc;
 }
 
-int __devinit a2_scom_startup_cpu(unsigned int lcpu, int thr_idx,
-                                 struct device_node *np)
+int a2_scom_startup_cpu(unsigned int lcpu, int thr_idx, struct device_node *np)
 {
        u64 init_iar, init_msr, init_ccr2;
        unsigned long start_here;
index 0ba103ae83a53c5218c5517227e942bf800753ba..332a18b814037843e2b21619b9a7bae2f4bba11e 100644 (file)
@@ -23,7 +23,7 @@
 #include "ics.h"
 #include "wsp.h"
 
-static void __devinit smp_a2_setup_cpu(int cpu)
+static void smp_a2_setup_cpu(int cpu)
 {
        doorbell_setup_this_cpu();
 
@@ -31,7 +31,7 @@ static void __devinit smp_a2_setup_cpu(int cpu)
                xics_setup_cpu();
 }
 
-int __devinit smp_a2_kick_cpu(int nr)
+int smp_a2_kick_cpu(int nr)
 {
        const char *enable_method;
        struct device_node *np;
index 10c1d1fff362e14c8ad85b5badb40c6fd44e5ac7..62ef21afb89a8a56189aa6638ee7a0483f6f64b0 100644 (file)
@@ -18,7 +18,7 @@ extern void a2_setup_smp(void);
 extern int a2_scom_startup_cpu(unsigned int lcpu, int thr_idx,
                               struct device_node *np);
 extern int smp_a2_cpu_bootable(unsigned int nr);
-extern int __devinit smp_a2_kick_cpu(int nr);
+extern int smp_a2_kick_cpu(int nr);
 
 extern void opb_pic_init(void);
 
index 1526551f9fe6b5541f08b15d8bbf343537c3d298..8e22f561d171aad87e0ee8f03f229c9a33abaca8 100644 (file)
@@ -402,7 +402,7 @@ static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
        return ERR_PTR(-ENOMEM);
 }
 
-static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev)
+static void wsp_pci_dma_dev_setup(struct pci_dev *pdev)
 {
        struct dev_archdata *archdata = &pdev->dev.archdata;
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
index b3fbb271be875efa2e513fffa6314add3db0dd04..d9130630f7ef6f5b8c4b00cff57843bb172c9580 100644 (file)
@@ -30,7 +30,7 @@
 #define DRIVER_NAME "bestcomm-core"
 
 /* MPC5200 device tree match tables */
-static struct of_device_id mpc52xx_sram_ids[] __devinitdata = {
+static struct of_device_id mpc52xx_sram_ids[] = {
        { .compatible = "fsl,mpc5200-sram", },
        { .compatible = "mpc5200-sram", },
        {}
@@ -273,8 +273,7 @@ static u32 fdt_ops[] = {
 };
 
 
-static int __devinit
-bcom_engine_init(void)
+static int bcom_engine_init(void)
 {
        int task;
        phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
@@ -365,7 +364,7 @@ bcom_engine_cleanup(void)
 /* OF platform driver                                                       */
 /* ======================================================================== */
 
-static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
+static int mpc52xx_bcom_probe(struct platform_device *op)
 {
        struct device_node *ofn_sram;
        struct resource res_bcom;
index d131c8a1cb15908a955147ae9d4eee3bfa5b3eb4..8cf93f029e178449b5e2b69259d6f1efc6fde6a9 100644 (file)
@@ -69,7 +69,7 @@ static int __init get_offset_from_cmdline(char *str)
 __setup("cache-sram-size=", get_size_from_cmdline);
 __setup("cache-sram-offset=", get_offset_from_cmdline);
 
-static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
+static int mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
 {
        long rval;
        unsigned int rem;
@@ -160,7 +160,7 @@ static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
+static int mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
 {
        BUG_ON(!l2ctlr);
 
@@ -213,7 +213,7 @@ static struct platform_driver mpc85xx_l2ctlr_of_platform_driver = {
                .of_match_table = mpc85xx_l2ctlr_of_match,
        },
        .probe          = mpc85xx_l2ctlr_of_probe,
-       .remove         = __devexit_p(mpc85xx_l2ctlr_of_remove),
+       .remove         = mpc85xx_l2ctlr_of_remove,
 };
 
 static __init int mpc85xx_l2ctlr_of_init(void)
index 097cc9d2585b8341068cbed9699128599dd978ec..2a36fd6a958320b58668f6e4741b10c2ceecffc5 100644 (file)
@@ -73,7 +73,7 @@ int fsl_ifc_find(phys_addr_t addr_base)
 }
 EXPORT_SYMBOL(fsl_ifc_find);
 
-static int __devinit fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
+static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
 {
        struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
 
@@ -211,7 +211,7 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
  * resources for the NAND banks themselves are allocated
  * in the chip probe function.
 */
-static int __devinit fsl_ifc_ctrl_probe(struct platform_device *dev)
+static int fsl_ifc_ctrl_probe(struct platform_device *dev)
 {
        int ret = 0;
 
index 483126d7b3c0f51dce66f6d73881f1888c7d8e40..300be2d06a26f09bc642c8cad0ef5d84422cdfac 100644 (file)
@@ -185,8 +185,8 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 }
 EXPORT_SYMBOL(fsl_upm_run_pattern);
 
-static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl,
-                                      struct device_node *node)
+static int fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl,
+                            struct device_node *node)
 {
        struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
@@ -273,7 +273,7 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
  * in the chip probe function.
 */
 
-static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
+static int fsl_lbc_ctrl_probe(struct platform_device *dev)
 {
        int ret;
 
index 63c5f04ea580177649aba38d101cb3f86b40cb35..6e53d97abd3fccb83c48bd179c7f68bfd76ca48c 100644 (file)
@@ -333,9 +333,8 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
        return 0;
 }
 
-static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
-                                        struct platform_device *dev,
-                                        int offset, int irq_index)
+static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
+                              int offset, int irq_index)
 {
        struct fsl_msi_cascade_data *cascade_data = NULL;
        int virt_msir;
@@ -363,7 +362,7 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
 }
 
 static const struct of_device_id fsl_of_msi_ids[];
-static int __devinit fsl_of_msi_probe(struct platform_device *dev)
+static int fsl_of_msi_probe(struct platform_device *dev)
 {
        const struct of_device_id *match;
        struct fsl_msi *msi;
index 5ba325bff3a28422cbbe2303e24783eca452fb38..92a5915b18276ec2cd0fc3b0d27107e770cd98a8 100644 (file)
@@ -36,7 +36,7 @@
 
 static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
-static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev)
+static void quirk_fsl_pcie_header(struct pci_dev *dev)
 {
        u8 hdr_type;
 
@@ -871,7 +871,7 @@ void fsl_pci_assign_primary(void)
        }
 }
 
-static int __devinit fsl_pci_probe(struct platform_device *pdev)
+static int fsl_pci_probe(struct platform_device *pdev)
 {
        int ret;
        struct device_node *node;
index 5b6f556094dd088271b569cd6c79f8c85fe2bf0d..e2fb3171f41b80545a99043b5a222b84adb799ba 100644 (file)
@@ -644,7 +644,7 @@ err_rio_regs:
 
 /* The probe function for RapidIO peer-to-peer network.
  */
-static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
+static int fsl_of_rio_rpn_probe(struct platform_device *dev)
 {
        printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
                        dev->dev.of_node->full_name);
index 9c6e535daad27b676422ea0813f27d322c576452..3b2efd41abf24d76710e0b38b176870c0e37f502 100644 (file)
@@ -1864,7 +1864,7 @@ int __init smp_mpic_probe(void)
        return nr_cpus;
 }
 
-void __devinit smp_mpic_setup_cpu(int cpu)
+void smp_mpic_setup_cpu(int cpu)
 {
        mpic_setup_this_cpu();
 }
index e961f8c4a8f070f341c2b80bbd8a18456a323ade..c75325865a8573053e0e47279d00d046c19dab9f 100644 (file)
@@ -160,7 +160,7 @@ static int mpic_msgr_block_number(struct device_node *node)
 
 /* The probe function for a single message register block.
  */
-static __devinit int mpic_msgr_probe(struct platform_device *dev)
+static int mpic_msgr_probe(struct platform_device *dev)
 {
        void __iomem *msgr_block_addr;
        int block_number;
index 364b14d4754b995336f7d7058806ddf2ab25c25c..330d56613c5a0ca88513e234cbbe0ce15ce77b11 100644 (file)
@@ -104,7 +104,7 @@ subsys_initcall(mv64x60_sysfs_init);
 
 #endif /* CONFIG_SYSFS */
 
-static void __devinit mv64x60_pci_fixup_early(struct pci_dev *dev)
+static void mv64x60_pci_fixup_early(struct pci_dev *dev)
 {
        /*
         * Set the host bridge hdr_type to an invalid value so that
index 82c6702dcbab7a756a7ed53de6c7638348f15c97..43948da837a799628aed3c33d9b89871ea4dc3b0 100644 (file)
@@ -220,7 +220,7 @@ static int ppc4xx_of_msi_remove(struct platform_device *dev)
        return 0;
 }
 
-static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
+static int ppc4xx_msi_probe(struct platform_device *dev)
 {
        struct ppc4xx_msi *msi;
        struct resource res;
index 32425af9d68d7b6379c7bba2da62cb335c8ad7be..c15ba7d1be643d9251079bba0d984a11f7d3d425 100644 (file)
@@ -78,7 +78,6 @@ config S390
        select HAVE_KVM if 64BIT
        select HAVE_ARCH_TRACEHOOK
        select INIT_ALL_POSSIBLE
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select HAVE_DEBUG_KMEMLEAK
@@ -137,8 +136,6 @@ config S390
        select GENERIC_CLOCKEVENTS
        select KTIME_SCALAR if 32BIT
        select HAVE_ARCH_SECCOMP_FILTER
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS2
index 4b8e08b56f49679b40bd4ee098bae0bb01945292..7e3ce78d42902e636de522d8f568e00e0f75701f 100644 (file)
@@ -24,8 +24,8 @@ CHECKFLAGS    += -D__s390__ -msize-long
 else
 LD_BFD         := elf64-s390
 LDFLAGS                := -m elf64_s390
-KBUILD_AFLAGS_MODULE += -fpic -D__PIC__
-KBUILD_CFLAGS_MODULE += -fpic -D__PIC__
+KBUILD_AFLAGS_MODULE += -fPIC
+KBUILD_CFLAGS_MODULE += -fPIC
 KBUILD_CFLAGS  += -m64
 KBUILD_AFLAGS  += -m64
 UTS_MACHINE    := s390x
index 18cd6b592650962010b7c72f32b0d401cf572a57..f8c6df6cd1f02c93910de5fba976b1c4161879dd 100644 (file)
@@ -7,6 +7,9 @@
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 
+#define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64))
+#define __SC_DELOUSE(t,v) (t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v))
+
 #define PSW32_MASK_PER         0x40000000UL
 #define PSW32_MASK_DAT         0x04000000UL
 #define PSW32_MASK_IO          0x02000000UL
index de015d85e3e5f9ce7f3f308e3bb5175d7bfcd2c0..bb9bdcd20864ea41546e670df5369c7bebfdda2d 100644 (file)
  */
 #define MAX_DMA_ADDRESS         0x80000000
 
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy   (0)
+#endif
+
 #endif /* _ASM_S390_DMA_H */
index 16c3eb164f4fe0cdb44b91eb3be271743b8beeb8..27cb32185ce1d950e5a6097198a1864a69e6594b 100644 (file)
@@ -85,6 +85,11 @@ static inline void iounmap(volatile void __iomem *addr)
 #define __raw_writel   zpci_write_u32
 #define __raw_writeq   zpci_write_u64
 
+#define readb_relaxed  readb
+#define readw_relaxed  readw
+#define readl_relaxed  readl
+#define readq_relaxed  readq
+
 #endif /* CONFIG_PCI */
 
 #include <asm-generic/io.h>
index e6972f85d2b0926e58832e955cefb538e58618e7..7def77302d630995a1018cd2ffe02a05ee289e10 100644 (file)
@@ -2,43 +2,61 @@
 #define _ASM_IRQ_H
 
 #include <linux/hardirq.h>
+#include <linux/percpu.h>
+#include <linux/cache.h>
 #include <linux/types.h>
 
-enum interruption_class {
+enum interruption_main_class {
        EXTERNAL_INTERRUPT,
        IO_INTERRUPT,
-       EXTINT_CLK,
-       EXTINT_EXC,
-       EXTINT_EMS,
-       EXTINT_TMR,
-       EXTINT_TLA,
-       EXTINT_PFL,
-       EXTINT_DSD,
-       EXTINT_VRT,
-       EXTINT_SCP,
-       EXTINT_IUC,
-       EXTINT_CMS,
-       EXTINT_CMC,
-       EXTINT_CMR,
-       IOINT_CIO,
-       IOINT_QAI,
-       IOINT_DAS,
-       IOINT_C15,
-       IOINT_C70,
-       IOINT_TAP,
-       IOINT_VMR,
-       IOINT_LCS,
-       IOINT_CLW,
-       IOINT_CTC,
-       IOINT_APB,
-       IOINT_ADM,
-       IOINT_CSC,
-       IOINT_PCI,
-       IOINT_MSI,
+       NR_IRQS
+};
+
+enum interruption_class {
+       IRQEXT_CLK,
+       IRQEXT_EXC,
+       IRQEXT_EMS,
+       IRQEXT_TMR,
+       IRQEXT_TLA,
+       IRQEXT_PFL,
+       IRQEXT_DSD,
+       IRQEXT_VRT,
+       IRQEXT_SCP,
+       IRQEXT_IUC,
+       IRQEXT_CMS,
+       IRQEXT_CMC,
+       IRQEXT_CMR,
+       IRQIO_CIO,
+       IRQIO_QAI,
+       IRQIO_DAS,
+       IRQIO_C15,
+       IRQIO_C70,
+       IRQIO_TAP,
+       IRQIO_VMR,
+       IRQIO_LCS,
+       IRQIO_CLW,
+       IRQIO_CTC,
+       IRQIO_APB,
+       IRQIO_ADM,
+       IRQIO_CSC,
+       IRQIO_PCI,
+       IRQIO_MSI,
        NMI_NMI,
-       NR_IRQS,
+       CPU_RST,
+       NR_ARCH_IRQS
 };
 
+struct irq_stat {
+       unsigned int irqs[NR_ARCH_IRQS];
+};
+
+DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
+
+static __always_inline void inc_irq_stat(enum interruption_class irq)
+{
+       __get_cpu_var(irq_stat).irqs[irq]++;
+}
+
 struct ext_code {
        unsigned short subcode;
        unsigned short code;
index c928dc1938f23c8a90134c972147c9bbfecb005e..098adbb62660be234d4d2ed5171d5c0615027f31 100644 (file)
@@ -1365,6 +1365,18 @@ static inline void pmdp_invalidate(struct vm_area_struct *vma,
        __pmd_idte(address, pmdp);
 }
 
+#define __HAVE_ARCH_PMDP_SET_WRPROTECT
+static inline void pmdp_set_wrprotect(struct mm_struct *mm,
+                                     unsigned long address, pmd_t *pmdp)
+{
+       pmd_t pmd = *pmdp;
+
+       if (pmd_write(pmd)) {
+               __pmd_idte(address, pmdp);
+               set_pmd_at(mm, address, pmdp, pmd_wrprotect(pmd));
+       }
+}
+
 static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
 {
        pmd_t __pmd;
@@ -1387,10 +1399,7 @@ static inline int has_transparent_hugepage(void)
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-       if (pmd_trans_huge(pmd))
-               return pmd_val(pmd) >> HPAGE_SHIFT;
-       else
-               return pmd_val(pmd) >> PAGE_SHIFT;
+       return pmd_val(pmd) >> PAGE_SHIFT;
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
index fba4d66788a247c94adfba5c13ae750e19929496..4c060bb5b8eafbfc5b816411dc91f9dea1201daf 100644 (file)
@@ -128,4 +128,32 @@ static inline unsigned long long get_clock_monotonic(void)
        return get_clock_xt() - sched_clock_base_cc;
 }
 
+/**
+ * tod_to_ns - convert a TOD format value to nanoseconds
+ * @todval: to be converted TOD format value
+ * Returns: number of nanoseconds that correspond to the TOD format value
+ *
+ * Converting a 64 Bit TOD format value to nanoseconds means that the value
+ * must be divided by 4.096. In order to achieve that we multiply with 125
+ * and divide by 512:
+ *
+ *    ns = (todval * 125) >> 9;
+ *
+ * In order to avoid an overflow with the multiplication we can rewrite this.
+ * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits)
+ * we end up with
+ *
+ *    ns = ((2^32 * th + tl) * 125 ) >> 9;
+ * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9);
+ *
+ */
+static inline unsigned long long tod_to_ns(unsigned long long todval)
+{
+       unsigned long long ns;
+
+       ns = ((todval >> 32) << 23) * 125;
+       ns += ((todval & 0xffffffff) * 125) >> 9;
+       return ns;
+}
+
 #endif
index 086bb8eaf6abf3a75e6df3992519f69f1513851c..636530872516a64c8f30e42cf9a0bab4cee511bf 100644 (file)
@@ -53,7 +53,6 @@
 #   define __ARCH_WANT_COMPAT_SYS_TIME
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
index 8c6a49e392eeae353fe377d2da00c8992a2f455a..2f43cfbf5f1a0036e5b911d94148a745f6d415a0 100644 (file)
@@ -90,12 +90,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER     0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK      1
-#define SS_DISABLE      2
-
 #define MINSIGSTKSZ     2048
 #define SIGSTKSZ        8192
 
index 63e6078699f11caf124fdd94ea220cf730f860f3..864f693c237fe440cd02125e588c4b5867b6edb8 100644 (file)
 #define __NR_process_vm_writev 341
 #define __NR_s390_runtime_instr 342
 #define __NR_kcmp              343
-#define NR_syscalls 344
+#define __NR_finit_module      344
+#define NR_syscalls 345
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 827e094a2f494d09bdf1936cde25df431ec7c012..9b9a805656b505e803a2bb9bb4da21e9c8f6f59c 100644 (file)
@@ -1659,3 +1659,9 @@ ENTRY(sys_kcmp_wrapper)
        llgfr   %r5,%r5                 # unsigned long
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_kcmp
+
+ENTRY(sys_finit_module_wrapper)
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # const char __user *
+       lgfr    %r4,%r4                 # int
+       jg      sys_finit_module
index ba500d8dc392056ddd66e4978389d072452f6859..4e8215e0d4b6d3047ec7df266e350e0e0ad83992 100644 (file)
@@ -1127,13 +1127,14 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
        if (i == DEBUG_MAX_VIEWS) {
                pr_err("Registering view %s/%s would exceed the maximum "
                       "number of views %i\n", id->name, view->name, i);
-               debugfs_remove(pde);
                rc = -1;
        } else {
                id->views[i] = view;
                id->debugfs_entries[i] = pde;
        }
        spin_unlock_irqrestore(&id->lock, flags);
+       if (rc)
+               debugfs_remove(pde);
 out:
        return rc;
 }
@@ -1146,9 +1147,9 @@ EXPORT_SYMBOL(debug_register_view);
 int
 debug_unregister_view(debug_info_t * id, struct debug_view *view)
 {
-       int rc = 0;
-       int i;
+       struct dentry *dentry = NULL;
        unsigned long flags;
+       int i, rc = 0;
 
        if (!id)
                goto out;
@@ -1160,10 +1161,12 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
        if (i == DEBUG_MAX_VIEWS)
                rc = -1;
        else {
-               debugfs_remove(id->debugfs_entries[i]);
+               dentry = id->debugfs_entries[i];
                id->views[i] = NULL;
+               id->debugfs_entries[i] = NULL;
        }
        spin_unlock_irqrestore(&id->lock, flags);
+       debugfs_remove(dentry);
 out:
        return rc;
 }
index bf24293970ce544b358f9bb3f4d4c7daa9bde88f..9df824ea16672aea9e8f6a93ec6c925f7b982a3a 100644 (file)
 #include <asm/irq.h>
 #include "entry.h"
 
+DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
+EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
+
 struct irq_class {
        char *name;
        char *desc;
 };
 
-static const struct irq_class intrclass_names[] = {
+/*
+ * The list of "main" irq classes on s390. This is the list of interrrupts
+ * that appear both in /proc/stat ("intr" line) and /proc/interrupts.
+ * Historically only external and I/O interrupts have been part of /proc/stat.
+ * We can't add the split external and I/O sub classes since the first field
+ * in the "intr" line in /proc/stat is supposed to be the sum of all other
+ * fields.
+ * Since the external and I/O interrupt fields are already sums we would end
+ * up with having a sum which accounts each interrupt twice.
+ */
+static const struct irq_class irqclass_main_desc[NR_IRQS] = {
        [EXTERNAL_INTERRUPT] = {.name = "EXT"},
-       [IO_INTERRUPT]       = {.name = "I/O"},
-       [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
-       [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
-       [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
-       [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
-       [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
-       [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
-       [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
-       [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
-       [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
-       [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
-       [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
-       [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
-       [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
-       [IOINT_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
-       [IOINT_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
-       [IOINT_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
-       [IOINT_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
-       [IOINT_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
-       [IOINT_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
-       [IOINT_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
-       [IOINT_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
-       [IOINT_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
-       [IOINT_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
-       [IOINT_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
-       [IOINT_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
-       [IOINT_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
-       [IOINT_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
-       [IOINT_MSI] =  {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
+       [IO_INTERRUPT]       = {.name = "I/O"}
+};
+
+/*
+ * The list of split external and I/O interrupts that appear only in
+ * /proc/interrupts.
+ * In addition this list contains non external / I/O events like NMIs.
+ */
+static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
+       [IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
+       [IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
+       [IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
+       [IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
+       [IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
+       [IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
+       [IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
+       [IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
+       [IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
+       [IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
+       [IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
+       [IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
+       [IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+       [IRQIO_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
+       [IRQIO_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
+       [IRQIO_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
+       [IRQIO_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
+       [IRQIO_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
+       [IRQIO_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
+       [IRQIO_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
+       [IRQIO_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
+       [IRQIO_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
+       [IRQIO_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
+       [IRQIO_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
+       [IRQIO_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
+       [IRQIO_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+       [IRQIO_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
+       [IRQIO_MSI]  = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
        [NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},
+       [CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},
 };
 
 /*
@@ -68,30 +90,34 @@ static const struct irq_class intrclass_names[] = {
  */
 int show_interrupts(struct seq_file *p, void *v)
 {
-       int i = *(loff_t *) v, j;
+       int irq = *(loff_t *) v;
+       int cpu;
 
        get_online_cpus();
-       if (i == 0) {
+       if (irq == 0) {
                seq_puts(p, "           ");
-               for_each_online_cpu(j)
-                       seq_printf(p, "CPU%d       ",j);
+               for_each_online_cpu(cpu)
+                       seq_printf(p, "CPU%d       ", cpu);
                seq_putc(p, '\n');
        }
-
-       if (i < NR_IRQS) {
-               seq_printf(p, "%s: ", intrclass_names[i].name);
-#ifndef CONFIG_SMP
-               seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-               for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-               if (intrclass_names[i].desc)
-                       seq_printf(p, "  %s", intrclass_names[i].desc);
-                seq_putc(p, '\n');
-        }
+       if (irq < NR_IRQS) {
+               seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
+               for_each_online_cpu(cpu)
+                       seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]);
+               seq_putc(p, '\n');
+               goto skip_arch_irqs;
+       }
+       for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
+               seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
+               for_each_online_cpu(cpu)
+                       seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]);
+               if (irqclass_sub_desc[irq].desc)
+                       seq_printf(p, "  %s", irqclass_sub_desc[irq].desc);
+               seq_putc(p, '\n');
+       }
+skip_arch_irqs:
        put_online_cpus();
-        return 0;
+       return 0;
 }
 
 /*
@@ -222,7 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code,
                /* Serve timer interrupts first. */
                clock_comparator_work();
        }
-       kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+       kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL);
        if (ext_code.code != 0x1004)
                __get_cpu_var(s390_idle).nohz_delay = 1;
 
index a6daa5c5cdb047708be93a173e47095af9d0f9f4..7918fbea36bb31446d6bea5d438854c8c2464938 100644 (file)
@@ -254,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
        int umode;
 
        nmi_enter();
-       kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++;
+       inc_irq_stat(NMI_NMI);
        mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
        mcck = &__get_cpu_var(cpu_mcck);
        umode = user_mode(regs);
index c4e7269d4a0980d8736c5a9c32e916cb581b0a58..86ec7447e1f5d57f8c4a53eb2867d355db1f45f3 100644 (file)
@@ -229,7 +229,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
        if (!(alert & CPU_MF_INT_CF_MASK))
                return;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++;
+       inc_irq_stat(IRQEXT_CMC);
        cpuhw = &__get_cpu_var(cpu_hw_events);
 
        /* Measurement alerts are shared and might happen when the PMU
index 61066f6f71a590d3d35fd688e8e6715719919dc1..077a99389b07919a2e0575b6b46249589f3cf968 100644 (file)
@@ -71,7 +71,7 @@ static void runtime_instr_int_handler(struct ext_code ext_code,
        if (!(param32 & CPU_MF_INT_RI_MASK))
                return;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++;
+       inc_irq_stat(IRQEXT_CMR);
 
        if (!current->thread.ri_cb)
                return;
index 2568590973ad2e429f394ce4f6147211e7169b11..a5360de85ec7e7eb190f64de6028d08ea2e2c68e 100644 (file)
@@ -16,7 +16,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/memblock.h>
@@ -289,6 +289,7 @@ void machine_power_off(void)
  * Dummy power off function.
  */
 void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL_GPL(pm_power_off);
 
 static int __init early_parse_mem(char *p)
 {
index ea431e551c6b2704a19d068376d9edb84c3da577..7433a2f9e5ccc3352236f52e8f365147bbb6a433 100644 (file)
@@ -433,9 +433,9 @@ static void do_ext_call_interrupt(struct ext_code ext_code,
 
        cpu = smp_processor_id();
        if (ext_code.code == 0x1202)
-               kstat_cpu(cpu).irqs[EXTINT_EXC]++;
+               inc_irq_stat(IRQEXT_EXC);
        else
-               kstat_cpu(cpu).irqs[EXTINT_EMS]++;
+               inc_irq_stat(IRQEXT_EMS);
        /*
         * handle bit signal external calls
         */
@@ -623,9 +623,9 @@ static struct sclp_cpu_info *smp_get_cpu_info(void)
        return info;
 }
 
-static int __devinit smp_add_present_cpu(int cpu);
+static int __cpuinit smp_add_present_cpu(int cpu);
 
-static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info,
+static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info,
                                       int sysfs_add)
 {
        struct pcpu *pcpu;
@@ -709,6 +709,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid)
        pfault_init();
        notify_cpu_starting(smp_processor_id());
        set_cpu_online(smp_processor_id(), true);
+       inc_irq_stat(CPU_RST);
        local_irq_enable();
        /* cpu_idle will call schedule for us */
        cpu_idle();
@@ -986,7 +987,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
        return notifier_from_errno(err);
 }
 
-static int __devinit smp_add_present_cpu(int cpu)
+static int __cpuinit smp_add_present_cpu(int cpu)
 {
        struct cpu *c = &pcpu_devices[cpu].cpu;
        struct device *s = &c->dev;
index 48174850f3b0859f05b2b5023f09cdbb827c9d56..6a6c61f94dd32244d62a9d25985ed8844dfb988b 100644 (file)
@@ -352,3 +352,4 @@ SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wr
 SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
 SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
 SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
+SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
index 7fcd690d42c753bfd027d00b05da12e35cf711cd..0aa98db8a80dff08f4ba392139e80eec173bfd62 100644 (file)
@@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);
  */
 unsigned long long notrace __kprobes sched_clock(void)
 {
-       return (get_clock_monotonic() * 125) >> 9;
+       return tod_to_ns(get_clock_monotonic());
 }
 
 /*
@@ -120,6 +120,9 @@ static int s390_next_ktime(ktime_t expires,
        nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
        do_div(nsecs, 125);
        S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
+       /* Program the maximum value if we have an overflow (== year 2042) */
+       if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc))
+               S390_lowcore.clock_comparator = -1ULL;
        set_clock_comparator(S390_lowcore.clock_comparator);
        return 0;
 }
@@ -168,7 +171,7 @@ static void clock_comparator_interrupt(struct ext_code ext_code,
                                       unsigned int param32,
                                       unsigned long param64)
 {
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++;
+       inc_irq_stat(IRQEXT_CLK);
        if (S390_lowcore.clock_comparator == -1ULL)
                set_clock_comparator(S390_lowcore.clock_comparator);
 }
@@ -179,7 +182,7 @@ static void stp_timing_alert(struct stp_irq_parm *);
 static void timing_alert_interrupt(struct ext_code ext_code,
                                   unsigned int param32, unsigned long param64)
 {
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++;
+       inc_irq_stat(IRQEXT_TLA);
        if (param32 & 0x00c40000)
                etr_timing_alert((struct etr_irq_parm *) &param32);
        if (param32 & 0x00038000)
index f1aba87cceb8acfd7d47df98ad3cb0854e3db288..4b2e3e317004a3cf5d725887c1136c9cbcdd4045 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/bootmem.h>
 #include <linux/cpuset.h>
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -42,6 +43,7 @@ static struct mask_info socket_info;
 static struct mask_info book_info;
 
 struct cpu_topology_s390 cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
 
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
index e84b8b68444a7289f6544361378bd00617aa9346..ce9cc5aa2033f735eb2db02fc3ca6319943861b3 100644 (file)
@@ -127,7 +127,7 @@ void vtime_account_user(struct task_struct *tsk)
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-void vtime_account(struct task_struct *tsk)
+void vtime_account_irq_enter(struct task_struct *tsk)
 {
        struct thread_info *ti = task_thread_info(tsk);
        u64 timer, system;
@@ -145,10 +145,10 @@ void vtime_account(struct task_struct *tsk)
 
        virt_timer_forward(system);
 }
-EXPORT_SYMBOL_GPL(vtime_account);
+EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
 
 void vtime_account_system(struct task_struct *tsk)
-__attribute__((alias("vtime_account")));
+__attribute__((alias("vtime_account_irq_enter")));
 EXPORT_SYMBOL_GPL(vtime_account_system);
 
 void __kprobes vtime_stop_cpu(void)
index c30615e605ac6716a1f93ee8dc377f9691ee99e0..82c481ddef76286c9be88ce0e45e4df31780eb5d 100644 (file)
@@ -408,7 +408,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
                return 0;
        }
 
-       sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9;
+       sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
 
        hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
        VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
index c9011bfaabbe8594bdd6d3c63ce242a55897cff3..f090e819bf71817ccf564d8798632fc6bf2d7fb7 100644 (file)
@@ -613,7 +613,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                kvm_s390_deliver_pending_interrupts(vcpu);
 
        vcpu->arch.sie_block->icptcode = 0;
+       preempt_disable();
        kvm_guest_enter();
+       preempt_enable();
        VCPU_EVENT(vcpu, 6, "entering sie flags %x",
                   atomic_read(&vcpu->arch.sie_block->cpuflags));
        trace_kvm_s390_sie_enter(vcpu,
index 42601d6e166fe73db1e6e97382df8158212dd5d7..2fb9e63b8fc44e58ae415dddefa3a067f48071da 100644 (file)
@@ -569,7 +569,7 @@ static void pfault_interrupt(struct ext_code ext_code,
        subcode = ext_code.subcode;
        if ((subcode & 0xff00) != __SUBCODE_MASK)
                return;
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
+       inc_irq_stat(IRQEXT_PFL);
        /* Get the token (= pid of the affected task). */
        pid = sizeof(void *) == 4 ? param32 : param64;
        rcu_read_lock();
index 0cb385da202c60836fd2cd006e5950ed448de656..b5b2916895e08dd8b562fb7784628c4a0294f55b 100644 (file)
@@ -233,7 +233,7 @@ static void hws_ext_handler(struct ext_code ext_code,
        if (!(param32 & CPU_MF_INT_SF_MASK))
                return;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_CMS]++;
+       inc_irq_stat(IRQEXT_CMS);
        atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32);
 
        if (hws_wq)
index 8fa416b8775ffc8a58355d4c9a29c2c4001c94ad..60e0372545d2800778ef067a7da9d139899fc5b8 100644 (file)
@@ -160,35 +160,6 @@ int pci_proc_domain(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pci_proc_domain);
 
-/* Store PCI function information block */
-static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc)
-{
-       struct zpci_fib *fib;
-       u8 status, cc;
-
-       fib = (void *) get_zeroed_page(GFP_KERNEL);
-       if (!fib)
-               return -ENOMEM;
-
-       do {
-               cc = __stpcifc(zdev->fh, 0, fib, &status);
-               if (cc == 2) {
-                       msleep(ZPCI_INSN_BUSY_DELAY);
-                       memset(fib, 0, PAGE_SIZE);
-               }
-       } while (cc == 2);
-
-       if (cc)
-               pr_err_once("%s: cc: %u  status: %u\n",
-                           __func__, cc, status);
-
-       /* Return PCI function controls */
-       *fc = fib->fc;
-
-       free_page((unsigned long) fib);
-       return (cc) ? -EIO : 0;
-}
-
 /* Modify PCI: Register adapter interruptions */
 static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
                              u64 aibv)
@@ -385,7 +356,7 @@ unsigned int probe_irq_mask(unsigned long val)
 }
 EXPORT_SYMBOL_GPL(probe_irq_mask);
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
@@ -469,7 +440,7 @@ static void zpci_irq_handler(void *dont, void *need)
        int rescan = 0, max = aisb_max;
        struct zdev_irq_map *imap;
 
-       kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++;
+       inc_irq_stat(IRQIO_PCI);
        sbit = start;
 
 scan:
@@ -481,7 +452,7 @@ scan:
                /* find vector bit */
                imap = bucket->imap[sbit];
                for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) {
-                       kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++;
+                       inc_irq_stat(IRQIO_MSI);
                        clear_bit(63 - mbit, &imap->aibv);
 
                        spin_lock(&imap->lock);
index 6138468b420f5653d0e3c96ae485a0e0a1649c95..a547419907c3a46be4e7a64c36f3f1a776abcfcf 100644 (file)
@@ -13,8 +13,6 @@
 #include <linux/pci.h>
 #include <asm/pci_dma.h>
 
-static enum zpci_ioat_dtype zpci_ioat_dt = ZPCI_IOTA_RTTO;
-
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
 
index 45893390c7ddb4f32052764177b3f2d01949b53c..3b1482e7afacd37969f338158468bc95bb2dc8d6 100644 (file)
@@ -13,8 +13,6 @@ config SCORE
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select CLONE_BACKWARDS
 
 choice
index 78fc538db84c70b672ba397f48a5ee659f91c6ff..abc279d96b7306858f82736ed98d1a614aef5783 100644 (file)
@@ -13,6 +13,7 @@ struct task_struct;
 
 #define instruction_pointer(regs)      ((unsigned long)(regs)->cp0_epc)
 #define profile_pc(regs)               instruction_pointer(regs)
+#define user_stack_pointer(r)          ((unsigned long)(r)->regs[0])
 
 extern void do_syscall_trace(struct pt_regs *regs, int entryexit);
 extern int read_tsk_long(struct task_struct *, unsigned long, unsigned long *);
index 56001c93095aaa7977d869e41f7866a5b0598f2c..9cb4260a5f3e3ea232fd1a328bac9f7e5ed854b3 100644 (file)
@@ -4,7 +4,6 @@
 #define __ARCH_WANT_SYSCALL_NO_FLAGS
 #define __ARCH_WANT_SYSCALL_OFF_T
 #define __ARCH_WANT_SYSCALL_DEPRECATED
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
index b25e957436000a1f94f51e8d4264e9500a84469b..f85ec1a7c88e85c683a0cd2faba78513d1b15d0c 100644 (file)
@@ -113,7 +113,7 @@ static inline void setup_protection_map(void)
        protection_map[15] = PAGE_SHARED;
 }
 
-void __devinit cpu_cache_init(void)
+void cpu_cache_init(void)
 {
        setup_protection_map();
 }
index 8451317eed58d3b79bc7ec3df8df6eac0b20fd0d..9c833c5858712b88897eec7c135842242d8e2d75 100644 (file)
@@ -11,7 +11,6 @@ config SUPERH
        select HAVE_ARCH_TRACEHOOK
        select HAVE_DMA_API_DEBUG
        select HAVE_DMA_ATTRS
-       select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select HAVE_DEBUG_BUGVERBOSE
        select ARCH_HAVE_CUSTOM_GPIO_H
@@ -40,8 +39,6 @@ config SUPERH
        select GENERIC_STRNLEN_USER
        select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -93,9 +90,6 @@ config GENERIC_CSUM
 config GENERIC_HWEIGHT
        def_bool y
 
-config IRQ_PER_CPU
-       def_bool y
-
 config GENERIC_GPIO
        def_bool n
 
index 3fede4556c91eee6ae7e5aa7a449675710254150..a0fa5791cd44abe9b29784e26142338c11768c1d 100644 (file)
  *                                  OFF-ON : MMC
  */
 
+/*
+ * FSI - DA7210
+ *
+ * it needs amixer settings for playing
+ *
+ * amixer set 'HeadPhone' 80
+ * amixer set 'Out Mixer Left DAC Left' on
+ * amixer set 'Out Mixer Right DAC Right' on
+ */
+
 /* Heartbeat */
 static unsigned char led_pos[] = { 0, 1, 2, 3 };
 
index a5fe1b54c952598090fac62b46f31970552a35fc..d6cde700e316950f3abec82476f2e40d2b22ddd2 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/irq.h>
 #include <mach/pci.h>
 
-static void __devinit gapspci_fixup_resources(struct pci_dev *dev)
+static void gapspci_fixup_resources(struct pci_dev *dev)
 {
        struct pci_channel *p = dev->sysdata;
 
index 81e5dafed3e47aae8b047796f94f85c6bbbef1ef..102f5d58b0371ac512af95a4d8994b91ad53a227 100644 (file)
@@ -32,7 +32,7 @@ static struct pci_channel *hose_head, **hose_tail = &hose_head;
 
 static int pci_initialized;
 
-static void __devinit pcibios_scanbus(struct pci_channel *hose)
+static void pcibios_scanbus(struct pci_channel *hose)
 {
        static int next_busno;
        static int need_domain_info;
@@ -82,7 +82,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
 DEFINE_RAW_SPINLOCK(pci_config_lock);
 static DEFINE_MUTEX(pci_scan_mutex);
 
-int __devinit register_pci_controller(struct pci_channel *hose)
+int register_pci_controller(struct pci_channel *hose)
 {
        int i;
 
@@ -156,7 +156,7 @@ subsys_initcall(pcibios_init);
  *  Called after each bus is probed, but before its children
  *  are examined.
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
index 9e702f2f80452a222e08f490f9095c948b1143e4..c2c85f6cd738c12ed26ca805b7e7acf16f5809da 100644 (file)
@@ -132,7 +132,7 @@ static struct clk fixed_pciexclkp = {
        .rate = 100000000,      /* 100 MHz reference clock */
 };
 
-static void __devinit sh7786_pci_fixup(struct pci_dev *dev)
+static void sh7786_pci_fixup(struct pci_dev *dev)
 {
        /*
         * Prevent enumeration of root complex resources.
index 37924afa8d8a26781a2e8ebf4952144b141f9295..bf9f44f17c2983a1f1994f451ab03d3e89c05355 100644 (file)
@@ -203,9 +203,9 @@ extern void __kernel_vsyscall;
        if (vdso_enabled)                                       \
                NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);        \
        else                                                    \
-               NEW_AUX_ENT(AT_IGNORE, 0);
+               NEW_AUX_ENT(AT_IGNORE, 0)
 #else
-#define VSYSCALL_AUX_ENT
+#define VSYSCALL_AUX_ENT       NEW_AUX_ENT(AT_IGNORE, 0)
 #endif /* CONFIG_VSYSCALL */
 
 #ifdef CONFIG_SH_FPU
index b1320d55ca305139f5087694a6c6b3c2db3a6990..e699a12cdcca0da391ee072797c74208fa93eddb 100644 (file)
@@ -39,7 +39,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     (TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
 
 /*
  * Bit of SR register
index 1ee8946f09520a987a19ae477cac15087f19bf4a..1cc7d31971435ee57f9997539fcec28e061b6187 100644 (file)
@@ -47,7 +47,7 @@ pc; })
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     (TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
 
 /*
  * Bit of SR register
index 43d3f26b2eab4cb8c891906a1e5e206cf6abd8cd..012004ed33305b84b32f1609932ec0b0bbc321a1 100644 (file)
@@ -28,7 +28,6 @@
 # define __ARCH_WANT_SYS_SIGPENDING
 # define __ARCH_WANT_SYS_SIGPROCMASK
 # define __ARCH_WANT_SYS_RT_SIGACTION
-# define __ARCH_WANT_SYS_EXECVE
 # define __ARCH_WANT_SYS_FORK
 # define __ARCH_WANT_SYS_VFORK
 # define __ARCH_WANT_SYS_CLONE
index 9e465f246dc1e49882473fdcdeb34f6520eb6b10..d13a1d6237363747117770a7620f448b08474e47 100644 (file)
 #define __NR_process_vm_readv  365
 #define __NR_process_vm_writev 366
 #define __NR_kcmp              367
+#define __NR_finit_module      368
 
-#define NR_syscalls 368
+#define NR_syscalls 369
 
 #endif /* __ASM_SH_UNISTD_32_H */
index 8e3a2edd284eadbefe740d9fea0cbcd14a27e48f..e6820c86e8c7bc1c0daf34cd9a891c45b3a5775f 100644 (file)
 #define __NR_process_vm_readv  376
 #define __NR_process_vm_writev 377
 #define __NR_kcmp              378
+#define __NR_finit_module      379
 
-#define NR_syscalls 379
+#define NR_syscalls 380
 
 #endif /* __ASM_SH_UNISTD_64_H */
index fe97ae5e56f168e642e4825fc76575a8a61811b2..734234be2f011cfb529bacecd8a0efdfaa8762ca 100644 (file)
@@ -385,3 +385,4 @@ ENTRY(sys_call_table)
        .long sys_process_vm_readv      /* 365 */
        .long sys_process_vm_writev
        .long sys_kcmp
+       .long sys_finit_module
index 5c7b1c67bdc1c04f9c858644c066063a7eaf6919..579fcb9a896be37d01421ce96e8b3fec18ff7e3b 100644 (file)
@@ -405,3 +405,4 @@ sys_call_table:
        .long sys_process_vm_readv
        .long sys_process_vm_writev
        .long sys_kcmp
+       .long sys_finit_module
index 60164e65d66551c4375121e984fd0ea28a9525fa..52aa2011d7537daa0b502d1891df4ee0184079fe 100644 (file)
@@ -294,6 +294,8 @@ stack_panic:
        .align 2
 .L_init_thread_union:
        .long   init_thread_union
+.L_ebss:
+       .long   __bss_stop
 .Lpanic:
        .long   panic
 .Lpanic_s:
index 0c7d365fa402d90dacbc9566ee8eb121b726b75a..9bff3db17c8c8ad66952ec3d0d557e2f5433e311 100644 (file)
@@ -23,7 +23,6 @@ config SPARC
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select RTC_CLASS
        select RTC_DRV_M48T59
-       select HAVE_IRQ_WORK
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
        select HAVE_ARCH_JUMP_LABEL
@@ -41,8 +40,6 @@ config SPARC
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 config SPARC32
        def_bool !64BIT
@@ -63,6 +60,7 @@ config SPARC64
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_SYSCALL_WRAPPERS
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_SYSCALL_TRACEPOINTS
index cb33608cc68f3c7c40a01e5ff49949b0ac15f0bf..c55291e5b83e8512f22c107c82ad3a3a49f2c712 100644 (file)
@@ -103,7 +103,7 @@ static inline unsigned int get_dma_residue(unsigned int dmanr)
        return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
 }
 
-static int __devinit ecpp_probe(struct platform_device *op)
+static int ecpp_probe(struct platform_device *op)
 {
        unsigned long base = op->resource[0].start;
        unsigned long config = op->resource[1].start;
@@ -192,7 +192,7 @@ out_err:
        return err;
 }
 
-static int __devexit ecpp_remove(struct platform_device *op)
+static int ecpp_remove(struct platform_device *op)
 {
        struct parport *p = dev_get_drvdata(&op->dev);
        int slot = p->dma;
@@ -242,7 +242,7 @@ static struct platform_driver ecpp_driver = {
                .of_match_table = ecpp_match,
        },
        .probe                  = ecpp_probe,
-       .remove                 = __devexit_p(ecpp_remove),
+       .remove                 = ecpp_remove,
 };
 
 static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
index 7870be0f5adc4d922c21874f06af9bedacc2dfd2..08fcce90316b36654dea14af5525a94a0cded6e8 100644 (file)
@@ -71,7 +71,6 @@
 #define PMD_PADDR      _AC(0xfffffffe,UL)
 #define PMD_PADDR_SHIFT        _AC(11,UL)
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define PMD_ISHUGE     _AC(0x00000001,UL)
 
 /* This is the PMD layout when PMD_ISHUGE is set.  With 4MB huge
@@ -86,7 +85,6 @@
 #define PMD_HUGE_ACCESSED      _AC(0x00000080,UL)
 #define PMD_HUGE_EXEC          _AC(0x00000040,UL)
 #define PMD_HUGE_SPLITTING     _AC(0x00000020,UL)
-#endif
 
 /* PGDs point to PMD tables which are 8K aligned.  */
 #define PGD_PADDR      _AC(0xfffffffc,UL)
@@ -628,6 +626,12 @@ static inline unsigned long pte_special(pte_t pte)
        return pte_val(pte) & _PAGE_SPECIAL;
 }
 
+static inline int pmd_large(pmd_t pmd)
+{
+       return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
+               (PMD_ISHUGE | PMD_HUGE_PRESENT);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline int pmd_young(pmd_t pmd)
 {
@@ -646,12 +650,6 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
        return val >> (PAGE_SHIFT - PMD_PADDR_SHIFT);
 }
 
-static inline int pmd_large(pmd_t pmd)
-{
-       return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
-               (PMD_ISHUGE | PMD_HUGE_PRESENT);
-}
-
 static inline int pmd_trans_splitting(pmd_t pmd)
 {
        return (pmd_val(pmd) & (PMD_ISHUGE|PMD_HUGE_SPLITTING)) ==
index ef3c3682debfde331bed231af7e7466ad070d7a4..01197d8215c4c87c61a40f11f20618ae8dd0a126 100644 (file)
@@ -24,7 +24,7 @@ struct sparc64_tick_ops {
 extern struct sparc64_tick_ops *tick_ops;
 
 extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
-extern void __devinit setup_sparc64_timer(void);
+extern void setup_sparc64_timer(void);
 extern void __init time_init(void);
 
 #endif /* _SPARC64_TIMER_H */
index 497386a7ed28d754e5efcc2a5c9d530e8cb56142..87ce24c5eb95a479d35f5709b3d85f1bbf4c3076 100644 (file)
@@ -47,7 +47,6 @@
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
-#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 1a041892538f6e4a077021ad133515a9175f92d8..c4ffd6c971069cd19e2bfc2b1058c364bef44713 100644 (file)
@@ -147,12 +147,6 @@ struct sigstack {
 #define SIG_UNBLOCK        0x02        /* for unblocking signals */
 #define SIG_SETMASK        0x04        /* for setting the signal mask */
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    4096
 #define SIGSTKSZ       16384
 
index cac719d1bc5c6b8238ff0b6be5f34bc166980534..62ced589bcf78f1554bcadd4f420fad19c7ebcc1 100644 (file)
 #define __NR_process_vm_writev 339
 #define __NR_kern_features     340
 #define __NR_kcmp              341
+#define __NR_finit_module      342
 
-#define NR_syscalls            342
+#define NR_syscalls            343
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index 812e10bbb0b332cf648f747884f93d1b3bc22073..348fa1aeabce586fd16ff03fcc89689d20358683 100644 (file)
@@ -31,7 +31,7 @@
 #define APC_DEVNAME "apc"
 
 static u8 __iomem *regs;
-static int apc_no_idle __devinitdata = 0;
+static int apc_no_idle = 0;
 
 #define apc_readb(offs)                (sbus_readb(regs+offs))
 #define apc_writeb(val, offs)  (sbus_writeb(val, regs+offs))
@@ -138,7 +138,7 @@ static const struct file_operations apc_fops = {
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
 
-static int __devinit apc_probe(struct platform_device *op)
+static int apc_probe(struct platform_device *op)
 {
        int err;
 
index 773091ac71a31e0ddf9e9e1df63f98d40c6bb222..86e55778e4afa4b68eecfca79628cab52c34cc83 100644 (file)
@@ -102,7 +102,7 @@ static const struct of_device_id auxio_match[] = {
 
 MODULE_DEVICE_TABLE(of, auxio_match);
 
-static int __devinit auxio_probe(struct platform_device *dev)
+static int auxio_probe(struct platform_device *dev)
 {
        struct device_node *dp = dev->dev.of_node;
        unsigned long size;
index 9708851a8b9f3c8a46baaebf708330fcc73a05ed..052b5a44318fd0b4b10c8a5af7e4db5b3c8e12c9 100644 (file)
@@ -33,7 +33,7 @@ struct fhc {
        struct platform_device  leds_pdev;
 };
 
-static int __devinit clock_board_calc_nslots(struct clock_board *p)
+static int clock_board_calc_nslots(struct clock_board *p)
 {
        u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0;
 
@@ -60,7 +60,7 @@ static int __devinit clock_board_calc_nslots(struct clock_board *p)
        }
 }
 
-static int __devinit clock_board_probe(struct platform_device *op)
+static int clock_board_probe(struct platform_device *op)
 {
        struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
        int err = -ENOMEM;
@@ -157,7 +157,7 @@ static struct platform_driver clock_board_driver = {
        },
 };
 
-static int __devinit fhc_probe(struct platform_device *op)
+static int fhc_probe(struct platform_device *op)
 {
        struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
        int err = -ENOMEM;
index 5f450260981dd3f564db36387b8e80b817b36986..dbb210d74e21962e58cb5a46ac1ab04fd8c3b1d7 100644 (file)
@@ -336,9 +336,9 @@ static int jbusmc_print_dimm(int syndrome_code,
        return 0;
 }
 
-static u64 __devinit jbusmc_dimm_group_size(u64 base,
-                                           const struct linux_prom64_registers *mem_regs,
-                                           int num_mem_regs)
+static u64 jbusmc_dimm_group_size(u64 base,
+                                 const struct linux_prom64_registers *mem_regs,
+                                 int num_mem_regs)
 {
        u64 max = base + (8UL * 1024 * 1024 * 1024);
        u64 max_seen = base;
@@ -363,10 +363,10 @@ static u64 __devinit jbusmc_dimm_group_size(u64 base,
        return max_seen - base;
 }
 
-static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p,
-                                                     unsigned long index,
-                                                     const struct linux_prom64_registers *mem_regs,
-                                                     int num_mem_regs)
+static void jbusmc_construct_one_dimm_group(struct jbusmc *p,
+                                           unsigned long index,
+                                           const struct linux_prom64_registers *mem_regs,
+                                           int num_mem_regs)
 {
        struct jbusmc_dimm_group *dp = &p->dimm_groups[index];
 
@@ -378,9 +378,9 @@ static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p,
        dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs);
 }
 
-static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p,
-                                                  const struct linux_prom64_registers *mem_regs,
-                                                  int num_mem_regs)
+static void jbusmc_construct_dimm_groups(struct jbusmc *p,
+                                        const struct linux_prom64_registers *mem_regs,
+                                        int num_mem_regs)
 {
        if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) {
                jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs);
@@ -392,7 +392,7 @@ static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p,
        }
 }
 
-static int __devinit jbusmc_probe(struct platform_device *op)
+static int jbusmc_probe(struct platform_device *op)
 {
        const struct linux_prom64_registers *mem_regs;
        struct device_node *mem_node;
@@ -689,7 +689,7 @@ static void chmc_fetch_decode_regs(struct chmc *p)
                                      chmc_read_mcreg(p, CHMCTRL_DECODE4));
 }
 
-static int __devinit chmc_probe(struct platform_device *op)
+static int chmc_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        unsigned long ver;
@@ -763,7 +763,7 @@ out_free:
        goto out;
 }
 
-static int __devinit us3mc_probe(struct platform_device *op)
+static int us3mc_probe(struct platform_device *op)
 {
        if (mc_type == MC_TYPE_SAFARI)
                return chmc_probe(op);
@@ -772,21 +772,21 @@ static int __devinit us3mc_probe(struct platform_device *op)
        return -ENODEV;
 }
 
-static void __devexit chmc_destroy(struct platform_device *op, struct chmc *p)
+static void chmc_destroy(struct platform_device *op, struct chmc *p)
 {
        list_del(&p->list);
        of_iounmap(&op->resource[0], p->regs, 0x48);
        kfree(p);
 }
 
-static void __devexit jbusmc_destroy(struct platform_device *op, struct jbusmc *p)
+static void jbusmc_destroy(struct platform_device *op, struct jbusmc *p)
 {
        mc_list_del(&p->list);
        of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE);
        kfree(p);
 }
 
-static int __devexit us3mc_remove(struct platform_device *op)
+static int us3mc_remove(struct platform_device *op)
 {
        void *p = dev_get_drvdata(&op->dev);
 
@@ -814,7 +814,7 @@ static struct platform_driver us3mc_driver = {
                .of_match_table = us3mc_match,
        },
        .probe          = us3mc_probe,
-       .remove         = __devexit_p(us3mc_remove),
+       .remove         = us3mc_remove,
 };
 
 static inline bool us3mc_platform(void)
index f09257c86107c0c64cf58076a9204d1d79bb697c..75bb608c423eacb459321c5628ee45d6ce769ba6 100644 (file)
@@ -29,7 +29,7 @@
 #define DRV_MODULE_VERSION     "1.0"
 #define DRV_MODULE_RELDATE     "Jul 11, 2007"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_DESCRIPTION("Sun LDOM domain services driver");
@@ -1146,8 +1146,7 @@ static void ds_event(void *arg, int event)
        spin_unlock_irqrestore(&ds_lock, flags);
 }
 
-static int __devinit ds_probe(struct vio_dev *vdev,
-                             const struct vio_device_id *id)
+static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 {
        static int ds_version_printed;
        struct ldc_channel_config ds_cfg = {
index 81d92fc9983b1c0244ab395b7dd81c6725d20d26..9fcc6b4e93b35832b2fe7ad88a4086552a722be9 100644 (file)
@@ -27,7 +27,7 @@
 #define DRV_MODULE_VERSION     "1.1"
 #define DRV_MODULE_RELDATE     "July 22, 2008"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 #define LDC_PACKET_SIZE                64
 
index fc05211615685a787ab0a38aa80fe067db105068..852dc843052861f12ca4ee1ca3a03252e6efec68 100644 (file)
@@ -43,7 +43,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
        }
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
+void pcibios_fixup_bus(struct pci_bus *pbus)
 {
        struct pci_dev *dev;
        int i, has_io, has_mem;
index b1bc38853a3da82200dfacb5c5b0a2439c9ac4b8..fc4320886a3aa5d15f817075cfca261487d21438 100644 (file)
@@ -668,7 +668,7 @@ static irqreturn_t grpci2_err_interrupt(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static int __devinit grpci2_of_probe(struct platform_device *ofdev)
+static int grpci2_of_probe(struct platform_device *ofdev)
 {
        struct grpci2_regs *regs;
        struct grpci2_priv *priv;
index 75b31bcdeadf46c89afdd04eb778718d0f09541e..baf4366e2d6afe937db5fe792c3183d56da4c580 100644 (file)
@@ -356,7 +356,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
        return dev;
 }
 
-static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
+static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 {
        u32 idx, first, last;
 
@@ -378,9 +378,9 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
-static void __devinit apb_fake_ranges(struct pci_dev *dev,
-                                     struct pci_bus *bus,
-                                     struct pci_pbm_info *pbm)
+static void apb_fake_ranges(struct pci_dev *dev,
+                           struct pci_bus *bus,
+                           struct pci_pbm_info *pbm)
 {
        struct pci_bus_region region;
        struct resource *res;
@@ -404,15 +404,15 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev,
        pcibios_bus_to_resource(dev, res, &region);
 }
 
-static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
-                                     struct device_node *node,
-                                     struct pci_bus *bus);
+static void pci_of_scan_bus(struct pci_pbm_info *pbm,
+                           struct device_node *node,
+                           struct pci_bus *bus);
 
 #define GET_64BIT(prop, i)     ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
-static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
-                                        struct device_node *node,
-                                        struct pci_dev *dev)
+static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
+                              struct device_node *node,
+                              struct pci_dev *dev)
 {
        struct pci_bus *bus;
        const u32 *busrange, *ranges;
@@ -503,9 +503,9 @@ after_ranges:
        pci_of_scan_bus(pbm, node, bus);
 }
 
-static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
-                                     struct device_node *node,
-                                     struct pci_bus *bus)
+static void pci_of_scan_bus(struct pci_pbm_info *pbm,
+                           struct device_node *node,
+                           struct pci_bus *bus)
 {
        struct device_node *child;
        const u32 *reg;
@@ -564,7 +564,7 @@ show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char *
 
 static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL);
 
-static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
+static void pci_bus_register_of_sysfs(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        struct pci_bus *child_bus;
@@ -585,8 +585,8 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
                pci_bus_register_of_sysfs(child_bus);
 }
 
-struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
-                                           struct device *parent)
+struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
+                                struct device *parent)
 {
        LIST_HEAD(resources);
        struct device_node *node = pbm->op->dev.of_node;
@@ -618,7 +618,7 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
        return bus;
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
+void pcibios_fixup_bus(struct pci_bus *pbus)
 {
 }
 
@@ -949,8 +949,7 @@ static int __init pcibios_init(void)
 subsys_initcall(pcibios_init);
 
 #ifdef CONFIG_SYSFS
-static void __devinit pci_bus_slot_names(struct device_node *node,
-                                        struct pci_bus *bus)
+static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
 {
        const struct pci_slot_names {
                u32     slot_mask;
index 188f935276fd75c407dc162c53fe06ffe58cfe3d..e60fc6a67e9be7c98e03dca18eeb247d1bc6d419 100644 (file)
@@ -408,8 +408,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
        upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB);
 }
 
-static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm,
-                                      struct platform_device *op, u32 portid)
+static int pci_fire_pbm_init(struct pci_pbm_info *pbm,
+                            struct platform_device *op, u32 portid)
 {
        const struct linux_prom64_registers *regs;
        struct device_node *dp = op->dev.of_node;
@@ -454,7 +454,7 @@ static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm,
        return 0;
 }
 
-static int __devinit fire_probe(struct platform_device *op)
+static int fire_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct pci_pbm_info *pbm;
index f4d29e15ce715c4fb1c476dc3eec780e148835fb..c647634ead2bc9e0eab04f6d9558579b93990f75 100644 (file)
@@ -366,8 +366,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void __devinit psycho_scan_bus(struct pci_pbm_info *pbm,
-                                     struct device *parent)
+static void psycho_scan_bus(struct pci_pbm_info *pbm,
+                           struct device *parent)
 {
        pbm_config_busmastering(pbm);
        pbm->is_66mhz_capable = 0;
@@ -483,15 +483,15 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm,
 #define PSYCHO_MEMSPACE_B      0x180000000UL
 #define PSYCHO_MEMSPACE_SIZE   0x07fffffffUL
 
-static void __devinit psycho_pbm_init(struct pci_pbm_info *pbm,
-                                     struct platform_device *op, int is_pbm_a)
+static void psycho_pbm_init(struct pci_pbm_info *pbm,
+                           struct platform_device *op, int is_pbm_a)
 {
        psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO);
        psycho_pbm_strbuf_init(pbm, is_pbm_a);
        psycho_scan_bus(pbm, &op->dev);
 }
 
-static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid)
+static struct pci_pbm_info *psycho_find_sibling(u32 upa_portid)
 {
        struct pci_pbm_info *pbm;
 
@@ -504,7 +504,7 @@ static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid)
 
 #define PSYCHO_CONFIGSPACE     0x001000000UL
 
-static int __devinit psycho_probe(struct platform_device *op)
+static int psycho_probe(struct platform_device *op)
 {
        const struct linux_prom64_registers *pr_regs;
        struct device_node *dp = op->dev.of_node;
index 3efaa4644d600e4aea88c0867df05ae1baee6008..6f00d27e8dacb348283df0f1b30f00b5755de6d9 100644 (file)
@@ -403,8 +403,7 @@ static void apb_init(struct pci_bus *sabre_bus)
        }
 }
 
-static void __devinit sabre_scan_bus(struct pci_pbm_info *pbm,
-                                    struct device *parent)
+static void sabre_scan_bus(struct pci_pbm_info *pbm, struct device *parent)
 {
        static int once;
 
@@ -443,8 +442,8 @@ static void __devinit sabre_scan_bus(struct pci_pbm_info *pbm,
        sabre_register_error_handlers(pbm);
 }
 
-static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
-                                    struct platform_device *op)
+static void sabre_pbm_init(struct pci_pbm_info *pbm,
+                          struct platform_device *op)
 {
        psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE);
        pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR;
@@ -454,7 +453,7 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
 }
 
 static const struct of_device_id sabre_match[];
-static int __devinit sabre_probe(struct platform_device *op)
+static int sabre_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
        const struct linux_prom64_registers *pr_regs;
index 13d4aa20b5a5d7f16a6da42fdce1b7e5825eec23..8f76f23dac38ec66b0afea55a5311e612f2459f0 100644 (file)
@@ -1064,8 +1064,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm,
-                                     struct device *parent)
+static void schizo_scan_bus(struct pci_pbm_info *pbm, struct device *parent)
 {
        pbm_config_busmastering(pbm);
        pbm->is_66mhz_capable =
@@ -1307,9 +1306,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
        }
 }
 
-static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
-                                    struct platform_device *op, u32 portid,
-                                    int chip_type)
+static int schizo_pbm_init(struct pci_pbm_info *pbm,
+                          struct platform_device *op, u32 portid,
+                          int chip_type)
 {
        const struct linux_prom64_registers *regs;
        struct device_node *dp = op->dev.of_node;
@@ -1400,8 +1399,7 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
        return (x == y);
 }
 
-static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid,
-                                                          int chip_type)
+static struct pci_pbm_info *schizo_find_sibling(u32 portid, int chip_type)
 {
        struct pci_pbm_info *pbm;
 
@@ -1412,7 +1410,7 @@ static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid,
        return NULL;
 }
 
-static int __devinit __schizo_init(struct platform_device *op, unsigned long chip_type)
+static int __schizo_init(struct platform_device *op, unsigned long chip_type)
 {
        struct device_node *dp = op->dev.of_node;
        struct pci_pbm_info *pbm;
@@ -1460,7 +1458,7 @@ out_err:
 }
 
 static const struct of_device_id schizo_match[];
-static int __devinit schizo_probe(struct platform_device *op)
+static int schizo_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
 
index 051b69caeffd382b9252a3986154bb8250b3f87d..d07f6b29aed88510f1625d90655a4fbd10159b4c 100644 (file)
@@ -536,8 +536,7 @@ static struct dma_map_ops sun4v_dma_ops = {
        .unmap_sg                       = dma_4v_unmap_sg,
 };
 
-static void __devinit pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
-                                        struct device *parent)
+static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm, struct device *parent)
 {
        struct property *prop;
        struct device_node *dp;
@@ -550,8 +549,8 @@ static void __devinit pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
        /* XXX register error interrupt handlers XXX */
 }
 
-static unsigned long __devinit probe_existing_entries(struct pci_pbm_info *pbm,
-                                                     struct iommu *iommu)
+static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
+                                           struct iommu *iommu)
 {
        struct iommu_arena *arena = &iommu->arena;
        unsigned long i, cnt = 0;
@@ -578,7 +577,7 @@ static unsigned long __devinit probe_existing_entries(struct pci_pbm_info *pbm,
        return cnt;
 }
 
-static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
+static int pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
        static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
        struct iommu *iommu = pbm->iommu;
@@ -879,8 +878,8 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
-static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
-                                       struct platform_device *op, u32 devhandle)
+static int pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
+                             struct platform_device *op, u32 devhandle)
 {
        struct device_node *dp = op->dev.of_node;
        int err;
@@ -919,7 +918,7 @@ static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
        return 0;
 }
 
-static int __devinit pci_sun4v_probe(struct platform_device *op)
+static int pci_sun4v_probe(struct platform_device *op)
 {
        const struct linux_prom64_registers *regs;
        static int hvapi_negotiated = 0;
index 521fdf1b20e592e06f9776c85e04b3a575019b0e..09f4fdd8d8080fd45f8795a193b9b308c5d748cc 100644 (file)
@@ -439,8 +439,7 @@ int pcic_present(void)
        return pcic0_up;
 }
 
-static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm,
-                                   struct pci_dev *pdev)
+static int pdev_to_pnode(struct linux_pbm_info *pbm, struct pci_dev *pdev)
 {
        struct linux_prom_pci_registers regs[PROMREG_MAX];
        int err;
@@ -595,7 +594,7 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
 /*
  * Normally called from {do_}pci_scan_bus...
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        int i, has_io, has_mem;
index 0e3202239ff5b7b1e13441ca1017fb672c9d33d8..dcbb62f63068b53497393a959bfe5b063a014f60 100644 (file)
@@ -52,7 +52,7 @@ static void pmc_swift_idle(void)
 #endif
 }
 
-static int __devinit pmc_probe(struct platform_device *op)
+static int pmc_probe(struct platform_device *op)
 {
        regs = of_ioremap(&op->resource[0], 0,
                          resource_size(&op->resource[0]), PMC_OBPNAME);
index 0d39075063b2d1f82a54c248d036575fdbd4e901..4cb23c41553f1e44f5430d7e85f92c5b0bd70a6f 100644 (file)
@@ -23,7 +23,7 @@ static irqreturn_t power_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit has_button_interrupt(unsigned int irq, struct device_node *dp)
+static int has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
        if (irq == 0xffffffff)
                return 0;
@@ -33,7 +33,7 @@ static int __devinit has_button_interrupt(unsigned int irq, struct device_node *
        return 1;
 }
 
-static int __devinit power_probe(struct platform_device *op)
+static int power_probe(struct platform_device *op)
 {
        struct resource *res = &op->resource[0];
        unsigned int irq = op->archdata.irqs[0];
index 1271b3a27d4ef4722834d89d16c6ad42373a27d1..be5bdf93c7676cfedffd91d645bffa3fe9cff419 100644 (file)
@@ -554,10 +554,8 @@ static void __init sbus_iommu_init(struct platform_device *op)
        regs = pr->phys_addr;
 
        iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
-       if (!iommu)
-               goto fatal_memory_error;
        strbuf = kzalloc(sizeof(*strbuf), GFP_ATOMIC);
-       if (!strbuf)
+       if (!iommu || !strbuf)
                goto fatal_memory_error;
 
        op->dev.archdata.iommu = iommu;
@@ -656,6 +654,8 @@ static void __init sbus_iommu_init(struct platform_device *op)
        return;
 
 fatal_memory_error:
+       kfree(iommu);
+       kfree(strbuf);
        prom_printf("sbus_iommu_init: Fatal memory allocation error.\n");
 }
 
index d94b878577b7ea34bd674c50ab2817be7d2d93db..537eb66abd0654054aef7402ffaf857ad3971a85 100644 (file)
@@ -1180,7 +1180,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
 {
 }
 
@@ -1194,7 +1194,7 @@ void __init smp_setup_processor_id(void)
                xcall_deliver_impl = hypervisor_xcall_deliver;
 }
 
-void __devinit smp_fill_in_sib_core_maps(void)
+void smp_fill_in_sib_core_maps(void)
 {
        unsigned int i;
 
index 5147f574f1256a7f3304a716da22bfb2ef68d42a..6ac43c36bbbfb98ad769ba6492f66a5fbb2ab554 100644 (file)
@@ -85,4 +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
+/*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module
index cdbd9b817751472200246245e85830b504478a0f..1009ecb92678185a388d708e8b28be070669524d 100644 (file)
@@ -86,7 +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
+/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module
 
 #endif /* CONFIG_COMPAT */
 
@@ -164,4 +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
+/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module
index 953641549e82941e73a3f39b79eaf14e4eb8b0bf..c4c27b0f9063d74f2a2d6dd8963b3753354976ba 100644 (file)
@@ -278,7 +278,7 @@ static struct platform_device m48t59_rtc = {
        },
 };
 
-static int __devinit clock_probe(struct platform_device *op)
+static int clock_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        const char *model = of_get_property(dp, "model", NULL);
index e861072b9c52b0cbabcc84f9af3d3e525ee35eb1..c3d82b5f54ca8501960d9145990304d5b15e4a3c 100644 (file)
@@ -419,7 +419,7 @@ static struct platform_device rtc_cmos_device = {
        .num_resources  = 1,
 };
 
-static int __devinit rtc_probe(struct platform_device *op)
+static int rtc_probe(struct platform_device *op)
 {
        struct resource *r;
 
@@ -477,7 +477,7 @@ static struct platform_device rtc_bq4802_device = {
        .num_resources  = 1,
 };
 
-static int __devinit bq4802_probe(struct platform_device *op)
+static int bq4802_probe(struct platform_device *op)
 {
 
        printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n",
@@ -534,7 +534,7 @@ static struct platform_device m48t59_rtc = {
        },
 };
 
-static int __devinit mostek_probe(struct platform_device *op)
+static int mostek_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
 
@@ -746,7 +746,7 @@ void __irq_entry timer_interrupt(int irq, struct pt_regs *regs)
        set_irq_regs(old_regs);
 }
 
-void __devinit setup_sparc64_timer(void)
+void setup_sparc64_timer(void)
 {
        struct clock_event_device *sevt;
        unsigned long pstate;
@@ -844,7 +844,7 @@ unsigned long long sched_clock(void)
                >> SPARC64_NSEC_PER_CYC_SHIFT;
 }
 
-int __devinit read_current_timer(unsigned long *timer_val)
+int read_current_timer(unsigned long *timer_val)
 {
        *timer_val = tick_ops->get_tick();
        return 0;
index 42c55df3aec300b5baee79e6af5123ab99c7b126..01ee23dd724d5812b7993245b8bcb15bb0a00a7a 100644 (file)
@@ -66,6 +66,56 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
        return 1;
 }
 
+static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
+                       unsigned long end, int write, struct page **pages,
+                       int *nr)
+{
+       struct page *head, *page, *tail;
+       u32 mask;
+       int refs;
+
+       mask = PMD_HUGE_PRESENT;
+       if (write)
+               mask |= PMD_HUGE_WRITE;
+       if ((pmd_val(pmd) & mask) != mask)
+               return 0;
+
+       refs = 0;
+       head = pmd_page(pmd);
+       page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+       tail = page;
+       do {
+               VM_BUG_ON(compound_head(page) != head);
+               pages[*nr] = page;
+               (*nr)++;
+               page++;
+               refs++;
+       } while (addr += PAGE_SIZE, addr != end);
+
+       if (!page_cache_add_speculative(head, refs)) {
+               *nr -= refs;
+               return 0;
+       }
+
+       if (unlikely(pmd_val(pmd) != pmd_val(*pmdp))) {
+               *nr -= refs;
+               while (refs--)
+                       put_page(head);
+               return 0;
+       }
+
+       /* Any tail page need their mapcount reference taken before we
+        * return.
+        */
+       while (refs--) {
+               if (PageTail(tail))
+                       get_huge_page_tail(tail);
+               tail++;
+       }
+
+       return 1;
+}
+
 static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                int write, struct page **pages, int *nr)
 {
@@ -77,9 +127,14 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                pmd_t pmd = *pmdp;
 
                next = pmd_addr_end(addr, end);
-               if (pmd_none(pmd))
+               if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
-               if (!gup_pte_range(pmd, addr, next, write, pages, nr))
+               if (unlikely(pmd_large(pmd))) {
+                       if (!gup_huge_pmd(pmdp, pmd, addr, next,
+                                         write, pages, nr))
+                               return 0;
+               } else if (!gup_pte_range(pmd, addr, next, write,
+                                         pages, nr))
                        return 0;
        } while (pmdp++, addr = next, addr != end);
 
index 85be1ca539b2e4cc5aea5d6fb8b1587fc7a4e73a..c3b72423c846465373e6c06ab961ac99efce4ea6 100644 (file)
@@ -87,8 +87,8 @@ static unsigned long cpu_pgsz_mask;
 
 #define MAX_BANKS      32
 
-static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata;
-static int pavail_ents __devinitdata;
+static struct linux_prom64_registers pavail[MAX_BANKS];
+static int pavail_ents;
 
 static int cmp_p64(const void *a, const void *b)
 {
@@ -1931,7 +1931,7 @@ void __init paging_init(void)
        printk("Booting Linux...\n");
 }
 
-int __devinit page_in_phys_avail(unsigned long paddr)
+int page_in_phys_avail(unsigned long paddr)
 {
        int i;
 
index ea7f61e8bc9e14cf525d6bde75fb909433959372..1bb7ad4aeff4754937bdc09f667110d28348fc96 100644 (file)
@@ -21,8 +21,6 @@ config TILE
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
@@ -142,6 +140,8 @@ config ARCH_DEFCONFIG
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "Tilera-specific configuration"
 
 config NR_CPUS
index 2a9b293fece6c00f2c71d8c5829340bb842970e5..31672918064cf781d9cf0197d812237125c4d8d0 100644 (file)
@@ -250,7 +250,9 @@ static inline void writeq(u64 val, unsigned long addr)
 #define iowrite32 writel
 #define iowrite64 writeq
 
-static inline void memset_io(void *dst, int val, size_t len)
+#if CHIP_HAS_MMIO() || defined(CONFIG_PCI)
+
+static inline void memset_io(volatile void *dst, int val, size_t len)
 {
        int x;
        BUG_ON((unsigned long)dst & 0x3);
@@ -277,6 +279,8 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
                writel(*(u32 *)(src + x), dst + x);
 }
 
+#endif
+
 /*
  * The Tile architecture does not support IOPORT, even with PCI.
  * Unfortunately we can't yet simply not declare these methods,
index b4e96fef2cf8edc0b4931af8edcce502c7bebd4f..241c0bb60b12e5cf4e9eedce50279d648d313e25 100644 (file)
 #include <arch/interrupts.h>
 #include <arch/chip.h>
 
-#if !defined(__tilegx__) && defined(__ASSEMBLY__)
-
 /*
  * The set of interrupts we want to allow when interrupts are nominally
  * disabled.  The remainder are effectively "NMI" interrupts from
  * the point of view of the generic Linux code.  Note that synchronous
  * interrupts (aka "non-queued") are not blocked by the mask in any case.
  */
-#if CHIP_HAS_AUX_PERF_COUNTERS()
-#define LINUX_MASKABLE_INTERRUPTS_HI \
-       (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT)))
-#else
-#define LINUX_MASKABLE_INTERRUPTS_HI \
-       (~(INT_MASK_HI(INT_PERF_COUNT)))
-#endif
-
-#else
-
-#if CHIP_HAS_AUX_PERF_COUNTERS()
-#define LINUX_MASKABLE_INTERRUPTS \
-       (~(INT_MASK(INT_PERF_COUNT) | INT_MASK(INT_AUX_PERF_COUNT)))
-#else
 #define LINUX_MASKABLE_INTERRUPTS \
-       (~(INT_MASK(INT_PERF_COUNT)))
-#endif
+       (~((_AC(1,ULL) << INT_PERF_COUNT) | (_AC(1,ULL) << INT_AUX_PERF_COUNT)))
 
+#if CHIP_HAS_SPLIT_INTR_MASK()
+/* The same macro, but for the two 32-bit SPRs separately. */
+#define LINUX_MASKABLE_INTERRUPTS_LO (-1)
+#define LINUX_MASKABLE_INTERRUPTS_HI \
+       (~((1 << (INT_PERF_COUNT - 32)) | (1 << (INT_AUX_PERF_COUNT - 32))))
 #endif
 
 #ifndef __ASSEMBLY__
  * to know our current state.
  */
 DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
-#define INITIAL_INTERRUPTS_ENABLED INT_MASK(INT_MEM_ERROR)
+#define INITIAL_INTERRUPTS_ENABLED (1ULL << INT_MEM_ERROR)
 
 /* Disable interrupts. */
 #define arch_local_irq_disable() \
@@ -165,7 +153,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 
 /* Prevent the given interrupt from being enabled next time we enable irqs. */
 #define arch_local_irq_mask(interrupt) \
-       (__get_cpu_var(interrupts_enabled_mask) &= ~INT_MASK(interrupt))
+       (__get_cpu_var(interrupts_enabled_mask) &= ~(1ULL << (interrupt)))
 
 /* Prevent the given interrupt from being enabled immediately. */
 #define arch_local_irq_mask_now(interrupt) do { \
@@ -175,7 +163,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 
 /* Allow the given interrupt to be enabled next time we enable irqs. */
 #define arch_local_irq_unmask(interrupt) \
-       (__get_cpu_var(interrupts_enabled_mask) |= INT_MASK(interrupt))
+       (__get_cpu_var(interrupts_enabled_mask) |= (1ULL << (interrupt)))
 
 /* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */
 #define arch_local_irq_unmask_now(interrupt) do { \
@@ -250,7 +238,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 /* Disable interrupts. */
 #define IRQ_DISABLE(tmp0, tmp1)                                        \
        {                                                       \
-        movei  tmp0, -1;                                       \
+        movei  tmp0, LINUX_MASKABLE_INTERRUPTS_LO;             \
         moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS_HI)        \
        };                                                      \
        {                                                       \
index 302cdf71ceed044811731e212f5d499807a38d11..54a924208d3ce5e16ec27615975fcd2e6335c054 100644 (file)
@@ -188,7 +188,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
 int __init tile_pci_init(void);
 int __init pcibios_init(void);
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus);
+void pcibios_fixup_bus(struct pci_bus *bus);
 
 #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
 
index 5ce052e16b7b1ca84c6b65af38362e14d4ea3bbf..2e83fc1b9467d2254f62db982157f3177c89934d 100644 (file)
@@ -35,6 +35,7 @@ typedef unsigned long pt_reg_t;
 
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define user_stack_pointer(regs) ((regs)->sp)
 
 /* Does the process account for user or for system time? */
 #define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL)
index fe841e7d4963e5e88ccdf08193788d535be4da9e..6ac21034f69a695e7d38a5656c80e1bdde0bdfb6 100644 (file)
@@ -17,6 +17,5 @@
 #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
index 96b5710505b6897b98e9eeb9c6f9317173fd2b23..2efe3f68b2d6a80059acd078d53acea552cf4631 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef __ARCH_INTERRUPTS_H__
 #define __ARCH_INTERRUPTS_H__
 
+#ifndef __KERNEL__
 /** Mask for an interrupt. */
 /* Note: must handle breaking interrupts into high and low words manually. */
 #define INT_MASK_LO(intno) (1 << (intno))
@@ -23,6 +24,7 @@
 #ifndef __ASSEMBLER__
 #define INT_MASK(intno) (1ULL << (intno))
 #endif
+#endif
 
 
 /** Where a given interrupt executes */
 
 #ifndef __ASSEMBLER__
 #define QUEUED_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_DMATLB_MISS) | \
-    INT_MASK(INT_DMATLB_ACCESS) | \
-    INT_MASK(INT_SNITLB_MISS) | \
-    INT_MASK(INT_SN_NOTIFY) | \
-    INT_MASK(INT_SN_FIREWALL) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_DMA_NOTIFY) | \
-    INT_MASK(INT_IDN_CA) | \
-    INT_MASK(INT_UDN_CA) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DMA_ASID) | \
-    INT_MASK(INT_SNI_ASID) | \
-    INT_MASK(INT_DMA_CPL) | \
-    INT_MASK(INT_SN_CPL) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_DMATLB_MISS) | \
+    (1ULL << INT_DMATLB_ACCESS) | \
+    (1ULL << INT_SNITLB_MISS) | \
+    (1ULL << INT_SN_NOTIFY) | \
+    (1ULL << INT_SN_FIREWALL) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_DMA_NOTIFY) | \
+    (1ULL << INT_IDN_CA) | \
+    (1ULL << INT_UDN_CA) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DMA_ASID) | \
+    (1ULL << INT_SNI_ASID) | \
+    (1ULL << INT_DMA_CPL) | \
+    (1ULL << INT_SN_CPL) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
     0)
 #define NONQUEUED_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_SN_ACCESS) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_IDN_REFILL) | \
-    INT_MASK(INT_UDN_REFILL) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_SN_STATIC_ACCESS) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_SN_ACCESS) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_IDN_REFILL) | \
+    (1ULL << INT_UDN_REFILL) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_SN_STATIC_ACCESS) | \
     0)
 #define CRITICAL_MASKED_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_DMATLB_MISS) | \
-    INT_MASK(INT_DMATLB_ACCESS) | \
-    INT_MASK(INT_SNITLB_MISS) | \
-    INT_MASK(INT_SN_NOTIFY) | \
-    INT_MASK(INT_SN_FIREWALL) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_DMA_NOTIFY) | \
-    INT_MASK(INT_IDN_CA) | \
-    INT_MASK(INT_UDN_CA) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_DMATLB_MISS) | \
+    (1ULL << INT_DMATLB_ACCESS) | \
+    (1ULL << INT_SNITLB_MISS) | \
+    (1ULL << INT_SN_NOTIFY) | \
+    (1ULL << INT_SN_FIREWALL) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_DMA_NOTIFY) | \
+    (1ULL << INT_IDN_CA) | \
+    (1ULL << INT_UDN_CA) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
     0)
 #define CRITICAL_UNMASKED_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_SN_ACCESS) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_IDN_REFILL) | \
-    INT_MASK(INT_UDN_REFILL) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DMA_ASID) | \
-    INT_MASK(INT_SNI_ASID) | \
-    INT_MASK(INT_DMA_CPL) | \
-    INT_MASK(INT_SN_CPL) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
-    INT_MASK(INT_SN_STATIC_ACCESS) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_SN_ACCESS) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_IDN_REFILL) | \
+    (1ULL << INT_UDN_REFILL) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DMA_ASID) | \
+    (1ULL << INT_SNI_ASID) | \
+    (1ULL << INT_DMA_CPL) | \
+    (1ULL << INT_SN_CPL) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
+    (1ULL << INT_SN_STATIC_ACCESS) | \
     0)
 #define MASKABLE_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_IDN_REFILL) | \
-    INT_MASK(INT_UDN_REFILL) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_DMATLB_MISS) | \
-    INT_MASK(INT_DMATLB_ACCESS) | \
-    INT_MASK(INT_SNITLB_MISS) | \
-    INT_MASK(INT_SN_NOTIFY) | \
-    INT_MASK(INT_SN_FIREWALL) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_DMA_NOTIFY) | \
-    INT_MASK(INT_IDN_CA) | \
-    INT_MASK(INT_UDN_CA) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_IDN_REFILL) | \
+    (1ULL << INT_UDN_REFILL) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_DMATLB_MISS) | \
+    (1ULL << INT_DMATLB_ACCESS) | \
+    (1ULL << INT_SNITLB_MISS) | \
+    (1ULL << INT_SN_NOTIFY) | \
+    (1ULL << INT_SN_FIREWALL) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_DMA_NOTIFY) | \
+    (1ULL << INT_IDN_CA) | \
+    (1ULL << INT_UDN_CA) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
     0)
 #define UNMASKABLE_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_SN_ACCESS) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DMA_ASID) | \
-    INT_MASK(INT_SNI_ASID) | \
-    INT_MASK(INT_DMA_CPL) | \
-    INT_MASK(INT_SN_CPL) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
-    INT_MASK(INT_SN_STATIC_ACCESS) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_SN_ACCESS) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DMA_ASID) | \
+    (1ULL << INT_SNI_ASID) | \
+    (1ULL << INT_DMA_CPL) | \
+    (1ULL << INT_SN_CPL) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
+    (1ULL << INT_SN_STATIC_ACCESS) | \
     0)
 #define SYNC_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_SN_ACCESS) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_IDN_REFILL) | \
-    INT_MASK(INT_UDN_REFILL) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_SN_STATIC_ACCESS) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_SN_ACCESS) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_IDN_REFILL) | \
+    (1ULL << INT_UDN_REFILL) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_SN_STATIC_ACCESS) | \
     0)
 #define NON_SYNC_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_DMATLB_MISS) | \
-    INT_MASK(INT_DMATLB_ACCESS) | \
-    INT_MASK(INT_SNITLB_MISS) | \
-    INT_MASK(INT_SN_NOTIFY) | \
-    INT_MASK(INT_SN_FIREWALL) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_DMA_NOTIFY) | \
-    INT_MASK(INT_IDN_CA) | \
-    INT_MASK(INT_UDN_CA) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DMA_ASID) | \
-    INT_MASK(INT_SNI_ASID) | \
-    INT_MASK(INT_DMA_CPL) | \
-    INT_MASK(INT_SN_CPL) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_DMATLB_MISS) | \
+    (1ULL << INT_DMATLB_ACCESS) | \
+    (1ULL << INT_SNITLB_MISS) | \
+    (1ULL << INT_SN_NOTIFY) | \
+    (1ULL << INT_SN_FIREWALL) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_DMA_NOTIFY) | \
+    (1ULL << INT_IDN_CA) | \
+    (1ULL << INT_UDN_CA) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DMA_ASID) | \
+    (1ULL << INT_SNI_ASID) | \
+    (1ULL << INT_DMA_CPL) | \
+    (1ULL << INT_SN_CPL) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
     0)
 #endif /* !__ASSEMBLER__ */
 #endif /* !__ARCH_INTERRUPTS_H__ */
index 5bb58b2e4e6f84370d04b6d233c212ddc37ddfad..13c9f91823484bf94b28703c3a3cede1e891c344 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef __ARCH_INTERRUPTS_H__
 #define __ARCH_INTERRUPTS_H__
 
+#ifndef __KERNEL__
 /** Mask for an interrupt. */
 #ifdef __ASSEMBLER__
 /* Note: must handle breaking interrupts into high and low words manually. */
@@ -22,6 +23,7 @@
 #else
 #define INT_MASK(intno) (1ULL << (intno))
 #endif
+#endif
 
 
 /** Where a given interrupt executes */
 
 #ifndef __ASSEMBLER__
 #define QUEUED_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_AUX_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_IPI_3) | \
-    INT_MASK(INT_IPI_2) | \
-    INT_MASK(INT_IPI_1) | \
-    INT_MASK(INT_IPI_0) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_AUX_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_IPI_3) | \
+    (1ULL << INT_IPI_2) | \
+    (1ULL << INT_IPI_1) | \
+    (1ULL << INT_IPI_0) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
     0)
 #define NONQUEUED_INTERRUPTS ( \
-    INT_MASK(INT_SINGLE_STEP_3) | \
-    INT_MASK(INT_SINGLE_STEP_2) | \
-    INT_MASK(INT_SINGLE_STEP_1) | \
-    INT_MASK(INT_SINGLE_STEP_0) | \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_ILL_TRANS) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
+    (1ULL << INT_SINGLE_STEP_3) | \
+    (1ULL << INT_SINGLE_STEP_2) | \
+    (1ULL << INT_SINGLE_STEP_1) | \
+    (1ULL << INT_SINGLE_STEP_0) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_ILL_TRANS) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
     0)
 #define CRITICAL_MASKED_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_SINGLE_STEP_3) | \
-    INT_MASK(INT_SINGLE_STEP_2) | \
-    INT_MASK(INT_SINGLE_STEP_1) | \
-    INT_MASK(INT_SINGLE_STEP_0) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_AUX_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_IPI_3) | \
-    INT_MASK(INT_IPI_2) | \
-    INT_MASK(INT_IPI_1) | \
-    INT_MASK(INT_IPI_0) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_SINGLE_STEP_3) | \
+    (1ULL << INT_SINGLE_STEP_2) | \
+    (1ULL << INT_SINGLE_STEP_1) | \
+    (1ULL << INT_SINGLE_STEP_0) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_AUX_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_IPI_3) | \
+    (1ULL << INT_IPI_2) | \
+    (1ULL << INT_IPI_1) | \
+    (1ULL << INT_IPI_0) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
     0)
 #define CRITICAL_UNMASKED_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_ILL_TRANS) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_ILL_TRANS) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
     0)
 #define MASKABLE_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_SINGLE_STEP_3) | \
-    INT_MASK(INT_SINGLE_STEP_2) | \
-    INT_MASK(INT_SINGLE_STEP_1) | \
-    INT_MASK(INT_SINGLE_STEP_0) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_AUX_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_IPI_3) | \
-    INT_MASK(INT_IPI_2) | \
-    INT_MASK(INT_IPI_1) | \
-    INT_MASK(INT_IPI_0) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_SINGLE_STEP_3) | \
+    (1ULL << INT_SINGLE_STEP_2) | \
+    (1ULL << INT_SINGLE_STEP_1) | \
+    (1ULL << INT_SINGLE_STEP_0) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_AUX_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_IPI_3) | \
+    (1ULL << INT_IPI_2) | \
+    (1ULL << INT_IPI_1) | \
+    (1ULL << INT_IPI_0) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
     0)
 #define UNMASKABLE_INTERRUPTS ( \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_ILL_TRANS) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_ILL_TRANS) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
     0)
 #define SYNC_INTERRUPTS ( \
-    INT_MASK(INT_SINGLE_STEP_3) | \
-    INT_MASK(INT_SINGLE_STEP_2) | \
-    INT_MASK(INT_SINGLE_STEP_1) | \
-    INT_MASK(INT_SINGLE_STEP_0) | \
-    INT_MASK(INT_IDN_COMPLETE) | \
-    INT_MASK(INT_UDN_COMPLETE) | \
-    INT_MASK(INT_ITLB_MISS) | \
-    INT_MASK(INT_ILL) | \
-    INT_MASK(INT_GPV) | \
-    INT_MASK(INT_IDN_ACCESS) | \
-    INT_MASK(INT_UDN_ACCESS) | \
-    INT_MASK(INT_SWINT_3) | \
-    INT_MASK(INT_SWINT_2) | \
-    INT_MASK(INT_SWINT_1) | \
-    INT_MASK(INT_SWINT_0) | \
-    INT_MASK(INT_ILL_TRANS) | \
-    INT_MASK(INT_UNALIGN_DATA) | \
-    INT_MASK(INT_DTLB_MISS) | \
-    INT_MASK(INT_DTLB_ACCESS) | \
+    (1ULL << INT_SINGLE_STEP_3) | \
+    (1ULL << INT_SINGLE_STEP_2) | \
+    (1ULL << INT_SINGLE_STEP_1) | \
+    (1ULL << INT_SINGLE_STEP_0) | \
+    (1ULL << INT_IDN_COMPLETE) | \
+    (1ULL << INT_UDN_COMPLETE) | \
+    (1ULL << INT_ITLB_MISS) | \
+    (1ULL << INT_ILL) | \
+    (1ULL << INT_GPV) | \
+    (1ULL << INT_IDN_ACCESS) | \
+    (1ULL << INT_UDN_ACCESS) | \
+    (1ULL << INT_SWINT_3) | \
+    (1ULL << INT_SWINT_2) | \
+    (1ULL << INT_SWINT_1) | \
+    (1ULL << INT_SWINT_0) | \
+    (1ULL << INT_ILL_TRANS) | \
+    (1ULL << INT_UNALIGN_DATA) | \
+    (1ULL << INT_DTLB_MISS) | \
+    (1ULL << INT_DTLB_ACCESS) | \
     0)
 #define NON_SYNC_INTERRUPTS ( \
-    INT_MASK(INT_MEM_ERROR) | \
-    INT_MASK(INT_IDN_FIREWALL) | \
-    INT_MASK(INT_UDN_FIREWALL) | \
-    INT_MASK(INT_TILE_TIMER) | \
-    INT_MASK(INT_AUX_TILE_TIMER) | \
-    INT_MASK(INT_IDN_TIMER) | \
-    INT_MASK(INT_UDN_TIMER) | \
-    INT_MASK(INT_IDN_AVAIL) | \
-    INT_MASK(INT_UDN_AVAIL) | \
-    INT_MASK(INT_IPI_3) | \
-    INT_MASK(INT_IPI_2) | \
-    INT_MASK(INT_IPI_1) | \
-    INT_MASK(INT_IPI_0) | \
-    INT_MASK(INT_PERF_COUNT) | \
-    INT_MASK(INT_AUX_PERF_COUNT) | \
-    INT_MASK(INT_INTCTRL_3) | \
-    INT_MASK(INT_INTCTRL_2) | \
-    INT_MASK(INT_INTCTRL_1) | \
-    INT_MASK(INT_INTCTRL_0) | \
-    INT_MASK(INT_BOOT_ACCESS) | \
-    INT_MASK(INT_WORLD_ACCESS) | \
-    INT_MASK(INT_I_ASID) | \
-    INT_MASK(INT_D_ASID) | \
-    INT_MASK(INT_DOUBLE_FAULT) | \
+    (1ULL << INT_MEM_ERROR) | \
+    (1ULL << INT_IDN_FIREWALL) | \
+    (1ULL << INT_UDN_FIREWALL) | \
+    (1ULL << INT_TILE_TIMER) | \
+    (1ULL << INT_AUX_TILE_TIMER) | \
+    (1ULL << INT_IDN_TIMER) | \
+    (1ULL << INT_UDN_TIMER) | \
+    (1ULL << INT_IDN_AVAIL) | \
+    (1ULL << INT_UDN_AVAIL) | \
+    (1ULL << INT_IPI_3) | \
+    (1ULL << INT_IPI_2) | \
+    (1ULL << INT_IPI_1) | \
+    (1ULL << INT_IPI_0) | \
+    (1ULL << INT_PERF_COUNT) | \
+    (1ULL << INT_AUX_PERF_COUNT) | \
+    (1ULL << INT_INTCTRL_3) | \
+    (1ULL << INT_INTCTRL_2) | \
+    (1ULL << INT_INTCTRL_1) | \
+    (1ULL << INT_INTCTRL_0) | \
+    (1ULL << INT_BOOT_ACCESS) | \
+    (1ULL << INT_WORLD_ACCESS) | \
+    (1ULL << INT_I_ASID) | \
+    (1ULL << INT_D_ASID) | \
+    (1ULL << INT_DOUBLE_FAULT) | \
     0)
 #endif /* !__ASSEMBLER__ */
 #endif /* !__ARCH_INTERRUPTS_H__ */
index 54bc9a6678e8d6b03c319d56b7b5b234f502fb6e..4ea08090265426df8f5f61dbcfaf6a0c92904694 100644 (file)
@@ -1035,7 +1035,9 @@ handle_syscall:
        /* Ensure that the syscall number is within the legal range. */
        {
         moveli r20, hw2(sys_call_table)
+#ifdef CONFIG_COMPAT
         blbs   r30, .Lcompat_syscall
+#endif
        }
        {
         cmpltu r21, TREG_SYSCALL_NR_NAME, r21
@@ -1093,6 +1095,7 @@ handle_syscall:
         j      .Lresume_userspace   /* jump into middle of interrupt_return */
        }
 
+#ifdef CONFIG_COMPAT
 .Lcompat_syscall:
        /*
         * Load the base of the compat syscall table in r20, and
@@ -1117,6 +1120,7 @@ handle_syscall:
        { move r15, r4; addxi r4, r4, 0 }
        { move r16, r5; addxi r5, r5, 0 }
        j .Lload_syscall_pointer
+#endif
 
 .Linvalid_syscall:
        /* Report an invalid syscall back to the user program */
index aac1cd586966e42b9057b1beb3bbd430b9e15a47..67237d34c2e2ad7f8b3b1c43f3f28bfe4d6c1acc 100644 (file)
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
  * controller_id is the controller number, config type is 0 or 1 for
  * config0 or config1 operations.
  */
-static int __devinit tile_pcie_open(int controller_id, int config_type)
+static int tile_pcie_open(int controller_id, int config_type)
 {
        char filename[32];
        int fd;
@@ -97,8 +97,7 @@ static int __devinit tile_pcie_open(int controller_id, int config_type)
 /*
  * Get the IRQ numbers from the HV and set up the handlers for them.
  */
-static int __devinit tile_init_irqs(int controller_id,
-                                struct pci_controller *controller)
+static int tile_init_irqs(int controller_id, struct pci_controller *controller)
 {
        char filename[32];
        int fd;
@@ -237,7 +236,7 @@ static int tile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 }
 
 
-static void __devinit fixup_read_and_payload_sizes(void)
+static void fixup_read_and_payload_sizes(void)
 {
        struct pci_dev *dev = NULL;
        int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */
@@ -379,7 +378,7 @@ subsys_initcall(pcibios_init);
 /*
  * No bus fixups needed.
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        /* Nothing needs to be done. */
 }
@@ -458,11 +457,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
  * specified bus & slot.
  */
 
-static int __devinit tile_cfg_read(struct pci_bus *bus,
-                                  unsigned int devfn,
-                                  int offset,
-                                  int size,
-                                  u32 *val)
+static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset,
+                        int size, u32 *val)
 {
        struct pci_controller *controller = bus->sysdata;
        int busnum = bus->number & 0xff;
@@ -504,11 +500,8 @@ static int __devinit tile_cfg_read(struct pci_bus *bus,
  * See tile_cfg_read() for relevant comments.
  * Note that "val" is the value to write, not a pointer to that value.
  */
-static int __devinit tile_cfg_write(struct pci_bus *bus,
-                                   unsigned int devfn,
-                                   int offset,
-                                   int size,
-                                   u32 val)
+static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset,
+                         int size, u32 val)
 {
        struct pci_controller *controller = bus->sysdata;
        int busnum = bus->number & 0xff;
index 94810d4a63327f418cf21b6b9084da211f6a5df4..11425633b2d7a03e2b04cadf144fbde7efe585cf 100644 (file)
 #define TRACE_CFG_RD(...)
 #endif
 
-static int __devinitdata pci_probe = 1;
+static int pci_probe = 1;
 
 /* Information on the PCIe RC ports configuration. */
-static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+static int pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
 
 /*
  * On some platforms with one or more Gx endpoint ports, we need to
@@ -72,7 +72,7 @@ static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
  * the delay in seconds. If the delay is not provided, the value
  * will be DEFAULT_RC_DELAY.
  */
-static int __devinitdata rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+static int rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
 
 /* Default number of seconds that the PCIe RC port probe can be delayed. */
 #define DEFAULT_RC_DELAY       10
@@ -137,7 +137,7 @@ static int tile_irq_cpu(int irq)
 /*
  * Open a file descriptor to the TRIO shim.
  */
-static int __devinit tile_pcie_open(int trio_index)
+static int tile_pcie_open(int trio_index)
 {
        gxio_trio_context_t *context = &trio_contexts[trio_index];
        int ret;
@@ -265,7 +265,7 @@ trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
  * Create kernel irqs and set up the handlers for the legacy interrupts.
  * Also some minimum initialization for the MSI support.
  */
-static int __devinit tile_init_irqs(struct pci_controller *controller)
+static int tile_init_irqs(struct pci_controller *controller)
 {
        int i;
        int j;
@@ -459,8 +459,7 @@ static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin)
 }
 
 
-static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
-                                               controller)
+static void fixup_read_and_payload_sizes(struct pci_controller *controller)
 {
        gxio_trio_context_t *trio_context = controller->trio;
        struct pci_bus *root_bus = controller->root_bus;
@@ -541,7 +540,7 @@ static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
        }
 }
 
-static int __devinit setup_pcie_rc_delay(char *str)
+static int setup_pcie_rc_delay(char *str)
 {
        unsigned long delay = 0;
        unsigned long trio_index;
@@ -1016,7 +1015,7 @@ alloc_mem_map_failed:
 subsys_initcall(pcibios_init);
 
 /* Note: to be deleted after Linux 3.6 merge. */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
@@ -1024,7 +1023,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
  * This can be called from the generic PCI layer, but doesn't need to
  * do anything.
  */
-char __devinit *pcibios_setup(char *str)
+char *pcibios_setup(char *str)
 {
        if (!strcmp(str, "off")) {
                pci_probe = 0;
@@ -1143,11 +1142,8 @@ EXPORT_SYMBOL(pci_iounmap);
  * specified bus & device.
  */
 
-static int __devinit tile_cfg_read(struct pci_bus *bus,
-                                  unsigned int devfn,
-                                  int offset,
-                                  int size,
-                                  u32 *val)
+static int tile_cfg_read(struct pci_bus *bus, unsigned int devfn, int offset,
+                        int size, u32 *val)
 {
        struct pci_controller *controller = bus->sysdata;
        gxio_trio_context_t *trio_context = controller->trio;
@@ -1271,11 +1267,8 @@ invalid_device:
  * See tile_cfg_read() for relevent comments.
  * Note that "val" is the value to write, not a pointer to that value.
  */
-static int __devinit tile_cfg_write(struct pci_bus *bus,
-                                   unsigned int devfn,
-                                   int offset,
-                                   int size,
-                                   u32 val)
+static int tile_cfg_write(struct pci_bus *bus, unsigned int devfn, int offset,
+                         int size, u32 val)
 {
        struct pci_controller *controller = bus->sysdata;
        gxio_trio_context_t *trio_context = controller->trio;
index 0e5661e7d00d36e770ccebfe752e891fa24e1e6f..caf93ae117930d407bf6a335039817cfdac67408 100644 (file)
@@ -159,7 +159,7 @@ static void save_arch_state(struct thread_struct *t);
 int copy_thread(unsigned long clone_flags, unsigned long sp,
                unsigned long arg, struct task_struct *p)
 {
-       struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs();
+       struct pt_regs *childregs = task_pt_regs(p);
        unsigned long ksp;
        unsigned long *callee_regs;
 
index baa3d905fee21c9fc2ef403449f7e4d671ad7e1e..d1b5c913ae724d4a4f794d0590e263d305a4a58a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/reboot.h>
 #include <linux/smp.h>
 #include <linux/pm.h>
+#include <linux/export.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <hv/hypervisor.h>
@@ -49,3 +50,4 @@ void machine_restart(char *cmd)
 
 /* No interesting distinction to be made here. */
 void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
index 6a649a4462d35ee7b70f0b2305e58bd90028ed87..d1e15f7b59c68ab54ee62a137443270287f59f34 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/timex.h>
 #include <linux/hugetlb.h>
 #include <linux/start_kernel.h>
+#include <linux/screen_info.h>
 #include <asm/setup.h>
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
@@ -49,6 +50,10 @@ static inline int ABS(int x) { return x >= 0 ? x : -x; }
 /* Chip information */
 char chip_model[64] __write_once;
 
+#ifdef CONFIG_VT
+struct screen_info screen_info;
+#endif
+
 struct pglist_data node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
index b2f44c28dda6f29c1867c59464462c63ac427e6a..ed258b8ae320229f401e7f22a9515ab4b6cda954 100644 (file)
@@ -112,7 +112,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
                       p->pc, p->sp, p->ex1);
                p = NULL;
        }
-       if (!kbt->profile || (INT_MASK(p->faultnum) & QUEUED_INTERRUPTS) == 0)
+       if (!kbt->profile || ((1ULL << p->faultnum) & QUEUED_INTERRUPTS) == 0)
                return p;
        return NULL;
 }
@@ -484,6 +484,7 @@ void save_stack_trace(struct stack_trace *trace)
 {
        save_stack_trace_tsk(NULL, trace);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
 
 #endif
 
index db4fb89e12d89a4461b8cc19c99885469fcaf22c..8f8ad814b1398619314b5a26d62695279d4f63f1 100644 (file)
@@ -12,6 +12,7 @@
  *   more details.
  */
 
+#include <linux/export.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 #include <arch/icache.h>
@@ -165,3 +166,4 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
        __insn_mtspr(SPR_DSTREAM_PF, old_dstream_pf);
 #endif
 }
+EXPORT_SYMBOL_GPL(finv_buffer_remote);
index fdc403614d12b1d06a271942b1f846ef3871ac67..75947edccb26625fa8e68fb43fdff54cbd4900f0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/export.h>
 
 /*
  * Allow cropping out bits beyond the end of the array.
@@ -50,3 +51,4 @@ int bitmap_parselist_crop(const char *bp, unsigned long *maskp, int nmaskbits)
        } while (*bp != '\0' && *bp != '\n');
        return 0;
 }
+EXPORT_SYMBOL(bitmap_parselist_crop);
index dd5f0a33fdaff95d6b53efb947fa86880d92d706..4385cb6fa00ade132dc1ba9fb3fda09fbc775151 100644 (file)
@@ -55,6 +55,8 @@ EXPORT_SYMBOL(hv_dev_poll_cancel);
 EXPORT_SYMBOL(hv_dev_close);
 EXPORT_SYMBOL(hv_sysconf);
 EXPORT_SYMBOL(hv_confstr);
+EXPORT_SYMBOL(hv_get_rtc);
+EXPORT_SYMBOL(hv_set_rtc);
 
 /* libgcc.a */
 uint32_t __udivsi3(uint32_t dividend, uint32_t divisor);
index 5f7868dcd6d482abc42e00b6349f5234d0c63c3b..1ae911939a18bdd6050e9a928b099471efeb7599 100644 (file)
@@ -408,6 +408,7 @@ void homecache_change_page_home(struct page *page, int order, int home)
                __set_pte(ptep, pte_set_home(pteval, home));
        }
 }
+EXPORT_SYMBOL(homecache_change_page_home);
 
 struct page *homecache_alloc_pages(gfp_t gfp_mask,
                                   unsigned int order, int home)
index db18eb6124e17d8c36f2e00af8a592230df92bdc..48ccf718e290144c9dce74459dfc765846c93c55 100644 (file)
@@ -132,8 +132,3 @@ long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
        siginitset(&blocked, mask);
        return sigsuspend(&blocked);
 }
-
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
-       return do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs));
-}
index c4fbb21e802b15349e7bfb09d06484b6163169cc..60651df5f95241bb063798df83e0af2545023e76 100644 (file)
@@ -16,8 +16,6 @@ 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
index 726749dab52fff679f6b787ff07498053f75e7e0..9df53d991c7872fba46cf23f3033ccbc3098df77 100644 (file)
@@ -54,6 +54,7 @@ static inline int valid_user_regs(struct pt_regs *regs)
 }
 
 #define instruction_pointer(regs)      ((regs)->UCreg_pc)
+#define user_stack_pointer(regs)       ((regs)->UCreg_sp)
 
 #endif /* __ASSEMBLY__ */
 #endif
index 00cf5e286fcadc1fe584c02ff67e335367db64ec..d4cc4559d8485f23838417c6f51208b4925082d3 100644 (file)
@@ -12,5 +12,4 @@
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
index 7c4359240b8134c409f252c292d0c98dce6b2869..ef69c0c828253991c7b633a22822acc04d333633 100644 (file)
@@ -167,7 +167,7 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev)
  * pcibios_fixup_bus - Called after each bus is probed,
  * but before its children are examined.
  */
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+void pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        u16 features = PCI_COMMAND_SERR
index 97f8c5ad8c2ddff2449da615e46c2faab3b9d067..5e05ee3a9810b3c42cdfdf627db150e5ceaa8c2f 100644 (file)
@@ -1,7 +1,7 @@
 # Select 32 or 64 bit
 config 64BIT
        bool "64-bit kernel" if ARCH = "x86"
-       default ARCH = "x86_64"
+       default ARCH != "i386"
        ---help---
          Say yes to build a 64-bit kernel - formerly known as x86_64
          Say no to build a 32-bit kernel - formerly known as i386
@@ -28,7 +28,6 @@ config X86
        select HAVE_OPROFILE
        select HAVE_PCSPKR_PLATFORM
        select HAVE_PERF_EVENTS
-       select HAVE_IRQ_WORK
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select HAVE_MEMBLOCK
@@ -40,10 +39,12 @@ config X86
        select HAVE_DMA_CONTIGUOUS if !SWIOTLB
        select HAVE_KRETPROBES
        select HAVE_OPTPROBES
+       select HAVE_KPROBES_ON_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_FENTRY if X86_64
        select HAVE_C_RECORDMCOUNT
        select HAVE_DYNAMIC_FTRACE
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_GRAPH_FP_TEST
@@ -106,15 +107,16 @@ config X86
        select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
        select GENERIC_TIME_VSYSCALL if X86_64
        select KTIME_SCALAR if X86_32
+       select ALWAYS_USE_PERSISTENT_CLOCK
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
        select HAVE_IRQ_TIME_ACCOUNTING
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
        select MODULES_USE_ELF_REL if X86_32
        select MODULES_USE_ELF_RELA if X86_64
        select CLONE_BACKWARDS if X86_32
+       select GENERIC_SIGALTSTACK
+       select ARCH_USE_BUILTIN_BSWAP
 
 config INSTRUCTION_DECODER
        def_bool y
@@ -2139,6 +2141,7 @@ config OLPC_XO1_RTC
 config OLPC_XO1_SCI
        bool "OLPC XO-1 SCI extras"
        depends on OLPC && OLPC_XO1_PM
+       depends on INPUT=y
        select POWER_SUPPLY
        select GPIO_CS5535
        select MFD_CORE
index e71fc4279aab62825524bba4357bd3cb3b6e847e..5c477260294f6ef78b1c1de6998b4860cc64ffbb 100644 (file)
@@ -2,7 +2,11 @@
 
 # select defconfig based on actual architecture
 ifeq ($(ARCH),x86)
+  ifeq ($(shell uname -m),x86_64)
+        KBUILD_DEFCONFIG := x86_64_defconfig
+  else
         KBUILD_DEFCONFIG := i386_defconfig
+  endif
 else
         KBUILD_DEFCONFIG := $(ARCH)_defconfig
 endif
index ccce0ed67dde703a80c78309252abbef17828291..379814bc41e3a956dc037a5f1d4ca23709854fbc 100644 (file)
@@ -71,7 +71,7 @@ GCOV_PROFILE := n
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@
 
 $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
@@ -92,7 +92,7 @@ targets += voffset.h
 $(obj)/voffset.h: vmlinux FORCE
        $(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
index b1942e222768e7c9c2707c14dbdbd9643a51a8b9..f8fa41190c3526f61ec7bb6e1dc5b0ebf08b3c4d 100644 (file)
@@ -256,10 +256,10 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
        int i;
        struct setup_data *data;
 
-       data = (struct setup_data *)params->hdr.setup_data;
+       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
 
        while (data && data->next)
-               data = (struct setup_data *)data->next;
+               data = (struct setup_data *)(unsigned long)data->next;
 
        status = efi_call_phys5(sys_table->boottime->locate_handle,
                                EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -295,16 +295,18 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
                if (!pci)
                        continue;
 
+#ifdef CONFIG_X86_64
                status = efi_call_phys4(pci->attributes, pci,
                                        EfiPciIoAttributeOperationGet, 0,
                                        &attributes);
-
+#else
+               status = efi_call_phys5(pci->attributes, pci,
+                                       EfiPciIoAttributeOperationGet, 0, 0,
+                                       &attributes);
+#endif
                if (status != EFI_SUCCESS)
                        continue;
 
-               if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
-                       continue;
-
                if (!pci->romimage || !pci->romsize)
                        continue;
 
@@ -345,9 +347,9 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
                memcpy(rom->romdata, pci->romimage, pci->romsize);
 
                if (data)
-                       data->next = (uint64_t)rom;
+                       data->next = (unsigned long)rom;
                else
-                       params->hdr.setup_data = (uint64_t)rom;
+                       params->hdr.setup_data = (unsigned long)rom;
 
                data = (struct setup_data *)rom;
 
@@ -432,10 +434,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
                         * Once we've found a GOP supporting ConOut,
                         * don't bother looking any further.
                         */
+                       first_gop = gop;
                        if (conout_found)
                                break;
-
-                       first_gop = gop;
                }
        }
 
index aa4aaf1b23803e8ef0e180e3cbeedc7a4db6c556..1e3184f6072f913250b3b18371978a4fd1b3f63d 100644 (file)
@@ -35,11 +35,11 @@ ENTRY(startup_32)
 #ifdef CONFIG_EFI_STUB
        jmp     preferred_addr
 
-       .balign 0x10
        /*
         * We don't need the return address, so set up the stack so
-        * efi_main() can find its arugments.
+        * efi_main() can find its arguments.
         */
+ENTRY(efi_pe_entry)
        add     $0x4, %esp
 
        call    make_boot_params
@@ -50,8 +50,10 @@ ENTRY(startup_32)
        pushl   %eax
        pushl   %esi
        pushl   %ecx
+       sub     $0x4, %esp
 
-       .org 0x30,0x90
+ENTRY(efi_stub_entry)
+       add     $0x4, %esp
        call    efi_main
        cmpl    $0, %eax
        movl    %eax, %esi
index 2c4b171eec337619e8f2dab2b3c3b2048e622e51..f5d1aaa0dec87ce844317f2a343a90739408ac22 100644 (file)
@@ -201,12 +201,12 @@ ENTRY(startup_64)
         */
 #ifdef CONFIG_EFI_STUB
        /*
-        * The entry point for the PE/COFF executable is 0x210, so only
-        * legacy boot loaders will execute this jmp.
+        * The entry point for the PE/COFF executable is efi_pe_entry, so
+        * only legacy boot loaders will execute this jmp.
         */
        jmp     preferred_addr
 
-       .org 0x210
+ENTRY(efi_pe_entry)
        mov     %rcx, %rdi
        mov     %rdx, %rsi
        pushq   %rdi
@@ -218,7 +218,7 @@ ENTRY(startup_64)
        popq    %rsi
        popq    %rdi
 
-       .org 0x230,0x90
+ENTRY(efi_stub_entry)
        call    efi_main
        movq    %rax,%rsi
        cmpq    $0,%rax
index 88f7ff6da40442086b6c6664b227f00f97bf2711..7cb56c6ca35154f19d3a1f4242845f8242a37202 100644 (file)
@@ -325,6 +325,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 {
        real_mode = rmode;
 
+       sanitize_boot_params(real_mode);
+
        if (real_mode->screen_info.orig_video_mode == 7) {
                vidmem = (char *) 0xb0000;
                vidport = 0x3b4;
index 0e6dc0ee0eeabd04fc283bce937b734ea42923c7..674019d8e2355901b69de5c55cfb92669c5628be 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/page.h>
 #include <asm/boot.h>
 #include <asm/bootparam.h>
+#include <asm/bootparam_utils.h>
 
 #define BOOT_BOOT_H
 #include "../ctype.h"
index 8c132a625b94991c179def21973bb8ad3c3a56d5..944ce595f767621f07a47d6c89cdea9415627663 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/e820.h>
 #include <asm/page_types.h>
 #include <asm/setup.h>
+#include <asm/bootparam.h>
 #include "boot.h"
 #include "voffset.h"
 #include "zoffset.h"
@@ -255,6 +256,9 @@ section_table:
        # header, from the old boot sector.
 
        .section ".header", "a"
+       .globl  sentinel
+sentinel:      .byte 0xff, 0xff        /* Used to detect broken loaders */
+
        .globl  hdr
 hdr:
 setup_sects:   .byte 0                 /* Filled in by build.c */
@@ -279,7 +283,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x020b          # header version number (>= 0x0105)
+               .word   0x020c          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -297,13 +301,7 @@ type_of_loader:    .byte   0               # 0 means ancient bootloader, newer
 
 # flags, unused bits must be zero (RFU) bit within loadflags
 loadflags:
-LOADED_HIGH    = 1                     # If set, the kernel is loaded high
-CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
-                                       # heap_end_ptr to tell how much
-                                       # space behind setup.S can be used for
-                                       # heap purposes.
-                                       # Only the loader knows what is free
-               .byte   LOADED_HIGH
+               .byte   LOADED_HIGH     # The kernel is to be loaded high
 
 setup_move_size: .word  0x8000         # size to move, when setup is not
                                        # loaded at 0x90000. We will move setup
@@ -369,7 +367,23 @@ relocatable_kernel:    .byte 1
 relocatable_kernel:    .byte 0
 #endif
 min_alignment:         .byte MIN_KERNEL_ALIGN_LG2      # minimum alignment
-pad3:                  .word 0
+
+xloadflags:
+#ifdef CONFIG_X86_64
+# define XLF0 XLF_KERNEL_64                    /* 64-bit kernel */
+#else
+# define XLF0 0
+#endif
+#ifdef CONFIG_EFI_STUB
+# ifdef CONFIG_X86_64
+#  define XLF23 XLF_EFI_HANDOVER_64            /* 64-bit EFI handover ok */
+# else
+#  define XLF23 XLF_EFI_HANDOVER_32            /* 32-bit EFI handover ok */
+# endif
+#else
+# define XLF23 0
+#endif
+                       .word XLF0 | XLF23
 
 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
                                                 #added with boot protocol
@@ -397,8 +411,13 @@ pref_address:              .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 #define INIT_SIZE VO_INIT_SIZE
 #endif
 init_size:             .long INIT_SIZE         # kernel initialization size
-handover_offset:       .long 0x30              # offset to the handover
+handover_offset:
+#ifdef CONFIG_EFI_STUB
+                       .long 0x30              # offset to the handover
                                                # protocol entry point
+#else
+                       .long 0
+#endif
 
 # End of setup header #####################################################
 
index 03c0683636b6fbf859a8795262f249631e6157f9..96a6c7563538364d2dee7e307846815156c11c33 100644 (file)
@@ -13,7 +13,7 @@ SECTIONS
        .bstext         : { *(.bstext) }
        .bsdata         : { *(.bsdata) }
 
-       . = 497;
+       . = 495;
        .header         : { *(.header) }
        .entrytext      : { *(.entrytext) }
        .inittext       : { *(.inittext) }
index 4b8e165ee5723643dcd89619a341c7559eafe2bd..94c54465002003e34af8f6fb3d14a1be839fdeba 100644 (file)
@@ -52,6 +52,10 @@ int is_big_kernel;
 
 #define PECOFF_RELOC_RESERVE 0x20
 
+unsigned long efi_stub_entry;
+unsigned long efi_pe_entry;
+unsigned long startup_64;
+
 /*----------------------------------------------------------------------*/
 
 static const u32 crctab32[] = {
@@ -132,7 +136,7 @@ static void die(const char * str, ...)
 
 static void usage(void)
 {
-       die("Usage: build setup system [> image]");
+       die("Usage: build setup system [zoffset.h] [> image]");
 }
 
 #ifdef CONFIG_EFI_STUB
@@ -206,30 +210,54 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
         */
        put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
 
-#ifdef CONFIG_X86_32
        /*
-        * Address of entry point.
-        *
-        * The EFI stub entry point is +16 bytes from the start of
-        * the .text section.
+        * Address of entry point for PE/COFF executable
         */
-       put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
-#else
-       /*
-        * Address of entry point. startup_32 is at the beginning and
-        * the 64-bit entry point (startup_64) is always 512 bytes
-        * after. The EFI stub entry point is 16 bytes after that, as
-        * the first instruction allows legacy loaders to jump over
-        * the EFI stub initialisation
-        */
-       put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
-#endif /* CONFIG_X86_32 */
+       put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
 
        update_pecoff_section_header(".text", text_start, text_sz);
 }
 
 #endif /* CONFIG_EFI_STUB */
 
+
+/*
+ * Parse zoffset.h and find the entry points. We could just #include zoffset.h
+ * but that would mean tools/build would have to be rebuilt every time. It's
+ * not as if parsing it is hard...
+ */
+#define PARSE_ZOFS(p, sym) do { \
+       if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))       \
+               sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);         \
+} while (0)
+
+static void parse_zoffset(char *fname)
+{
+       FILE *file;
+       char *p;
+       int c;
+
+       file = fopen(fname, "r");
+       if (!file)
+               die("Unable to open `%s': %m", fname);
+       c = fread(buf, 1, sizeof(buf) - 1, file);
+       if (ferror(file))
+               die("read-error on `zoffset.h'");
+       buf[c] = 0;
+
+       p = (char *)buf;
+
+       while (p && *p) {
+               PARSE_ZOFS(p, efi_stub_entry);
+               PARSE_ZOFS(p, efi_pe_entry);
+               PARSE_ZOFS(p, startup_64);
+
+               p = strchr(p, '\n');
+               while (p && (*p == '\r' || *p == '\n'))
+                       p++;
+       }
+}
+
 int main(int argc, char ** argv)
 {
        unsigned int i, sz, setup_sectors;
@@ -241,7 +269,19 @@ int main(int argc, char ** argv)
        void *kernel;
        u32 crc = 0xffffffffUL;
 
-       if (argc != 3)
+       /* Defaults for old kernel */
+#ifdef CONFIG_X86_32
+       efi_pe_entry = 0x10;
+       efi_stub_entry = 0x30;
+#else
+       efi_pe_entry = 0x210;
+       efi_stub_entry = 0x230;
+       startup_64 = 0x200;
+#endif
+
+       if (argc == 4)
+               parse_zoffset(argv[3]);
+       else if (argc != 3)
                usage();
 
        /* Copy the setup code */
@@ -299,6 +339,11 @@ int main(int argc, char ** argv)
 
 #ifdef CONFIG_EFI_STUB
        update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
+
+#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */
+       efi_stub_entry -= 0x200;
+#endif
+       put_unaligned_le32(efi_stub_entry, &buf[0x264]);
 #endif
 
        crc = partial_crc32(buf, i, crc);
index 5598547281a75a4a0b4fc6a31cfecfcec3540022..94447086e551e3a8b4102a0e46800bc39c7ff172 100644 (file)
@@ -1,3 +1,4 @@
+# CONFIG_64BIT is not set
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
index efc6a958b71d186a25ee4eadd759f886cf8670f7..a1daf4a6500926a1305415a6eb4eaba53db6b31f 100644 (file)
@@ -136,52 +136,6 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
        return sigsuspend(&blocked);
 }
 
-asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
-                                 stack_ia32_t __user *uoss_ptr,
-                                 struct pt_regs *regs)
-{
-       stack_t uss, uoss;
-       int ret, err = 0;
-       mm_segment_t seg;
-
-       if (uss_ptr) {
-               u32 ptr;
-
-               memset(&uss, 0, sizeof(stack_t));
-               if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
-                       return -EFAULT;
-
-               get_user_try {
-                       get_user_ex(ptr, &uss_ptr->ss_sp);
-                       get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
-                       get_user_ex(uss.ss_size, &uss_ptr->ss_size);
-               } get_user_catch(err);
-
-               if (err)
-                       return -EFAULT;
-               uss.ss_sp = compat_ptr(ptr);
-       }
-       seg = get_fs();
-       set_fs(KERNEL_DS);
-       ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
-                            (stack_t __force __user *) &uoss, regs->sp);
-       set_fs(seg);
-       if (ret >= 0 && uoss_ptr)  {
-               if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
-                       return -EFAULT;
-
-               put_user_try {
-                       put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
-                       put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
-                       put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
-               } put_user_catch(err);
-
-               if (err)
-                       ret = -EFAULT;
-       }
-       return ret;
-}
-
 /*
  * Do a signal return; undo the signal stack.
  */
@@ -292,7 +246,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe_ia32 __user *frame;
        sigset_t set;
        unsigned int ax;
-       struct pt_regs tregs;
 
        frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
 
@@ -306,8 +259,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
        if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-       tregs = *regs;
-       if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
+       if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
        return ax;
@@ -515,10 +467,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-               put_user_ex(sas_ss_flags(regs->sp),
-                           &frame->uc.uc_stack.ss_flags);
-               put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
 
                if (ka->sa.sa_flags & SA_RESTORER)
                        restorer = ka->sa.sa_restorer;
index 32e6f05ddaaab84f71d2501c07185776055cf855..142c4ceff1122cadb5dd92ddb0fab05c64f0c48e 100644 (file)
@@ -207,7 +207,7 @@ sysexit_from_sys_call:
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jnz ia32_ret_from_sys_call
        TRACE_IRQS_ON
-       sti
+       ENABLE_INTERRUPTS(CLBR_NONE)
        movl %eax,%esi          /* second arg, syscall return value */
        cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
        jbe 1f
@@ -217,7 +217,7 @@ sysexit_from_sys_call:
        call __audit_syscall_exit
        movq RAX-ARGOFFSET(%rsp),%rax   /* reload syscall return value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
-       cli
+       DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jz \exit
@@ -464,7 +464,6 @@ GLOBAL(\label)
 
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
        PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
-       PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
        PTREGSCALL stub32_execve, compat_sys_execve, %rcx
        PTREGSCALL stub32_fork, sys_fork, %rdi
        PTREGSCALL stub32_vfork, sys_vfork, %rdi
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
new file mode 100644 (file)
index 0000000..5b5e9cb
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _ASM_X86_BOOTPARAM_UTILS_H
+#define _ASM_X86_BOOTPARAM_UTILS_H
+
+#include <asm/bootparam.h>
+
+/*
+ * This file is included from multiple environments.  Do not
+ * add completing #includes to make it standalone.
+ */
+
+/*
+ * Deal with bootloaders which fail to initialize unknown fields in
+ * boot_params to zero.  The list fields in this list are taken from
+ * analysis of kexec-tools; if other broken bootloaders initialize a
+ * different set of fields we will need to figure out how to disambiguate.
+ *
+ */
+static void sanitize_boot_params(struct boot_params *boot_params)
+{
+       if (boot_params->sentinel) {
+               /*fields in boot_params are not valid, clear them */
+               memset(&boot_params->olpc_ofw_header, 0,
+                      (char *)&boot_params->alt_mem_k -
+                       (char *)&boot_params->olpc_ofw_header);
+               memset(&boot_params->kbd_status, 0,
+                      (char *)&boot_params->hdr -
+                      (char *)&boot_params->kbd_status);
+               memset(&boot_params->_pad7[0], 0,
+                      (char *)&boot_params->edd_mbr_sig_buffer[0] -
+                       (char *)&boot_params->_pad7[0]);
+               memset(&boot_params->_pad8[0], 0,
+                      (char *)&boot_params->eddbuf[0] -
+                       (char *)&boot_params->_pad8[0]);
+               memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+       }
+}
+
+#endif /* _ASM_X86_BOOTPARAM_UTILS_H */
index 2d9075e863a0cfc25e43b7d40e706e8016586859..93fe929d1cee20ec1dc183d5c390e5d9325b26ce 100644 (file)
 #define X86_FEATURE_TBM                (6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT    (6*32+22) /* topology extensions CPUID leafs */
 #define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB  (6*32+24) /* NB performance counter extensions */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -309,6 +310,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_hypervisor     boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq      boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core   boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
+#define cpu_has_perfctr_nb     boot_cpu_has(X86_FEATURE_PERFCTR_NB)
 #define cpu_has_cx8            boot_cpu_has(X86_FEATURE_CX8)
 #define cpu_has_cx16           boot_cpu_has(X86_FEATURE_CX16)
 #define cpu_has_eager_fpu      boot_cpu_has(X86_FEATURE_EAGER_FPU)
index 6e8fdf5ad1135c0100c8b7a5220bb79db2359ddb..28677c55113f8cea59e59c67e7cd53cfcd615b6d 100644 (file)
@@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
+extern unsigned long x86_efi_facility;
 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);
index 9a25b522d37799adf0b7a00d898ba30cb70b08b7..86cb51e1ca96abc11dda6317293a775aebbdf51e 100644 (file)
@@ -44,7 +44,6 @@
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 #define ARCH_SUPPORTS_FTRACE_OPS 1
-#define ARCH_SUPPORTS_FTRACE_SAVE_REGS
 #endif
 
 #ifndef __ASSEMBLY__
index 434e2106cc870d48e1f142e60a436f50e04a592a..b18df579c0e99b09ff33261e692135338826de3a 100644 (file)
@@ -80,9 +80,9 @@ extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
 extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
 
 #ifdef CONFIG_PCI_MSI
-extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id);
+extern int default_setup_hpet_msi(unsigned int irq, unsigned int id);
 #else
-static inline int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
+static inline int default_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
        return -EINVAL;
 }
@@ -111,6 +111,7 @@ extern void hpet_unregister_irq_handler(rtc_irq_handler handler);
 static inline int hpet_enable(void) { return 0; }
 static inline int is_hpet_enabled(void) { return 0; }
 #define hpet_readl(a) 0
+#define default_setup_hpet_msi NULL
 
 #endif
 #endif /* _ASM_X86_HPET_H */
index eb92a6ed2be704ace2a935354b4667df75563394..10a78c3d3d5a771d8581a13e402eb69e462e1dae 100644 (file)
@@ -101,6 +101,7 @@ static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
        irq_attr->polarity      = polarity;
 }
 
+/* Intel specific interrupt remapping information */
 struct irq_2_iommu {
        struct intel_iommu *iommu;
        u16 irte_index;
@@ -108,6 +109,12 @@ struct irq_2_iommu {
        u8  irte_mask;
 };
 
+/* AMD specific interrupt remapping information */
+struct irq_2_irte {
+       u16 devid; /* Device ID for IRTE table */
+       u16 index; /* Index into IRTE table*/
+};
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -120,7 +127,11 @@ struct irq_cfg {
        u8                      vector;
        u8                      move_in_progress : 1;
 #ifdef CONFIG_IRQ_REMAP
-       struct irq_2_iommu      irq_2_iommu;
+       u8                      remapped : 1;
+       union {
+               struct irq_2_iommu irq_2_iommu;
+               struct irq_2_irte  irq_2_irte;
+       };
 #endif
 };
 
index b518c7509933337225756646fcbd73a6882c2990..86095ed141356f3210fee6954f80a763df4a5bea 100644 (file)
@@ -25,6 +25,7 @@
 
 extern void init_hypervisor(struct cpuinfo_x86 *c);
 extern void init_hypervisor_platform(void);
+extern bool hypervisor_x2apic_available(void);
 
 /*
  * x86 hypervisor information
@@ -41,6 +42,9 @@ struct hypervisor_x86 {
 
        /* Platform setup (run once per boot) */
        void            (*init_platform)(void);
+
+       /* X2APIC detection (run once per boot) */
+       bool            (*x2apic_available)(void);
 };
 
 extern const struct hypervisor_x86 *x86_hyper;
@@ -51,13 +55,4 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
 
-static inline bool hypervisor_x2apic_available(void)
-{
-       if (kvm_para_available())
-               return true;
-       if (xen_x2apic_para_available())
-               return true;
-       return false;
-}
-
 #endif
index e6232773ce4925dc790a2b6b41152393f80b84a1..4c6da2e4bb1d3e843c057ca40158d39035150273 100644 (file)
@@ -29,16 +29,10 @@ struct old_sigaction32 {
        unsigned int sa_restorer;       /* Another 32 bit pointer */
 };
 
-typedef struct sigaltstack_ia32 {
-       unsigned int    ss_sp;
-       int             ss_flags;
-       unsigned int    ss_size;
-} stack_ia32_t;
-
 struct ucontext_ia32 {
        unsigned int      uc_flags;
        unsigned int      uc_link;
-       stack_ia32_t      uc_stack;
+       compat_stack_t    uc_stack;
        struct sigcontext_ia32 uc_mcontext;
        compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
 };
@@ -46,7 +40,7 @@ struct ucontext_ia32 {
 struct ucontext_x32 {
        unsigned int      uc_flags;
        unsigned int      uc_link;
-       stack_ia32_t      uc_stack;
+       compat_stack_t    uc_stack;
        unsigned int      uc__pad0;     /* needed for alignment */
        struct sigcontext uc_mcontext;  /* the 64-bit sigcontext type */
        compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
index 73d8c5398ea995dd685ad00ad99b17fd69c5c1b4..459e50a424d148eb94163a343cbf17a8b4abfad9 100644 (file)
@@ -144,11 +144,24 @@ extern int timer_through_8259;
        (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
 
 struct io_apic_irq_attr;
+struct irq_cfg;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
                 struct io_apic_irq_attr *irq_attr);
 void setup_IO_APIC_irq_extra(u32 gsi);
 extern void ioapic_insert_resources(void);
 
+extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
+                                    unsigned int, int,
+                                    struct io_apic_irq_attr *);
+extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
+                                    unsigned int, int,
+                                    struct io_apic_irq_attr *);
+extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);
+
+extern void native_compose_msi_msg(struct pci_dev *pdev,
+                                  unsigned int irq, unsigned int dest,
+                                  struct msi_msg *msg, u8 hpet_id);
+extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
 int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
 
 extern int save_ioapic_entries(void);
@@ -179,6 +192,12 @@ extern void __init native_io_apic_init_mappings(void);
 extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
 extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val);
 extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
+extern void native_disable_io_apic(void);
+extern void native_io_apic_print_entries(unsigned int apic, unsigned int nr_entries);
+extern void intel_ir_io_apic_print_entries(unsigned int apic, unsigned int nr_entries);
+extern int native_ioapic_set_affinity(struct irq_data *,
+                                     const struct cpumask *,
+                                     bool);
 
 static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
 {
@@ -193,6 +212,9 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
 {
        x86_io_apic_ops.modify(apic, reg, value);
 }
+
+extern void io_apic_eoi(unsigned int apic, unsigned int vector);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
@@ -223,6 +245,12 @@ static inline void disable_ioapic_support(void) { }
 #define native_io_apic_read            NULL
 #define native_io_apic_write           NULL
 #define native_io_apic_modify          NULL
+#define native_disable_io_apic         NULL
+#define native_io_apic_print_entries   NULL
+#define native_ioapic_set_affinity     NULL
+#define native_setup_ioapic_entry      NULL
+#define native_compose_msi_msg         NULL
+#define native_eoi_ioapic_pin          NULL
 #endif
 
 #endif /* _ASM_X86_IO_APIC_H */
index 5fb9bbbd2f14c0ad07033b067797ed179e1d8fd8..95fd3527f632d2f0b45c47b07bada7fee46effea 100644 (file)
@@ -26,8 +26,6 @@
 
 #ifdef CONFIG_IRQ_REMAP
 
-extern int irq_remapping_enabled;
-
 extern void setup_irq_remapping_ops(void);
 extern int irq_remapping_supported(void);
 extern int irq_remapping_prepare(void);
@@ -40,21 +38,19 @@ extern int setup_ioapic_remapped_entry(int irq,
                                       unsigned int destination,
                                       int vector,
                                       struct io_apic_irq_attr *attr);
-extern int set_remapped_irq_affinity(struct irq_data *data,
-                                    const struct cpumask *mask,
-                                    bool force);
 extern void free_remapped_irq(int irq);
 extern void compose_remapped_msi_msg(struct pci_dev *pdev,
                                     unsigned int irq, unsigned int dest,
                                     struct msi_msg *msg, u8 hpet_id);
-extern int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
-extern int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                                 int index, int sub_handle);
 extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id);
+extern void panic_if_irq_remap(const char *msg);
+extern bool setup_remapped_irq(int irq,
+                              struct irq_cfg *cfg,
+                              struct irq_chip *chip);
 
-#else  /* CONFIG_IRQ_REMAP */
+void irq_remap_modify_chip_defaults(struct irq_chip *chip);
 
-#define irq_remapping_enabled  0
+#else  /* CONFIG_IRQ_REMAP */
 
 static inline void setup_irq_remapping_ops(void) { }
 static inline int irq_remapping_supported(void) { return 0; }
@@ -71,30 +67,30 @@ static inline int setup_ioapic_remapped_entry(int irq,
 {
        return -ENODEV;
 }
-static inline int set_remapped_irq_affinity(struct irq_data *data,
-                                           const struct cpumask *mask,
-                                           bool force)
-{
-       return 0;
-}
 static inline void free_remapped_irq(int irq) { }
 static inline void compose_remapped_msi_msg(struct pci_dev *pdev,
                                            unsigned int irq, unsigned int dest,
                                            struct msi_msg *msg, u8 hpet_id)
 {
 }
-static inline int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
+static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
 {
        return -ENODEV;
 }
-static inline int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                                        int index, int sub_handle)
+
+static inline void panic_if_irq_remap(const char *msg)
+{
+}
+
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
 {
-       return -ENODEV;
 }
-static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
+
+static inline bool setup_remapped_irq(int irq,
+                                     struct irq_cfg *cfg,
+                                     struct irq_chip *chip)
 {
-       return -ENODEV;
+       return false;
 }
 #endif /* CONFIG_IRQ_REMAP */
 
index 5ed1f16187be177dc799531f4a1e0febd6f38d97..65231e173bafceb5895f49da00b95f39c3088beb 100644 (file)
@@ -85,13 +85,13 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
        return ret;
 }
 
-static inline int kvm_para_available(void)
+static inline bool kvm_para_available(void)
 {
        unsigned int eax, ebx, ecx, edx;
        char signature[13];
 
        if (boot_cpu_data.cpuid_level < 0)
-               return 0;       /* So we don't blow up on old processors */
+               return false;   /* So we don't blow up on old processors */
 
        if (cpu_has_hypervisor) {
                cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
@@ -101,10 +101,10 @@ static inline int kvm_para_available(void)
                signature[12] = 0;
 
                if (strcmp(signature, "KVMKVMKVM") == 0)
-                       return 1;
+                       return true;
        }
 
-       return 0;
+       return false;
 }
 
 static inline unsigned int kvm_arch_para_features(void)
index 48142971b25d095b9724a06a6eff47b2cf302532..79327e9483a34ec33c3ba71bbdc94397f2456f46 100644 (file)
 #define __asmlinkage_protect0(ret) \
        __asmlinkage_protect_n(ret)
 #define __asmlinkage_protect1(ret, arg1) \
-       __asmlinkage_protect_n(ret, "g" (arg1))
+       __asmlinkage_protect_n(ret, "m" (arg1))
 #define __asmlinkage_protect2(ret, arg1, arg2) \
-       __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2))
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2))
 #define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
-       __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3))
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3))
 #define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
-       __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
-                             "g" (arg4))
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4))
 #define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
-       __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
-                             "g" (arg4), "g" (arg5))
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5))
 #define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
-       __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
-                             "g" (arg4), "g" (arg5), "g" (arg6))
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5), "m" (arg6))
 
 #endif /* CONFIG_X86_32 */
 
index ecdfee60ee4afb0e3b21e3c313420fc565468e56..f4076af1f4ed695480318634837173827b18b34d 100644 (file)
@@ -3,6 +3,90 @@
 
 #include <uapi/asm/mce.h>
 
+/*
+ * Machine Check support for x86
+ */
+
+/* MCG_CAP register defines */
+#define MCG_BANKCNT_MASK       0xff         /* Number of Banks */
+#define MCG_CTL_P              (1ULL<<8)    /* MCG_CTL register available */
+#define MCG_EXT_P              (1ULL<<9)    /* Extended registers available */
+#define MCG_CMCI_P             (1ULL<<10)   /* CMCI supported */
+#define MCG_EXT_CNT_MASK       0xff0000     /* Number of Extended registers */
+#define MCG_EXT_CNT_SHIFT      16
+#define MCG_EXT_CNT(c)         (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
+#define MCG_SER_P              (1ULL<<24)   /* MCA recovery/new status bits */
+
+/* MCG_STATUS register defines */
+#define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
+#define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
+#define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
+
+/* MCi_STATUS register defines */
+#define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
+#define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
+#define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
+#define MCI_STATUS_EN    (1ULL<<60)  /* error enabled */
+#define MCI_STATUS_MISCV (1ULL<<59)  /* misc error reg. valid */
+#define MCI_STATUS_ADDRV (1ULL<<58)  /* addr reg. valid */
+#define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
+#define MCI_STATUS_S    (1ULL<<56)  /* Signaled machine check */
+#define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
+#define MCACOD           0xffff     /* MCA Error Code */
+
+/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */
+#define MCACOD_SCRUB   0x00C0  /* 0xC0-0xCF Memory Scrubbing */
+#define MCACOD_SCRUBMSK        0xfff0
+#define MCACOD_L3WB    0x017A  /* L3 Explicit Writeback */
+#define MCACOD_DATA    0x0134  /* Data Load */
+#define MCACOD_INSTR   0x0150  /* Instruction Fetch */
+
+/* MCi_MISC register defines */
+#define MCI_MISC_ADDR_LSB(m)   ((m) & 0x3f)
+#define MCI_MISC_ADDR_MODE(m)  (((m) >> 6) & 7)
+#define  MCI_MISC_ADDR_SEGOFF  0       /* segment offset */
+#define  MCI_MISC_ADDR_LINEAR  1       /* linear address */
+#define  MCI_MISC_ADDR_PHYS    2       /* physical address */
+#define  MCI_MISC_ADDR_MEM     3       /* memory address */
+#define  MCI_MISC_ADDR_GENERIC 7       /* generic */
+
+/* CTL2 register defines */
+#define MCI_CTL2_CMCI_EN               (1ULL << 30)
+#define MCI_CTL2_CMCI_THRESHOLD_MASK   0x7fffULL
+
+#define MCJ_CTX_MASK           3
+#define MCJ_CTX(flags)         ((flags) & MCJ_CTX_MASK)
+#define MCJ_CTX_RANDOM         0    /* inject context: random */
+#define MCJ_CTX_PROCESS                0x1  /* inject context: process */
+#define MCJ_CTX_IRQ            0x2  /* inject context: IRQ */
+#define MCJ_NMI_BROADCAST      0x4  /* do NMI broadcasting */
+#define MCJ_EXCEPTION          0x8  /* raise as exception */
+#define MCJ_IRQ_BRAODCAST      0x10 /* do IRQ broadcasting */
+
+#define MCE_OVERFLOW 0         /* bit 0 in flags means overflow */
+
+/* Software defined banks */
+#define MCE_EXTENDED_BANK      128
+#define MCE_THERMAL_BANK       (MCE_EXTENDED_BANK + 0)
+#define K8_MCE_THRESHOLD_BASE   (MCE_EXTENDED_BANK + 1)
+
+#define MCE_LOG_LEN 32
+#define MCE_LOG_SIGNATURE      "MACHINECHECK"
+
+/*
+ * This structure contains all data related to the MCE log.  Also
+ * carries a signature to make it easier to find from external
+ * debugging tools.  Each entry is only valid when its finished flag
+ * is set.
+ */
+struct mce_log {
+       char signature[12]; /* "MACHINECHECK" */
+       unsigned len;       /* = MCE_LOG_LEN */
+       unsigned next;
+       unsigned flags;
+       unsigned recordlen;     /* length of struct mce */
+       struct mce entry[MCE_LOG_LEN];
+};
 
 struct mca_config {
        bool dont_log_ce;
index 3c4ffeb467e9886ad62b1a4c6bf60686fcb219a3..0d2d3b29118fe8c5eddeb5c1583927e83b40d6c5 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef _ASM_X86_PARPORT_H
 #define _ASM_X86_PARPORT_H
 
-static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+static int parport_pc_find_isa_ports(int autoirq, int autodma);
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
 {
        return parport_pc_find_isa_ports(autoirq, autodma);
 }
index dba7805176bf3cf705b5308d6c7d13b5142f9a61..c28fd02f4bf76e3fc7cc65bbfb946d5c324101f2 100644 (file)
@@ -121,9 +121,12 @@ static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
 #define arch_teardown_msi_irq x86_teardown_msi_irq
 #define arch_restore_msi_irqs x86_restore_msi_irqs
 /* implemented in arch/x86/kernel/apic/io_apic. */
+struct msi_desc;
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev, int irq);
+int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+                 unsigned int irq_base, unsigned int irq_offset);
 /* default to the implementation in drivers/lib/msi.c */
 #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
 #define HAVE_DEFAULT_MSI_RESTORE_IRQS
index 73e8eeff22ee038784b9a88841ba659250f9a18c..747e5a38b59042026b370acf9fcb86b40d1bf3e4 100644 (file)
@@ -140,11 +140,10 @@ struct pci_mmcfg_region {
 
 extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
-extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
+extern int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
 extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
-extern int __devinit pci_mmconfig_insert(struct device *dev,
-                                        u16 seg, u8 start,
-                                        u8 end, phys_addr_t addr);
+extern int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
+                              phys_addr_t addr);
 extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
 extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
 
index 4fabcdf1cfa74b6f6c7c04327e43fb5c7c1466ac..57cb634022136f39f3c9b4eebe9390b917717d89 100644 (file)
 #define ARCH_PERFMON_EVENTSEL_INV                      (1ULL << 23)
 #define ARCH_PERFMON_EVENTSEL_CMASK                    0xFF000000ULL
 
-#define AMD_PERFMON_EVENTSEL_GUESTONLY                 (1ULL << 40)
-#define AMD_PERFMON_EVENTSEL_HOSTONLY                  (1ULL << 41)
+#define AMD64_EVENTSEL_INT_CORE_ENABLE                 (1ULL << 36)
+#define AMD64_EVENTSEL_GUESTONLY                       (1ULL << 40)
+#define AMD64_EVENTSEL_HOSTONLY                                (1ULL << 41)
+
+#define AMD64_EVENTSEL_INT_CORE_SEL_SHIFT              37
+#define AMD64_EVENTSEL_INT_CORE_SEL_MASK               \
+       (0xFULL << AMD64_EVENTSEL_INT_CORE_SEL_SHIFT)
 
 #define AMD64_EVENTSEL_EVENT   \
        (ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32))
 #define AMD64_RAW_EVENT_MASK           \
        (X86_RAW_EVENT_MASK          |  \
         AMD64_EVENTSEL_EVENT)
+#define AMD64_RAW_EVENT_MASK_NB                \
+       (AMD64_EVENTSEL_EVENT        |  \
+        ARCH_PERFMON_EVENTSEL_UMASK)
 #define AMD64_NUM_COUNTERS                             4
 #define AMD64_NUM_COUNTERS_CORE                                6
+#define AMD64_NUM_COUNTERS_NB                          4
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL          0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK                (0x00 << 8)
index 5199db2923d31ff88b94c54397daae2b279a7bc7..fc304279b559d36ebe464206d56611c03e27b9d3 100644 (file)
@@ -142,6 +142,11 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
        return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
+static inline unsigned long pud_pfn(pud_t pud)
+{
+       return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT;
+}
+
 #define pte_page(pte)  pfn_to_page(pte_pfn(pte))
 
 static inline int pmd_large(pmd_t pte)
@@ -781,6 +786,18 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
        memcpy(dst, src, count * sizeof(pgd_t));
 }
 
+/*
+ * The x86 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+               unsigned long addr, pte_t *ptep)
+{
+}
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
+               unsigned long addr, pmd_t *pmd)
+{
+}
 
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
index 8faa215a503e54469359ab25376cc316e7703f82..9ee322103c6da79835fbae00772e9d6a7d60135c 100644 (file)
@@ -66,13 +66,6 @@ do {                                         \
        __flush_tlb_one((vaddr));               \
 } while (0)
 
-/*
- * The i386 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
- */
-#define update_mmu_cache(vma, address, ptep) do { } while (0)
-#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
index 47356f9df82e411ca3aa4e0025611d37451064b1..615b0c78449fd474257a3a63bd58c5c4ba52042f 100644 (file)
@@ -142,9 +142,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
 #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
 #define pte_unmap(pte) ((void)(pte))/* NOP */
 
-#define update_mmu_cache(vma, address, ptep) do { } while (0)
-#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
-
 /* Encode and de-code a swap entry */
 #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
 #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
index 03ca442d8f0d6af3ec3ab0ee73413eff3d392423..942a08623a1a09db57171fa60d03c664b7e8aa46 100644 (file)
@@ -133,6 +133,13 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
        return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs;
 #endif
 }
+
+#define current_user_stack_pointer()   this_cpu_read(old_rsp)
+/* ia32 vs. x32 difference */
+#define compat_user_stack_pointer()    \
+       (test_thread_flag(TIF_IA32)     \
+        ? current_pt_regs()->sp        \
+        : this_cpu_read(old_rsp))
 #endif
 
 #ifdef CONFIG_X86_32
index 6c7fc25f2c34a0eab822c2d6ab17c3b1cacbf0a0..5c6e4fb370f5aac25ee36002022ed72a59592f5e 100644 (file)
 # define NEED_NOPL     0
 #endif
 
+#ifdef CONFIG_MATOM
+# define NEED_MOVBE    (1<<(X86_FEATURE_MOVBE & 31))
+#else
+# define NEED_MOVBE    0
+#endif
+
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_PARAVIRT
 /* Paravirtualized systems may not have PSE or PGE available */
@@ -80,7 +86,7 @@
 
 #define REQUIRED_MASK2 0
 #define REQUIRED_MASK3 (NEED_NOPL)
-#define REQUIRED_MASK4 0
+#define REQUIRED_MASK4 (NEED_MOVBE)
 #define REQUIRED_MASK5 0
 #define REQUIRED_MASK6 0
 #define REQUIRED_MASK7 0
index c76fae4d90be0802e6bf659d8e998e4010791c75..31f61f96e0fb370030c31ad9318660c6af60ba03 100644 (file)
@@ -69,8 +69,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
 
 /* ia32/ia32_signal.c */
 asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
-asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
-                                 stack_ia32_t __user *, struct pt_regs *);
 asmlinkage long sys32_sigreturn(struct pt_regs *);
 asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
 
index 2f8374718aa301b4244a51f4c1bd9ad6bd37fc25..58b7e3eac0ae50cbeb9a0582d8014de0b58cd09c 100644 (file)
@@ -25,9 +25,6 @@ asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
 
 /* kernel/signal.c */
 long sys_rt_sigreturn(struct pt_regs *);
-long sys_sigaltstack(const stack_t __user *, stack_t __user *,
-                    struct pt_regs *);
-
 
 /* kernel/tls.c */
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
index 1003e69a40d9d217cf7443cea4609c3701fc7196..a0790e07ba6594305dbb14b8db687db49c71a0c9 100644 (file)
@@ -48,7 +48,6 @@
 # define __ARCH_WANT_SYS_TIME
 # define __ARCH_WANT_SYS_UTIME
 # define __ARCH_WANT_SYS_WAITPID
-# define __ARCH_WANT_SYS_EXECVE
 # define __ARCH_WANT_SYS_FORK
 # define __ARCH_WANT_SYS_VFORK
 # define __ARCH_WANT_SYS_CLONE
index b47c2a82ff1546a7efcd77a820a990d1e08bef00..062921ef34e9136100d3b4820826642dd45f223b 100644 (file)
@@ -16,7 +16,7 @@ extern void uv_system_init(void);
 extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                                                 struct mm_struct *mm,
                                                 unsigned long start,
-                                                unsigned end,
+                                                unsigned long end,
                                                 unsigned int cpu);
 
 #else  /* X86_UV */
index 57693498519c4a69962417c8889b376182b49e2f..7669941cc9d230c1261d82e3eba4a6d92b238eaa 100644 (file)
@@ -181,19 +181,38 @@ struct x86_platform_ops {
 };
 
 struct pci_dev;
+struct msi_msg;
 
 struct x86_msi_ops {
        int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
+       void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq,
+                               unsigned int dest, struct msi_msg *msg,
+                              u8 hpet_id);
        void (*teardown_msi_irq)(unsigned int irq);
        void (*teardown_msi_irqs)(struct pci_dev *dev);
        void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
+       int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
 };
 
+struct IO_APIC_route_entry;
+struct io_apic_irq_attr;
+struct irq_data;
+struct cpumask;
+
 struct x86_io_apic_ops {
-       void            (*init)  (void);
-       unsigned int    (*read)  (unsigned int apic, unsigned int reg);
-       void            (*write) (unsigned int apic, unsigned int reg, unsigned int value);
-       void            (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
+       void            (*init)   (void);
+       unsigned int    (*read)   (unsigned int apic, unsigned int reg);
+       void            (*write)  (unsigned int apic, unsigned int reg, unsigned int value);
+       void            (*modify) (unsigned int apic, unsigned int reg, unsigned int value);
+       void            (*disable)(void);
+       void            (*print_entries)(unsigned int apic, unsigned int nr_entries);
+       int             (*set_affinity)(struct irq_data *data,
+                                       const struct cpumask *mask,
+                                       bool force);
+       int             (*setup_entry)(int irq, struct IO_APIC_route_entry *entry,
+                                      unsigned int destination, int vector,
+                                      struct io_apic_irq_attr *attr);
+       void            (*eoi_ioapic_pin)(int apic, int pin, int vector);
 };
 
 extern struct x86_init_ops x86_init;
index f8fde90bc45e37171a7390723e3afff2ee9a1788..d8829751b3f895e9fd19fa6bd597758650f417b8 100644 (file)
 #ifdef CONFIG_KMEMCHECK
 /* kmemcheck doesn't handle MMX/SSE/SSE2 instructions */
 # include <asm-generic/xor.h>
+#elif !defined(_ASM_X86_XOR_H)
+#define _ASM_X86_XOR_H
+
+/*
+ * Optimized RAID-5 checksumming functions for SSE.
+ *
+ * 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.
+ */
+
+/*
+ * Cache avoiding checksumming functions utilizing KNI instructions
+ * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
+ */
+
+/*
+ * Based on
+ * High-speed RAID5 checksumming functions utilizing SSE instructions.
+ * Copyright (C) 1998 Ingo Molnar.
+ */
+
+/*
+ * x86-64 changes / gcc fixes from Andi Kleen.
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ *
+ * This hasn't been optimized for the hammer yet, but there are likely
+ * no advantages to be gotten from x86-64 here anyways.
+ */
+
+#include <asm/i387.h>
+
+#ifdef CONFIG_X86_32
+/* reduce register pressure */
+# define XOR_CONSTANT_CONSTRAINT "i"
 #else
+# define XOR_CONSTANT_CONSTRAINT "re"
+#endif
+
+#define OFFS(x)                "16*("#x")"
+#define PF_OFFS(x)     "256+16*("#x")"
+#define PF0(x)         "       prefetchnta "PF_OFFS(x)"(%[p1])         ;\n"
+#define LD(x, y)       "       movaps "OFFS(x)"(%[p1]), %%xmm"#y"      ;\n"
+#define ST(x, y)       "       movaps %%xmm"#y", "OFFS(x)"(%[p1])      ;\n"
+#define PF1(x)         "       prefetchnta "PF_OFFS(x)"(%[p2])         ;\n"
+#define PF2(x)         "       prefetchnta "PF_OFFS(x)"(%[p3])         ;\n"
+#define PF3(x)         "       prefetchnta "PF_OFFS(x)"(%[p4])         ;\n"
+#define PF4(x)         "       prefetchnta "PF_OFFS(x)"(%[p5])         ;\n"
+#define XO1(x, y)      "       xorps "OFFS(x)"(%[p2]), %%xmm"#y"       ;\n"
+#define XO2(x, y)      "       xorps "OFFS(x)"(%[p3]), %%xmm"#y"       ;\n"
+#define XO3(x, y)      "       xorps "OFFS(x)"(%[p4]), %%xmm"#y"       ;\n"
+#define XO4(x, y)      "       xorps "OFFS(x)"(%[p5]), %%xmm"#y"       ;\n"
+#define NOP(x)
+
+#define BLK64(pf, op, i)                               \
+               pf(i)                                   \
+               op(i, 0)                                \
+                       op(i + 1, 1)                    \
+                               op(i + 2, 2)            \
+                                       op(i + 3, 3)
+
+static void
+xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i)                                       \
+               LD(i, 0)                                \
+                       LD(i + 1, 1)                    \
+               PF1(i)                                  \
+                               PF1(i + 2)              \
+                               LD(i + 2, 2)            \
+                                       LD(i + 3, 3)    \
+               PF0(i + 4)                              \
+                               PF0(i + 6)              \
+               XO1(i, 0)                               \
+                       XO1(i + 1, 1)                   \
+                               XO1(i + 2, 2)           \
+                                       XO1(i + 3, 3)   \
+               ST(i, 0)                                \
+                       ST(i + 1, 1)                    \
+                               ST(i + 2, 2)            \
+                                       ST(i + 3, 3)    \
+
+
+               PF0(0)
+                               PF0(2)
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines),
+         [p1] "+r" (p1), [p2] "+r" (p2)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_2_pf64(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i)                       \
+               BLK64(PF0, LD, i)       \
+               BLK64(PF1, XO1, i)      \
+               BLK64(NOP, ST, i)       \
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines),
+         [p1] "+r" (p1), [p2] "+r" (p2)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+         unsigned long *p3)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+               PF1(i)                                  \
+                               PF1(i + 2)              \
+               LD(i, 0)                                \
+                       LD(i + 1, 1)                    \
+                               LD(i + 2, 2)            \
+                                       LD(i + 3, 3)    \
+               PF2(i)                                  \
+                               PF2(i + 2)              \
+               PF0(i + 4)                              \
+                               PF0(i + 6)              \
+               XO1(i, 0)                               \
+                       XO1(i + 1, 1)                   \
+                               XO1(i + 2, 2)           \
+                                       XO1(i + 3, 3)   \
+               XO2(i, 0)                               \
+                       XO2(i + 1, 1)                   \
+                               XO2(i + 2, 2)           \
+                                       XO2(i + 3, 3)   \
+               ST(i, 0)                                \
+                       ST(i + 1, 1)                    \
+                               ST(i + 2, 2)            \
+                                       ST(i + 3, 3)    \
+
+
+               PF0(0)
+                               PF0(2)
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines),
+         [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_3_pf64(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+              unsigned long *p3)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i)                       \
+               BLK64(PF0, LD, i)       \
+               BLK64(PF1, XO1, i)      \
+               BLK64(PF2, XO2, i)      \
+               BLK64(NOP, ST, i)       \
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines),
+         [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+         unsigned long *p3, unsigned long *p4)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+               PF1(i)                                  \
+                               PF1(i + 2)              \
+               LD(i, 0)                                \
+                       LD(i + 1, 1)                    \
+                               LD(i + 2, 2)            \
+                                       LD(i + 3, 3)    \
+               PF2(i)                                  \
+                               PF2(i + 2)              \
+               XO1(i, 0)                               \
+                       XO1(i + 1, 1)                   \
+                               XO1(i + 2, 2)           \
+                                       XO1(i + 3, 3)   \
+               PF3(i)                                  \
+                               PF3(i + 2)              \
+               PF0(i + 4)                              \
+                               PF0(i + 6)              \
+               XO2(i, 0)                               \
+                       XO2(i + 1, 1)                   \
+                               XO2(i + 2, 2)           \
+                                       XO2(i + 3, 3)   \
+               XO3(i, 0)                               \
+                       XO3(i + 1, 1)                   \
+                               XO3(i + 2, 2)           \
+                                       XO3(i + 3, 3)   \
+               ST(i, 0)                                \
+                       ST(i + 1, 1)                    \
+                               ST(i + 2, 2)            \
+                                       ST(i + 3, 3)    \
+
+
+               PF0(0)
+                               PF0(2)
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       add %[inc], %[p4]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines), [p1] "+r" (p1),
+         [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_4_pf64(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+              unsigned long *p3, unsigned long *p4)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i)                       \
+               BLK64(PF0, LD, i)       \
+               BLK64(PF1, XO1, i)      \
+               BLK64(PF2, XO2, i)      \
+               BLK64(PF3, XO3, i)      \
+               BLK64(NOP, ST, i)       \
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       add %[inc], %[p4]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines), [p1] "+r" (p1),
+         [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+         unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+               PF1(i)                                  \
+                               PF1(i + 2)              \
+               LD(i, 0)                                \
+                       LD(i + 1, 1)                    \
+                               LD(i + 2, 2)            \
+                                       LD(i + 3, 3)    \
+               PF2(i)                                  \
+                               PF2(i + 2)              \
+               XO1(i, 0)                               \
+                       XO1(i + 1, 1)                   \
+                               XO1(i + 2, 2)           \
+                                       XO1(i + 3, 3)   \
+               PF3(i)                                  \
+                               PF3(i + 2)              \
+               XO2(i, 0)                               \
+                       XO2(i + 1, 1)                   \
+                               XO2(i + 2, 2)           \
+                                       XO2(i + 3, 3)   \
+               PF4(i)                                  \
+                               PF4(i + 2)              \
+               PF0(i + 4)                              \
+                               PF0(i + 6)              \
+               XO3(i, 0)                               \
+                       XO3(i + 1, 1)                   \
+                               XO3(i + 2, 2)           \
+                                       XO3(i + 3, 3)   \
+               XO4(i, 0)                               \
+                       XO4(i + 1, 1)                   \
+                               XO4(i + 2, 2)           \
+                                       XO4(i + 3, 3)   \
+               ST(i, 0)                                \
+                       ST(i + 1, 1)                    \
+                               ST(i + 2, 2)            \
+                                       ST(i + 3, 3)    \
+
+
+               PF0(0)
+                               PF0(2)
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       add %[inc], %[p4]       ;\n"
+       "       add %[inc], %[p5]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines), [p1] "+r" (p1), [p2] "+r" (p2),
+         [p3] "+r" (p3), [p4] "+r" (p4), [p5] "+r" (p5)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static void
+xor_sse_5_pf64(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+              unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+       unsigned long lines = bytes >> 8;
+
+       kernel_fpu_begin();
+
+       asm volatile(
+#undef BLOCK
+#define BLOCK(i)                       \
+               BLK64(PF0, LD, i)       \
+               BLK64(PF1, XO1, i)      \
+               BLK64(PF2, XO2, i)      \
+               BLK64(PF3, XO3, i)      \
+               BLK64(PF4, XO4, i)      \
+               BLK64(NOP, ST, i)       \
+
+       " .align 32                     ;\n"
+       " 1:                            ;\n"
+
+               BLOCK(0)
+               BLOCK(4)
+               BLOCK(8)
+               BLOCK(12)
+
+       "       add %[inc], %[p1]       ;\n"
+       "       add %[inc], %[p2]       ;\n"
+       "       add %[inc], %[p3]       ;\n"
+       "       add %[inc], %[p4]       ;\n"
+       "       add %[inc], %[p5]       ;\n"
+       "       dec %[cnt]              ;\n"
+       "       jnz 1b                  ;\n"
+       : [cnt] "+r" (lines), [p1] "+r" (p1), [p2] "+r" (p2),
+         [p3] "+r" (p3), [p4] "+r" (p4), [p5] "+r" (p5)
+       : [inc] XOR_CONSTANT_CONSTRAINT (256UL)
+       : "memory");
+
+       kernel_fpu_end();
+}
+
+static struct xor_block_template xor_block_sse_pf64 = {
+       .name = "prefetch64-sse",
+       .do_2 = xor_sse_2_pf64,
+       .do_3 = xor_sse_3_pf64,
+       .do_4 = xor_sse_4_pf64,
+       .do_5 = xor_sse_5_pf64,
+};
+
+#undef LD
+#undef XO1
+#undef XO2
+#undef XO3
+#undef XO4
+#undef ST
+#undef NOP
+#undef BLK64
+#undef BLOCK
+
+#undef XOR_CONSTANT_CONSTRAINT
+
 #ifdef CONFIG_X86_32
 # include <asm/xor_32.h>
 #else
 # include <asm/xor_64.h>
 #endif
-#endif
+
+#define XOR_SELECT_TEMPLATE(FASTEST) \
+       AVX_SELECT(FASTEST)
+
+#endif /* _ASM_X86_XOR_H */
index f79cb7ec0e06a4c7f36361a381c3156d45dab365..ce05722e3c68bce4d72a1bcdc9e798b5014581cf 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_X86_XOR_32_H
 
 /*
- * Optimized RAID-5 checksumming functions for MMX and SSE.
+ * Optimized RAID-5 checksumming functions for MMX.
  *
  * 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
@@ -529,290 +529,6 @@ static struct xor_block_template xor_block_p5_mmx = {
        .do_5 = xor_p5_mmx_5,
 };
 
-/*
- * Cache avoiding checksumming functions utilizing KNI instructions
- * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
- */
-
-#define OFFS(x)                "16*("#x")"
-#define PF_OFFS(x)     "256+16*("#x")"
-#define        PF0(x)          "       prefetchnta "PF_OFFS(x)"(%1)            ;\n"
-#define LD(x, y)       "       movaps   "OFFS(x)"(%1), %%xmm"#y"       ;\n"
-#define ST(x, y)       "       movaps %%xmm"#y",   "OFFS(x)"(%1)       ;\n"
-#define PF1(x)         "       prefetchnta "PF_OFFS(x)"(%2)            ;\n"
-#define PF2(x)         "       prefetchnta "PF_OFFS(x)"(%3)            ;\n"
-#define PF3(x)         "       prefetchnta "PF_OFFS(x)"(%4)            ;\n"
-#define PF4(x)         "       prefetchnta "PF_OFFS(x)"(%5)            ;\n"
-#define PF5(x)         "       prefetchnta "PF_OFFS(x)"(%6)            ;\n"
-#define XO1(x, y)      "       xorps   "OFFS(x)"(%2), %%xmm"#y"        ;\n"
-#define XO2(x, y)      "       xorps   "OFFS(x)"(%3), %%xmm"#y"        ;\n"
-#define XO3(x, y)      "       xorps   "OFFS(x)"(%4), %%xmm"#y"        ;\n"
-#define XO4(x, y)      "       xorps   "OFFS(x)"(%5), %%xmm"#y"        ;\n"
-#define XO5(x, y)      "       xorps   "OFFS(x)"(%6), %%xmm"#y"        ;\n"
-
-
-static void
-xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
-{
-       unsigned long lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i)                                       \
-               LD(i, 0)                                \
-                       LD(i + 1, 1)                    \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO1(i, 0)                               \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               ST(i, 0)                                \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addl $256, %1           ;\n"
-       "       addl $256, %2           ;\n"
-       "       decl %0                 ;\n"
-       "       jnz 1b                  ;\n"
-       : "+r" (lines),
-         "+r" (p1), "+r" (p2)
-       :
-       : "memory");
-
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3)
-{
-       unsigned long lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i,0)                                 \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO1(i,0)                                \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               XO2(i,0)                                \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               ST(i,0)                                 \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addl $256, %1           ;\n"
-       "       addl $256, %2           ;\n"
-       "       addl $256, %3           ;\n"
-       "       decl %0                 ;\n"
-       "       jnz 1b                  ;\n"
-       : "+r" (lines),
-         "+r" (p1), "+r"(p2), "+r"(p3)
-       :
-       : "memory" );
-
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3, unsigned long *p4)
-{
-       unsigned long lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i,0)                                 \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               XO1(i,0)                                \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               PF3(i)                                  \
-                               PF3(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO2(i,0)                                \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               XO3(i,0)                                \
-                       XO3(i + 1, 1)                   \
-                               XO3(i + 2, 2)           \
-                                       XO3(i + 3, 3)   \
-               ST(i,0)                                 \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addl $256, %1           ;\n"
-       "       addl $256, %2           ;\n"
-       "       addl $256, %3           ;\n"
-       "       addl $256, %4           ;\n"
-       "       decl %0                 ;\n"
-       "       jnz 1b                  ;\n"
-       : "+r" (lines),
-         "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
-       :
-       : "memory" );
-
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3, unsigned long *p4, unsigned long *p5)
-{
-       unsigned long lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       /* Make sure GCC forgets anything it knows about p4 or p5,
-          such that it won't pass to the asm volatile below a
-          register that is shared with any other variable.  That's
-          because we modify p4 and p5 there, but we can't mark them
-          as read/write, otherwise we'd overflow the 10-asm-operands
-          limit of GCC < 3.1.  */
-       asm("" : "+r" (p4), "+r" (p5));
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i,0)                                 \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               XO1(i,0)                                \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               PF3(i)                                  \
-                               PF3(i + 2)              \
-               XO2(i,0)                                \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               PF4(i)                                  \
-                               PF4(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO3(i,0)                                \
-                       XO3(i + 1, 1)                   \
-                               XO3(i + 2, 2)           \
-                                       XO3(i + 3, 3)   \
-               XO4(i,0)                                \
-                       XO4(i + 1, 1)                   \
-                               XO4(i + 2, 2)           \
-                                       XO4(i + 3, 3)   \
-               ST(i,0)                                 \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addl $256, %1           ;\n"
-       "       addl $256, %2           ;\n"
-       "       addl $256, %3           ;\n"
-       "       addl $256, %4           ;\n"
-       "       addl $256, %5           ;\n"
-       "       decl %0                 ;\n"
-       "       jnz 1b                  ;\n"
-       : "+r" (lines),
-         "+r" (p1), "+r" (p2), "+r" (p3)
-       : "r" (p4), "r" (p5)
-       : "memory");
-
-       /* p4 and p5 were modified, and now the variables are dead.
-          Clobber them just to be sure nobody does something stupid
-          like assuming they have some legal value.  */
-       asm("" : "=r" (p4), "=r" (p5));
-
-       kernel_fpu_end();
-}
-
 static struct xor_block_template xor_block_pIII_sse = {
        .name = "pIII_sse",
        .do_2 = xor_sse_2,
@@ -827,26 +543,25 @@ static struct xor_block_template xor_block_pIII_sse = {
 /* Also try the generic routines.  */
 #include <asm-generic/xor.h>
 
+/* We force the use of the SSE xor block because it can write around L2.
+   We may also be able to load into the L1 only depending on how the cpu
+   deals with a load to a line that is being prefetched.  */
 #undef XOR_TRY_TEMPLATES
 #define XOR_TRY_TEMPLATES                              \
 do {                                                   \
-       xor_speed(&xor_block_8regs);                    \
-       xor_speed(&xor_block_8regs_p);                  \
-       xor_speed(&xor_block_32regs);                   \
-       xor_speed(&xor_block_32regs_p);                 \
        AVX_XOR_SPEED;                                  \
-       if (cpu_has_xmm)                                \
+       if (cpu_has_xmm) {                              \
                xor_speed(&xor_block_pIII_sse);         \
-       if (cpu_has_mmx) {                              \
+               xor_speed(&xor_block_sse_pf64);         \
+       } else if (cpu_has_mmx) {                       \
                xor_speed(&xor_block_pII_mmx);          \
                xor_speed(&xor_block_p5_mmx);           \
+       } else {                                        \
+               xor_speed(&xor_block_8regs);            \
+               xor_speed(&xor_block_8regs_p);          \
+               xor_speed(&xor_block_32regs);           \
+               xor_speed(&xor_block_32regs_p);         \
        }                                               \
 } while (0)
 
-/* We force the use of the SSE xor block because it can write around L2.
-   We may also be able to load into the L1 only depending on how the cpu
-   deals with a load to a line that is being prefetched.  */
-#define XOR_SELECT_TEMPLATE(FASTEST)                   \
-       AVX_SELECT(cpu_has_xmm ? &xor_block_pIII_sse : FASTEST)
-
 #endif /* _ASM_X86_XOR_32_H */
index 87ac522c4af53b9770297f38f78a02d065bb2cbf..546f1e3b87cce3d346f95fec83ff2630342da47c 100644 (file)
@@ -1,301 +1,6 @@
 #ifndef _ASM_X86_XOR_64_H
 #define _ASM_X86_XOR_64_H
 
-/*
- * Optimized RAID-5 checksumming functions for MMX and SSE.
- *
- * 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.
- */
-
-
-/*
- * Cache avoiding checksumming functions utilizing KNI instructions
- * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
- */
-
-/*
- * Based on
- * High-speed RAID5 checksumming functions utilizing SSE instructions.
- * Copyright (C) 1998 Ingo Molnar.
- */
-
-/*
- * x86-64 changes / gcc fixes from Andi Kleen.
- * Copyright 2002 Andi Kleen, SuSE Labs.
- *
- * This hasn't been optimized for the hammer yet, but there are likely
- * no advantages to be gotten from x86-64 here anyways.
- */
-
-#include <asm/i387.h>
-
-#define OFFS(x)                "16*("#x")"
-#define PF_OFFS(x)     "256+16*("#x")"
-#define        PF0(x)          "       prefetchnta "PF_OFFS(x)"(%[p1])         ;\n"
-#define LD(x, y)       "       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"    ;\n"
-#define ST(x, y)       "       movaps %%xmm"#y",   "OFFS(x)"(%[p1])    ;\n"
-#define PF1(x)         "       prefetchnta "PF_OFFS(x)"(%[p2])         ;\n"
-#define PF2(x)         "       prefetchnta "PF_OFFS(x)"(%[p3])         ;\n"
-#define PF3(x)         "       prefetchnta "PF_OFFS(x)"(%[p4])         ;\n"
-#define PF4(x)         "       prefetchnta "PF_OFFS(x)"(%[p5])         ;\n"
-#define PF5(x)         "       prefetchnta "PF_OFFS(x)"(%[p6])         ;\n"
-#define XO1(x, y)      "       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"     ;\n"
-#define XO2(x, y)      "       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"     ;\n"
-#define XO3(x, y)      "       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"     ;\n"
-#define XO4(x, y)      "       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"     ;\n"
-#define XO5(x, y)      "       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"     ;\n"
-
-
-static void
-xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
-{
-       unsigned int lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               LD(i, 0)                                \
-                       LD(i + 1, 1)                    \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO1(i, 0)                               \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               ST(i, 0)                                \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addq %[inc], %[p1]           ;\n"
-       "       addq %[inc], %[p2]           ;\n"
-               "               decl %[cnt] ; jnz 1b"
-       : [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
-       : [inc] "r" (256UL)
-       : "memory");
-
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3)
-{
-       unsigned int lines = bytes >> 8;
-
-       kernel_fpu_begin();
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i, 0)                                        \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO1(i, 0)                               \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               XO2(i, 0)                               \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               ST(i, 0)                                \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addq %[inc], %[p1]           ;\n"
-       "       addq %[inc], %[p2]          ;\n"
-       "       addq %[inc], %[p3]           ;\n"
-               "               decl %[cnt] ; jnz 1b"
-       : [cnt] "+r" (lines),
-         [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
-       : [inc] "r" (256UL)
-       : "memory");
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3, unsigned long *p4)
-{
-       unsigned int lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i, 0)                                \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               XO1(i, 0)                               \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               PF3(i)                                  \
-                               PF3(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO2(i, 0)                               \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               XO3(i, 0)                               \
-                       XO3(i + 1, 1)                   \
-                               XO3(i + 2, 2)           \
-                                       XO3(i + 3, 3)   \
-               ST(i, 0)                                \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addq %[inc], %[p1]           ;\n"
-       "       addq %[inc], %[p2]           ;\n"
-       "       addq %[inc], %[p3]           ;\n"
-       "       addq %[inc], %[p4]           ;\n"
-       "       decl %[cnt] ; jnz 1b"
-       : [cnt] "+c" (lines),
-         [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
-       : [inc] "r" (256UL)
-       : "memory" );
-
-       kernel_fpu_end();
-}
-
-static void
-xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-         unsigned long *p3, unsigned long *p4, unsigned long *p5)
-{
-       unsigned int lines = bytes >> 8;
-
-       kernel_fpu_begin();
-
-       asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
-               PF1(i)                                  \
-                               PF1(i + 2)              \
-               LD(i, 0)                                \
-                       LD(i + 1, 1)                    \
-                               LD(i + 2, 2)            \
-                                       LD(i + 3, 3)    \
-               PF2(i)                                  \
-                               PF2(i + 2)              \
-               XO1(i, 0)                               \
-                       XO1(i + 1, 1)                   \
-                               XO1(i + 2, 2)           \
-                                       XO1(i + 3, 3)   \
-               PF3(i)                                  \
-                               PF3(i + 2)              \
-               XO2(i, 0)                               \
-                       XO2(i + 1, 1)                   \
-                               XO2(i + 2, 2)           \
-                                       XO2(i + 3, 3)   \
-               PF4(i)                                  \
-                               PF4(i + 2)              \
-               PF0(i + 4)                              \
-                               PF0(i + 6)              \
-               XO3(i, 0)                               \
-                       XO3(i + 1, 1)                   \
-                               XO3(i + 2, 2)           \
-                                       XO3(i + 3, 3)   \
-               XO4(i, 0)                               \
-                       XO4(i + 1, 1)                   \
-                               XO4(i + 2, 2)           \
-                                       XO4(i + 3, 3)   \
-               ST(i, 0)                                \
-                       ST(i + 1, 1)                    \
-                               ST(i + 2, 2)            \
-                                       ST(i + 3, 3)    \
-
-
-               PF0(0)
-                               PF0(2)
-
-       " .align 32                     ;\n"
-       " 1:                            ;\n"
-
-               BLOCK(0)
-               BLOCK(4)
-               BLOCK(8)
-               BLOCK(12)
-
-       "       addq %[inc], %[p1]           ;\n"
-       "       addq %[inc], %[p2]           ;\n"
-       "       addq %[inc], %[p3]           ;\n"
-       "       addq %[inc], %[p4]           ;\n"
-       "       addq %[inc], %[p5]           ;\n"
-       "       decl %[cnt] ; jnz 1b"
-       : [cnt] "+c" (lines),
-         [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
-         [p5] "+r" (p5)
-       : [inc] "r" (256UL)
-       : "memory");
-
-       kernel_fpu_end();
-}
-
 static struct xor_block_template xor_block_sse = {
        .name = "generic_sse",
        .do_2 = xor_sse_2,
@@ -308,17 +13,15 @@ static struct xor_block_template xor_block_sse = {
 /* Also try the AVX routines */
 #include <asm/xor_avx.h>
 
+/* We force the use of the SSE xor block because it can write around L2.
+   We may also be able to load into the L1 only depending on how the cpu
+   deals with a load to a line that is being prefetched.  */
 #undef XOR_TRY_TEMPLATES
 #define XOR_TRY_TEMPLATES                      \
 do {                                           \
        AVX_XOR_SPEED;                          \
+       xor_speed(&xor_block_sse_pf64);         \
        xor_speed(&xor_block_sse);              \
 } while (0)
 
-/* We force the use of the SSE xor block because it can write around L2.
-   We may also be able to load into the L1 only depending on how the cpu
-   deals with a load to a line that is being prefetched.  */
-#define XOR_SELECT_TEMPLATE(FASTEST) \
-       AVX_SELECT(&xor_block_sse)
-
 #endif /* _ASM_X86_XOR_64_H */
index 92862cd902012b9fb174d03e6e2cd687787136cf..c15ddaf907107134d6cd2f8d86f554e510a6f848 100644 (file)
@@ -1,6 +1,31 @@
 #ifndef _ASM_X86_BOOTPARAM_H
 #define _ASM_X86_BOOTPARAM_H
 
+/* setup_data types */
+#define SETUP_NONE                     0
+#define SETUP_E820_EXT                 1
+#define SETUP_DTB                      2
+#define SETUP_PCI                      3
+
+/* ram_size flags */
+#define RAMDISK_IMAGE_START_MASK       0x07FF
+#define RAMDISK_PROMPT_FLAG            0x8000
+#define RAMDISK_LOAD_FLAG              0x4000
+
+/* loadflags */
+#define LOADED_HIGH    (1<<0)
+#define QUIET_FLAG     (1<<5)
+#define KEEP_SEGMENTS  (1<<6)
+#define CAN_USE_HEAP   (1<<7)
+
+/* xloadflags */
+#define XLF_KERNEL_64                  (1<<0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G     (1<<1)
+#define XLF_EFI_HANDOVER_32            (1<<2)
+#define XLF_EFI_HANDOVER_64            (1<<3)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/screen_info.h>
 #include <linux/apm_bios.h>
@@ -9,12 +34,6 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
-/* setup data types */
-#define SETUP_NONE                     0
-#define SETUP_E820_EXT                 1
-#define SETUP_DTB                      2
-#define SETUP_PCI                      3
-
 /* extensible setup data list node */
 struct setup_data {
        __u64 next;
@@ -28,9 +47,6 @@ struct setup_header {
        __u16   root_flags;
        __u32   syssize;
        __u16   ram_size;
-#define RAMDISK_IMAGE_START_MASK       0x07FF
-#define RAMDISK_PROMPT_FLAG            0x8000
-#define RAMDISK_LOAD_FLAG              0x4000
        __u16   vid_mode;
        __u16   root_dev;
        __u16   boot_flag;
@@ -42,10 +58,6 @@ struct setup_header {
        __u16   kernel_version;
        __u8    type_of_loader;
        __u8    loadflags;
-#define LOADED_HIGH    (1<<0)
-#define QUIET_FLAG     (1<<5)
-#define KEEP_SEGMENTS  (1<<6)
-#define CAN_USE_HEAP   (1<<7)
        __u16   setup_move_size;
        __u32   code32_start;
        __u32   ramdisk_image;
@@ -58,7 +70,8 @@ struct setup_header {
        __u32   initrd_addr_max;
        __u32   kernel_alignment;
        __u8    relocatable_kernel;
-       __u8    _pad2[3];
+       __u8    min_alignment;
+       __u16   xloadflags;
        __u32   cmdline_size;
        __u32   hardware_subarch;
        __u64   hardware_subarch_data;
@@ -106,7 +119,10 @@ struct boot_params {
        __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
        struct sys_desc_table sys_desc_table;           /* 0x0a0 */
        struct olpc_ofw_header olpc_ofw_header;         /* 0x0b0 */
-       __u8  _pad4[128];                               /* 0x0c0 */
+       __u32 ext_ramdisk_image;                        /* 0x0c0 */
+       __u32 ext_ramdisk_size;                         /* 0x0c4 */
+       __u32 ext_cmd_line_ptr;                         /* 0x0c8 */
+       __u8  _pad4[116];                               /* 0x0cc */
        struct edid_info edid_info;                     /* 0x140 */
        struct efi_info efi_info;                       /* 0x1c0 */
        __u32 alt_mem_k;                                /* 0x1e0 */
@@ -115,7 +131,20 @@ struct boot_params {
        __u8  eddbuf_entries;                           /* 0x1e9 */
        __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */
        __u8  kbd_status;                               /* 0x1eb */
-       __u8  _pad6[5];                                 /* 0x1ec */
+       __u8  _pad5[3];                                 /* 0x1ec */
+       /*
+        * The sentinel is set to a nonzero value (0xff) in header.S.
+        *
+        * A bootloader is supposed to only take setup_header and put
+        * it into a clean boot_params buffer. If it turns out that
+        * it is clumsy or too generous with the buffer, it most
+        * probably will pick up the sentinel variable too. The fact
+        * that this variable then is still 0xff will let kernel
+        * know that some variables in boot_params are invalid and
+        * kernel should zero out certain portions of boot_params.
+        */
+       __u8  sentinel;                                 /* 0x1ef */
+       __u8  _pad6[1];                                 /* 0x1f0 */
        struct setup_header hdr;    /* setup header */  /* 0x1f1 */
        __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
        __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];      /* 0x290 */
@@ -134,6 +163,6 @@ enum {
        X86_NR_SUBARCHS,
 };
 
-
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_BOOTPARAM_H */
index 58c829871c317b89d2cf011ea78f099de69622a4..a0eab85ce7b8283cc5f194ec175e8076669a762f 100644 (file)
@@ -4,66 +4,6 @@
 #include <linux/types.h>
 #include <asm/ioctls.h>
 
-/*
- * Machine Check support for x86
- */
-
-/* MCG_CAP register defines */
-#define MCG_BANKCNT_MASK       0xff         /* Number of Banks */
-#define MCG_CTL_P              (1ULL<<8)    /* MCG_CTL register available */
-#define MCG_EXT_P              (1ULL<<9)    /* Extended registers available */
-#define MCG_CMCI_P             (1ULL<<10)   /* CMCI supported */
-#define MCG_EXT_CNT_MASK       0xff0000     /* Number of Extended registers */
-#define MCG_EXT_CNT_SHIFT      16
-#define MCG_EXT_CNT(c)         (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
-#define MCG_SER_P              (1ULL<<24)   /* MCA recovery/new status bits */
-
-/* MCG_STATUS register defines */
-#define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
-#define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
-#define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
-
-/* MCi_STATUS register defines */
-#define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
-#define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
-#define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
-#define MCI_STATUS_EN    (1ULL<<60)  /* error enabled */
-#define MCI_STATUS_MISCV (1ULL<<59)  /* misc error reg. valid */
-#define MCI_STATUS_ADDRV (1ULL<<58)  /* addr reg. valid */
-#define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
-#define MCI_STATUS_S    (1ULL<<56)  /* Signaled machine check */
-#define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
-#define MCACOD           0xffff     /* MCA Error Code */
-
-/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */
-#define MCACOD_SCRUB   0x00C0  /* 0xC0-0xCF Memory Scrubbing */
-#define MCACOD_SCRUBMSK        0xfff0
-#define MCACOD_L3WB    0x017A  /* L3 Explicit Writeback */
-#define MCACOD_DATA    0x0134  /* Data Load */
-#define MCACOD_INSTR   0x0150  /* Instruction Fetch */
-
-/* MCi_MISC register defines */
-#define MCI_MISC_ADDR_LSB(m)   ((m) & 0x3f)
-#define MCI_MISC_ADDR_MODE(m)  (((m) >> 6) & 7)
-#define  MCI_MISC_ADDR_SEGOFF  0       /* segment offset */
-#define  MCI_MISC_ADDR_LINEAR  1       /* linear address */
-#define  MCI_MISC_ADDR_PHYS    2       /* physical address */
-#define  MCI_MISC_ADDR_MEM     3       /* memory address */
-#define  MCI_MISC_ADDR_GENERIC 7       /* generic */
-
-/* CTL2 register defines */
-#define MCI_CTL2_CMCI_EN               (1ULL << 30)
-#define MCI_CTL2_CMCI_THRESHOLD_MASK   0x7fffULL
-
-#define MCJ_CTX_MASK           3
-#define MCJ_CTX(flags)         ((flags) & MCJ_CTX_MASK)
-#define MCJ_CTX_RANDOM         0    /* inject context: random */
-#define MCJ_CTX_PROCESS                0x1  /* inject context: process */
-#define MCJ_CTX_IRQ            0x2  /* inject context: IRQ */
-#define MCJ_NMI_BROADCAST      0x4  /* do NMI broadcasting */
-#define MCJ_EXCEPTION          0x8  /* raise as exception */
-#define MCJ_IRQ_BRAODCAST      0x10 /* do IRQ broadcasting */
-
 /* Fields are zero when not available */
 struct mce {
        __u64 status;
@@ -87,35 +27,8 @@ struct mce {
        __u64 mcgcap;   /* MCGCAP MSR: machine check capabilities of CPU */
 };
 
-/*
- * This structure contains all data related to the MCE log.  Also
- * carries a signature to make it easier to find from external
- * debugging tools.  Each entry is only valid when its finished flag
- * is set.
- */
-
-#define MCE_LOG_LEN 32
-
-struct mce_log {
-       char signature[12]; /* "MACHINECHECK" */
-       unsigned len;       /* = MCE_LOG_LEN */
-       unsigned next;
-       unsigned flags;
-       unsigned recordlen;     /* length of struct mce */
-       struct mce entry[MCE_LOG_LEN];
-};
-
-#define MCE_OVERFLOW 0         /* bit 0 in flags means overflow */
-
-#define MCE_LOG_SIGNATURE      "MACHINECHECK"
-
 #define MCE_GET_RECORD_LEN   _IOR('M', 1, int)
 #define MCE_GET_LOG_LEN      _IOR('M', 2, int)
 #define MCE_GETCLEAR_FLAGS   _IOR('M', 3, int)
 
-/* Software defined banks */
-#define MCE_EXTENDED_BANK      128
-#define MCE_THERMAL_BANK       MCE_EXTENDED_BANK + 0
-#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)
-
 #endif /* _UAPI_ASM_X86_MCE_H */
index 433a59fb1a7411b97cd0db54d30a3bc727a4aeea..075a402555912541fe0b502c6c6b877812a5b089 100644 (file)
 /* Fam 15h MSRs */
 #define MSR_F15H_PERF_CTL              0xc0010200
 #define MSR_F15H_PERF_CTR              0xc0010201
+#define MSR_F15H_NB_PERF_CTL           0xc0010240
+#define MSR_F15H_NB_PERF_CTR           0xc0010241
 
 /* Fam 10h MSRs */
 #define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
index 0818f9a8e889f047932ba9f78aca5a95c6c3ed39..aa7d6ae39e0e9b8629938a408ba3e7f18a5a0fca 100644 (file)
@@ -87,12 +87,6 @@ typedef unsigned long sigset_t;
 
 #define SA_RESTORER    0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index 34e923a537628777aa4e5ac90741bef6ef575633..ac3b3d002833024a6641ffbbc5d7ead7a99ca23b 100644 (file)
@@ -65,8 +65,7 @@ obj-$(CONFIG_X86_TSC)         += trace_clock.o
 obj-$(CONFIG_KEXEC)            += machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC)            += relocate_kernel_$(BITS).o crash.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump_$(BITS).o
-obj-$(CONFIG_KPROBES)          += kprobes.o
-obj-$(CONFIG_OPTPROBES)                += kprobes-opt.o
+obj-y                          += kprobes/
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_DOUBLEFAULT)      += doublefault_32.o
 obj-$(CONFIG_KGDB)             += kgdb.o
index b994cc84aa7e0f0654775f82b286c77d28d9d621..a5b4dce1b7acb74552908e05d77b9354f108739b 100644 (file)
@@ -1477,8 +1477,7 @@ void __init bsp_end_local_APIC_setup(void)
         * Now that local APIC setup is completed for BP, configure the fault
         * handling for interrupt remapping.
         */
-       if (irq_remapping_enabled)
-               irq_remap_enable_fault_handling();
+       irq_remap_enable_fault_handling();
 
 }
 
@@ -2251,8 +2250,7 @@ static int lapic_suspend(void)
        local_irq_save(flags);
        disable_local_APIC();
 
-       if (irq_remapping_enabled)
-               irq_remapping_disable();
+       irq_remapping_disable();
 
        local_irq_restore(flags);
        return 0;
@@ -2268,16 +2266,15 @@ static void lapic_resume(void)
                return;
 
        local_irq_save(flags);
-       if (irq_remapping_enabled) {
-               /*
-                * IO-APIC and PIC have their own resume routines.
-                * We just mask them here to make sure the interrupt
-                * subsystem is completely quiet while we enable x2apic
-                * and interrupt-remapping.
-                */
-               mask_ioapic_entries();
-               legacy_pic->mask_all();
-       }
+
+       /*
+        * IO-APIC and PIC have their own resume routines.
+        * We just mask them here to make sure the interrupt
+        * subsystem is completely quiet while we enable x2apic
+        * and interrupt-remapping.
+        */
+       mask_ioapic_entries();
+       legacy_pic->mask_all();
 
        if (x2apic_mode)
                enable_x2apic();
@@ -2320,8 +2317,7 @@ static void lapic_resume(void)
        apic_write(APIC_ESR, 0);
        apic_read(APIC_ESR);
 
-       if (irq_remapping_enabled)
-               irq_remapping_reenable(x2apic_mode);
+       irq_remapping_reenable(x2apic_mode);
 
        local_irq_restore(flags);
 }
index b739d398bb29bc6951e777827cd56c982cedb452..9ed796ccc32ccda58fe9e1d914aa2c7828845d0c 100644 (file)
 #define for_each_irq_pin(entry, head) \
        for (entry = head; entry; entry = entry->next)
 
-#ifdef CONFIG_IRQ_REMAP
-static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
-static inline bool irq_remapped(struct irq_cfg *cfg)
-{
-       return cfg->irq_2_iommu.iommu != NULL;
-}
-#else
-static inline bool irq_remapped(struct irq_cfg *cfg)
-{
-       return false;
-}
-static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
-{
-}
-#endif
-
 /*
  *      Is the SiS APIC rmw bug present ?
  *      -1 = don't know, 0 = no, 1 = yes
@@ -300,9 +284,9 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
        return cfg;
 }
 
-static int alloc_irq_from(unsigned int from, int node)
+static int alloc_irqs_from(unsigned int from, unsigned int count, int node)
 {
-       return irq_alloc_desc_from(from, node);
+       return irq_alloc_descs_from(from, count, node);
 }
 
 static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
@@ -326,7 +310,7 @@ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
                + (mpc_ioapic_addr(idx) & ~PAGE_MASK);
 }
 
-static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
+void io_apic_eoi(unsigned int apic, unsigned int vector)
 {
        struct io_apic __iomem *io_apic = io_apic_base(apic);
        writel(vector, &io_apic->eoi);
@@ -573,19 +557,10 @@ static void unmask_ioapic_irq(struct irq_data *data)
  * Otherwise, we simulate the EOI message manually by changing the trigger
  * mode to edge and then back to level, with RTE being masked during this.
  */
-static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
+void native_eoi_ioapic_pin(int apic, int pin, int vector)
 {
        if (mpc_ioapic_ver(apic) >= 0x20) {
-               /*
-                * Intr-remapping uses pin number as the virtual vector
-                * in the RTE. Actual vector is programmed in
-                * intr-remapping table entry. Hence for the io-apic
-                * EOI we use the pin number.
-                */
-               if (cfg && irq_remapped(cfg))
-                       io_apic_eoi(apic, pin);
-               else
-                       io_apic_eoi(apic, vector);
+               io_apic_eoi(apic, vector);
        } else {
                struct IO_APIC_route_entry entry, entry1;
 
@@ -606,14 +581,15 @@ static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
        }
 }
 
-static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 {
        struct irq_pin_list *entry;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        for_each_irq_pin(entry, cfg->irq_2_pin)
-               __eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
+               x86_io_apic_ops.eoi_ioapic_pin(entry->apic, entry->pin,
+                                              cfg->vector);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -650,7 +626,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
                }
 
                raw_spin_lock_irqsave(&ioapic_lock, flags);
-               __eoi_ioapic_pin(apic, pin, entry.vector, NULL);
+               x86_io_apic_ops.eoi_ioapic_pin(apic, pin, entry.vector);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
        }
 
@@ -1304,25 +1280,18 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
                fasteoi = false;
        }
 
-       if (irq_remapped(cfg)) {
-               irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-               irq_remap_modify_chip_defaults(chip);
+       if (setup_remapped_irq(irq, cfg, chip))
                fasteoi = trigger != 0;
-       }
 
        hdl = fasteoi ? handle_fasteoi_irq : handle_edge_irq;
        irq_set_chip_and_handler_name(irq, chip, hdl,
                                      fasteoi ? "fasteoi" : "edge");
 }
 
-static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
-                              unsigned int destination, int vector,
-                              struct io_apic_irq_attr *attr)
+int native_setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
+                             unsigned int destination, int vector,
+                             struct io_apic_irq_attr *attr)
 {
-       if (irq_remapping_enabled)
-               return setup_ioapic_remapped_entry(irq, entry, destination,
-                                                  vector, attr);
-
        memset(entry, 0, sizeof(*entry));
 
        entry->delivery_mode = apic->irq_delivery_mode;
@@ -1370,8 +1339,8 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
                    attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin,
                    cfg->vector, irq, attr->trigger, attr->polarity, dest);
 
-       if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
-               pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
+       if (x86_io_apic_ops.setup_entry(irq, &entry, dest, cfg->vector, attr)) {
+               pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
                        mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
                __clear_irq_vector(irq, cfg);
 
@@ -1479,9 +1448,6 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
        struct IO_APIC_route_entry entry;
        unsigned int dest;
 
-       if (irq_remapping_enabled)
-               return;
-
        memset(&entry, 0, sizeof(entry));
 
        /*
@@ -1513,9 +1479,63 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
        ioapic_write_entry(ioapic_idx, pin, entry);
 }
 
-__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
+void native_io_apic_print_entries(unsigned int apic, unsigned int nr_entries)
 {
        int i;
+
+       pr_debug(" NR Dst Mask Trig IRR Pol Stat Dmod Deli Vect:\n");
+
+       for (i = 0; i <= nr_entries; i++) {
+               struct IO_APIC_route_entry entry;
+
+               entry = ioapic_read_entry(apic, i);
+
+               pr_debug(" %02x %02X  ", i, entry.dest);
+               pr_cont("%1d    %1d    %1d   %1d   %1d    "
+                       "%1d    %1d    %02X\n",
+                       entry.mask,
+                       entry.trigger,
+                       entry.irr,
+                       entry.polarity,
+                       entry.delivery_status,
+                       entry.dest_mode,
+                       entry.delivery_mode,
+                       entry.vector);
+       }
+}
+
+void intel_ir_io_apic_print_entries(unsigned int apic,
+                                   unsigned int nr_entries)
+{
+       int i;
+
+       pr_debug(" NR Indx Fmt Mask Trig IRR Pol Stat Indx2 Zero Vect:\n");
+
+       for (i = 0; i <= nr_entries; i++) {
+               struct IR_IO_APIC_route_entry *ir_entry;
+               struct IO_APIC_route_entry entry;
+
+               entry = ioapic_read_entry(apic, i);
+
+               ir_entry = (struct IR_IO_APIC_route_entry *)&entry;
+
+               pr_debug(" %02x %04X ", i, ir_entry->index);
+               pr_cont("%1d   %1d    %1d    %1d   %1d   "
+                       "%1d    %1d     %X    %02X\n",
+                       ir_entry->format,
+                       ir_entry->mask,
+                       ir_entry->trigger,
+                       ir_entry->irr,
+                       ir_entry->polarity,
+                       ir_entry->delivery_status,
+                       ir_entry->index2,
+                       ir_entry->zero,
+                       ir_entry->vector);
+       }
+}
+
+__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
+{
        union IO_APIC_reg_00 reg_00;
        union IO_APIC_reg_01 reg_01;
        union IO_APIC_reg_02 reg_02;
@@ -1568,58 +1588,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-       if (irq_remapping_enabled) {
-               printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
-                       " Pol Stat Indx2 Zero Vect:\n");
-       } else {
-               printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
-                       " Stat Dmod Deli Vect:\n");
-       }
-
-       for (i = 0; i <= reg_01.bits.entries; i++) {
-               if (irq_remapping_enabled) {
-                       struct IO_APIC_route_entry entry;
-                       struct IR_IO_APIC_route_entry *ir_entry;
-
-                       entry = ioapic_read_entry(ioapic_idx, i);
-                       ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
-                       printk(KERN_DEBUG " %02x %04X ",
-                               i,
-                               ir_entry->index
-                       );
-                       pr_cont("%1d   %1d    %1d    %1d   %1d   "
-                               "%1d    %1d     %X    %02X\n",
-                               ir_entry->format,
-                               ir_entry->mask,
-                               ir_entry->trigger,
-                               ir_entry->irr,
-                               ir_entry->polarity,
-                               ir_entry->delivery_status,
-                               ir_entry->index2,
-                               ir_entry->zero,
-                               ir_entry->vector
-                       );
-               } else {
-                       struct IO_APIC_route_entry entry;
-
-                       entry = ioapic_read_entry(ioapic_idx, i);
-                       printk(KERN_DEBUG " %02x %02X  ",
-                               i,
-                               entry.dest
-                       );
-                       pr_cont("%1d    %1d    %1d   %1d   %1d    "
-                               "%1d    %1d    %02X\n",
-                               entry.mask,
-                               entry.trigger,
-                               entry.irr,
-                               entry.polarity,
-                               entry.delivery_status,
-                               entry.dest_mode,
-                               entry.delivery_mode,
-                               entry.vector
-                       );
-               }
-       }
+       x86_io_apic_ops.print_entries(ioapic_idx, reg_01.bits.entries);
 }
 
 __apicdebuginit(void) print_IO_APICs(void)
@@ -1921,30 +1890,14 @@ void __init enable_IO_APIC(void)
        clear_IO_APIC();
 }
 
-/*
- * Not an __init, needed by the reboot code
- */
-void disable_IO_APIC(void)
+void native_disable_io_apic(void)
 {
-       /*
-        * Clear the IO-APIC before rebooting:
-        */
-       clear_IO_APIC();
-
-       if (!legacy_pic->nr_legacy_irqs)
-               return;
-
        /*
         * If the i8259 is routed through an IOAPIC
         * Put that IOAPIC in virtual wire mode
         * so legacy interrupts can be delivered.
-        *
-        * With interrupt-remapping, for now we will use virtual wire A mode,
-        * as virtual wire B is little complex (need to configure both
-        * IOAPIC RTE as well as interrupt-remapping table entry).
-        * As this gets called during crash dump, keep this simple for now.
         */
-       if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) {
+       if (ioapic_i8259.pin != -1) {
                struct IO_APIC_route_entry entry;
 
                memset(&entry, 0, sizeof(entry));
@@ -1964,12 +1917,25 @@ void disable_IO_APIC(void)
                ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
        }
 
+       if (cpu_has_apic || apic_from_smp_config())
+               disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+
+}
+
+/*
+ * Not an __init, needed by the reboot code
+ */
+void disable_IO_APIC(void)
+{
        /*
-        * Use virtual wire A mode when interrupt remapping is enabled.
+        * Clear the IO-APIC before rebooting:
         */
-       if (cpu_has_apic || apic_from_smp_config())
-               disconnect_bsp_APIC(!irq_remapping_enabled &&
-                               ioapic_i8259.pin != -1);
+       clear_IO_APIC();
+
+       if (!legacy_pic->nr_legacy_irqs)
+               return;
+
+       x86_io_apic_ops.disable();
 }
 
 #ifdef CONFIG_X86_32
@@ -2322,12 +2288,8 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
 
                apic = entry->apic;
                pin = entry->pin;
-               /*
-                * With interrupt-remapping, destination information comes
-                * from interrupt-remapping table entry.
-                */
-               if (!irq_remapped(cfg))
-                       io_apic_write(apic, 0x11 + pin*2, dest);
+
+               io_apic_write(apic, 0x11 + pin*2, dest);
                reg = io_apic_read(apic, 0x10 + pin*2);
                reg &= ~IO_APIC_REDIR_VECTOR_MASK;
                reg |= vector;
@@ -2369,9 +2331,10 @@ int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        return 0;
 }
 
-static int
-ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                   bool force)
+
+int native_ioapic_set_affinity(struct irq_data *data,
+                              const struct cpumask *mask,
+                              bool force)
 {
        unsigned int dest, irq = data->irq;
        unsigned long flags;
@@ -2548,33 +2511,6 @@ static void ack_apic_level(struct irq_data *data)
        ioapic_irqd_unmask(data, cfg, masked);
 }
 
-#ifdef CONFIG_IRQ_REMAP
-static void ir_ack_apic_edge(struct irq_data *data)
-{
-       ack_APIC_irq();
-}
-
-static void ir_ack_apic_level(struct irq_data *data)
-{
-       ack_APIC_irq();
-       eoi_ioapic_irq(data->irq, data->chip_data);
-}
-
-static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
-{
-       seq_printf(p, " IR-%s", data->chip->name);
-}
-
-static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
-{
-       chip->irq_print_chip = ir_print_prefix;
-       chip->irq_ack = ir_ack_apic_edge;
-       chip->irq_eoi = ir_ack_apic_level;
-
-       chip->irq_set_affinity = set_remapped_irq_affinity;
-}
-#endif /* CONFIG_IRQ_REMAP */
-
 static struct irq_chip ioapic_chip __read_mostly = {
        .name                   = "IO-APIC",
        .irq_startup            = startup_ioapic_irq,
@@ -2582,7 +2518,7 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .irq_unmask             = unmask_ioapic_irq,
        .irq_ack                = ack_apic_edge,
        .irq_eoi                = ack_apic_level,
-       .irq_set_affinity       = ioapic_set_affinity,
+       .irq_set_affinity       = native_ioapic_set_affinity,
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -2781,8 +2717,7 @@ static inline void __init check_timer(void)
         * 8259A.
         */
        if (pin1 == -1) {
-               if (irq_remapping_enabled)
-                       panic("BIOS bug: timer not connected to IO-APIC");
+               panic_if_irq_remap("BIOS bug: timer not connected to IO-APIC");
                pin1 = pin2;
                apic1 = apic2;
                no_pin1 = 1;
@@ -2814,8 +2749,7 @@ static inline void __init check_timer(void)
                                clear_IO_APIC_pin(0, pin1);
                        goto out;
                }
-               if (irq_remapping_enabled)
-                       panic("timer doesn't work through Interrupt-remapped IO-APIC");
+               panic_if_irq_remap("timer doesn't work through Interrupt-remapped IO-APIC");
                local_irq_disable();
                clear_IO_APIC_pin(apic1, pin1);
                if (!no_pin1)
@@ -2982,37 +2916,58 @@ device_initcall(ioapic_init_ops);
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq_nr(unsigned int from, int node)
+unsigned int __create_irqs(unsigned int from, unsigned int count, int node)
 {
-       struct irq_cfg *cfg;
+       struct irq_cfg **cfg;
        unsigned long flags;
-       unsigned int ret = 0;
-       int irq;
+       int irq, i;
 
        if (from < nr_irqs_gsi)
                from = nr_irqs_gsi;
 
-       irq = alloc_irq_from(from, node);
-       if (irq < 0)
-               return 0;
-       cfg = alloc_irq_cfg(irq, node);
-       if (!cfg) {
-               free_irq_at(irq, NULL);
+       cfg = kzalloc_node(count * sizeof(cfg[0]), GFP_KERNEL, node);
+       if (!cfg)
                return 0;
+
+       irq = alloc_irqs_from(from, count, node);
+       if (irq < 0)
+               goto out_cfgs;
+
+       for (i = 0; i < count; i++) {
+               cfg[i] = alloc_irq_cfg(irq + i, node);
+               if (!cfg[i])
+                       goto out_irqs;
        }
 
        raw_spin_lock_irqsave(&vector_lock, flags);
-       if (!__assign_irq_vector(irq, cfg, apic->target_cpus()))
-               ret = irq;
+       for (i = 0; i < count; i++)
+               if (__assign_irq_vector(irq + i, cfg[i], apic->target_cpus()))
+                       goto out_vecs;
        raw_spin_unlock_irqrestore(&vector_lock, flags);
 
-       if (ret) {
-               irq_set_chip_data(irq, cfg);
-               irq_clear_status_flags(irq, IRQ_NOREQUEST);
-       } else {
-               free_irq_at(irq, cfg);
+       for (i = 0; i < count; i++) {
+               irq_set_chip_data(irq + i, cfg[i]);
+               irq_clear_status_flags(irq + i, IRQ_NOREQUEST);
        }
-       return ret;
+
+       kfree(cfg);
+       return irq;
+
+out_vecs:
+       for (i--; i >= 0; i--)
+               __clear_irq_vector(irq + i, cfg[i]);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+out_irqs:
+       for (i = 0; i < count; i++)
+               free_irq_at(irq + i, cfg[i]);
+out_cfgs:
+       kfree(cfg);
+       return 0;
+}
+
+unsigned int create_irq_nr(unsigned int from, int node)
+{
+       return __create_irqs(from, 1, node);
 }
 
 int create_irq(void)
@@ -3037,48 +2992,35 @@ void destroy_irq(unsigned int irq)
 
        irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
 
-       if (irq_remapped(cfg))
-               free_remapped_irq(irq);
+       free_remapped_irq(irq);
+
        raw_spin_lock_irqsave(&vector_lock, flags);
        __clear_irq_vector(irq, cfg);
        raw_spin_unlock_irqrestore(&vector_lock, flags);
        free_irq_at(irq, cfg);
 }
 
+void destroy_irqs(unsigned int irq, unsigned int count)
+{
+       unsigned int i;
+
+       for (i = 0; i < count; i++)
+               destroy_irq(irq + i);
+}
+
 /*
  * MSI message composition
  */
-#ifdef CONFIG_PCI_MSI
-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
-                          struct msi_msg *msg, u8 hpet_id)
+void native_compose_msi_msg(struct pci_dev *pdev,
+                           unsigned int irq, unsigned int dest,
+                           struct msi_msg *msg, u8 hpet_id)
 {
-       struct irq_cfg *cfg;
-       int err;
-       unsigned dest;
-
-       if (disable_apic)
-               return -ENXIO;
-
-       cfg = irq_cfg(irq);
-       err = assign_irq_vector(irq, cfg, apic->target_cpus());
-       if (err)
-               return err;
+       struct irq_cfg *cfg = irq_cfg(irq);
 
-       err = apic->cpu_mask_to_apicid_and(cfg->domain,
-                                          apic->target_cpus(), &dest);
-       if (err)
-               return err;
-
-       if (irq_remapped(cfg)) {
-               compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
-               return err;
-       }
+       msg->address_hi = MSI_ADDR_BASE_HI;
 
        if (x2apic_enabled())
-               msg->address_hi = MSI_ADDR_BASE_HI |
-                                 MSI_ADDR_EXT_DEST_ID(dest);
-       else
-               msg->address_hi = MSI_ADDR_BASE_HI;
+               msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
 
        msg->address_lo =
                MSI_ADDR_BASE_LO |
@@ -3097,8 +3039,32 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
                        MSI_DATA_DELIVERY_FIXED:
                        MSI_DATA_DELIVERY_LOWPRI) |
                MSI_DATA_VECTOR(cfg->vector);
+}
 
-       return err;
+#ifdef CONFIG_PCI_MSI
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
+                          struct msi_msg *msg, u8 hpet_id)
+{
+       struct irq_cfg *cfg;
+       int err;
+       unsigned dest;
+
+       if (disable_apic)
+               return -ENXIO;
+
+       cfg = irq_cfg(irq);
+       err = assign_irq_vector(irq, cfg, apic->target_cpus());
+       if (err)
+               return err;
+
+       err = apic->cpu_mask_to_apicid_and(cfg->domain,
+                                          apic->target_cpus(), &dest);
+       if (err)
+               return err;
+
+       x86_msi.compose_msi_msg(pdev, irq, dest, msg, hpet_id);
+
+       return 0;
 }
 
 static int
@@ -3136,23 +3102,28 @@ static struct irq_chip msi_chip = {
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
+int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+                 unsigned int irq_base, unsigned int irq_offset)
 {
        struct irq_chip *chip = &msi_chip;
        struct msi_msg msg;
+       unsigned int irq = irq_base + irq_offset;
        int ret;
 
        ret = msi_compose_msg(dev, irq, &msg, -1);
        if (ret < 0)
                return ret;
 
-       irq_set_msi_desc(irq, msidesc);
-       write_msi_msg(irq, &msg);
+       irq_set_msi_desc_off(irq_base, irq_offset, msidesc);
 
-       if (irq_remapped(irq_get_chip_data(irq))) {
-               irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-               irq_remap_modify_chip_defaults(chip);
-       }
+       /*
+        * MSI-X message is written per-IRQ, the offset is always 0.
+        * MSI message denotes a contiguous group of IRQs, written for 0th IRQ.
+        */
+       if (!irq_offset)
+               write_msi_msg(irq, &msg);
+
+       setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
 
        irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 
@@ -3163,46 +3134,26 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-       int node, ret, sub_handle, index = 0;
        unsigned int irq, irq_want;
        struct msi_desc *msidesc;
+       int node, ret;
 
-       /* x86 doesn't support multiple MSI yet */
+       /* Multiple MSI vectors only supported with interrupt remapping */
        if (type == PCI_CAP_ID_MSI && nvec > 1)
                return 1;
 
        node = dev_to_node(&dev->dev);
        irq_want = nr_irqs_gsi;
-       sub_handle = 0;
        list_for_each_entry(msidesc, &dev->msi_list, list) {
                irq = create_irq_nr(irq_want, node);
                if (irq == 0)
-                       return -1;
+                       return -ENOSPC;
+
                irq_want = irq + 1;
-               if (!irq_remapping_enabled)
-                       goto no_ir;
 
-               if (!sub_handle) {
-                       /*
-                        * allocate the consecutive block of IRTE's
-                        * for 'nvec'
-                        */
-                       index = msi_alloc_remapped_irq(dev, irq, nvec);
-                       if (index < 0) {
-                               ret = index;
-                               goto error;
-                       }
-               } else {
-                       ret = msi_setup_remapped_irq(dev, irq, index,
-                                                    sub_handle);
-                       if (ret < 0)
-                               goto error;
-               }
-no_ir:
-               ret = setup_msi_irq(dev, msidesc, irq);
+               ret = setup_msi_irq(dev, msidesc, irq, 0);
                if (ret < 0)
                        goto error;
-               sub_handle++;
        }
        return 0;
 
@@ -3298,26 +3249,19 @@ static struct irq_chip hpet_msi_type = {
        .irq_retrigger = ioapic_retrigger_irq,
 };
 
-int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
+int default_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
        struct irq_chip *chip = &hpet_msi_type;
        struct msi_msg msg;
        int ret;
 
-       if (irq_remapping_enabled) {
-               ret = setup_hpet_msi_remapped(irq, id);
-               if (ret)
-                       return ret;
-       }
-
        ret = msi_compose_msg(NULL, irq, &msg, id);
        if (ret < 0)
                return ret;
 
        hpet_msi_write(irq_get_handler_data(irq), &msg);
        irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-       if (irq_remapped(irq_get_chip_data(irq)))
-               irq_remap_modify_chip_defaults(chip);
+       setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
 
        irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
        return 0;
@@ -3683,10 +3627,7 @@ void __init setup_ioapic_dest(void)
                else
                        mask = apic->target_cpus();
 
-               if (irq_remapping_enabled)
-                       set_remapped_irq_affinity(idata, mask, false);
-               else
-                       ioapic_set_affinity(idata, mask, false);
+               x86_io_apic_ops.set_affinity(idata, mask, false);
        }
 
 }
index cce91bf26676cddee4b5c42fa21016a801411079..7434d8556d091612f688e2325dc6e2c8abfcde77 100644 (file)
@@ -106,7 +106,7 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
        unsigned long mask = cpumask_bits(cpumask)[0];
        unsigned long flags;
 
-       if (WARN_ONCE(!mask, "empty IPI mask"))
+       if (!mask)
                return;
 
        local_irq_save(flags);
index e03a1e180e81789bb334918f7f92c2886142d491..562a76d433c8e286a45ecfb28bf5d88cd7ccd50a 100644 (file)
@@ -20,18 +20,19 @@ static int set_x2apic_phys_mode(char *arg)
 }
 early_param("x2apic_phys", set_x2apic_phys_mode);
 
-static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static bool x2apic_fadt_phys(void)
 {
-       if (x2apic_phys)
-               return x2apic_enabled();
-       else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
-               (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) &&
-               x2apic_enabled()) {
+       if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
+               (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
                printk(KERN_DEBUG "System requires x2apic physical mode\n");
-               return 1;
+               return true;
        }
-       else
-               return 0;
+       return false;
+}
+
+static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+       return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys());
 }
 
 static void
@@ -82,7 +83,7 @@ static void init_x2apic_ldr(void)
 
 static int x2apic_phys_probe(void)
 {
-       if (x2apic_mode && x2apic_phys)
+       if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
                return 1;
 
        return apic == &apic_x2apic_phys;
index d65464e4350343c9d379aa6d44a1ed03a1ca1f2c..8d7012b7f4020ffe3fc7cb7da0ed15cdfd05e5e7 100644 (file)
@@ -899,6 +899,7 @@ static void apm_cpu_idle(void)
        static int use_apm_idle; /* = 0 */
        static unsigned int last_jiffies; /* = 0 */
        static unsigned int last_stime; /* = 0 */
+       cputime_t stime;
 
        int apm_idle_done = 0;
        unsigned int jiffies_since_last_check = jiffies - last_jiffies;
@@ -906,23 +907,23 @@ static void apm_cpu_idle(void)
 
        WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012");
 recalc:
+       task_cputime(current, NULL, &stime);
        if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
                use_apm_idle = 0;
-               last_jiffies = jiffies;
-               last_stime = current->stime;
        } else if (jiffies_since_last_check > idle_period) {
                unsigned int idle_percentage;
 
-               idle_percentage = current->stime - last_stime;
+               idle_percentage = stime - last_stime;
                idle_percentage *= 100;
                idle_percentage /= jiffies_since_last_check;
                use_apm_idle = (idle_percentage > idle_threshold);
                if (apm_info.forbid_idle)
                        use_apm_idle = 0;
-               last_jiffies = jiffies;
-               last_stime = current->stime;
        }
 
+       last_jiffies = jiffies;
+       last_stime = stime;
+
        bucket = IDLE_LEAKY_MAX;
 
        while (!need_resched()) {
index a8f8fa9769d680869d1f9e533f79608baa181ca7..1e7e84a02ebaf4924702019c18cc5d1101609c30 100644 (file)
@@ -79,3 +79,10 @@ void __init init_hypervisor_platform(void)
        if (x86_hyper->init_platform)
                x86_hyper->init_platform();
 }
+
+bool __init hypervisor_x2apic_available(void)
+{
+       return x86_hyper                   &&
+              x86_hyper->x2apic_available &&
+              x86_hyper->x2apic_available();
+}
index fe9edec6698a3c0c15846c0e56c1a502cea05c08..84c1309c4c0c8932b90e25bf84f7f031c3ffa5a5 100644 (file)
@@ -298,8 +298,7 @@ struct _cache_attr {
                         unsigned int);
 };
 
-#ifdef CONFIG_AMD_NB
-
+#if defined(CONFIG_AMD_NB) && defined(CONFIG_SYSFS)
 /*
  * L3 cache descriptors
  */
@@ -524,9 +523,9 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
 static struct _cache_attr subcaches =
        __ATTR(subcaches, 0644, show_subcaches, store_subcaches);
 
-#else  /* CONFIG_AMD_NB */
+#else
 #define amd_init_l3_cache(x, y)
-#endif /* CONFIG_AMD_NB */
+#endif  /* CONFIG_AMD_NB && CONFIG_SYSFS */
 
 static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
index 4428fd178bce07a3a8fd75b81c61b83fc63d9258..bf0f01aea99449e53a87f092a84b3263263da911 100644 (file)
@@ -340,9 +340,6 @@ 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;
@@ -385,9 +382,6 @@ 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++;
@@ -835,7 +829,7 @@ static inline void x86_assign_hw_event(struct perf_event *event,
        } else {
                hwc->config_base = x86_pmu_config_addr(hwc->idx);
                hwc->event_base  = x86_pmu_event_addr(hwc->idx);
-               hwc->event_base_rdpmc = hwc->idx;
+               hwc->event_base_rdpmc = x86_pmu_rdpmc_index(hwc->idx);
        }
 }
 
@@ -1316,11 +1310,6 @@ static struct attribute_group x86_pmu_format_group = {
        .attrs = NULL,
 };
 
-struct perf_pmu_events_attr {
-       struct device_attribute attr;
-       u64 id;
-};
-
 /*
  * Remove all undefined events (x86_pmu.event_map(id) == 0)
  * out of events_attr attributes.
@@ -1354,11 +1343,9 @@ static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *at
 #define EVENT_VAR(_id)  event_attr_##_id
 #define EVENT_PTR(_id) &event_attr_##_id.attr.attr
 
-#define EVENT_ATTR(_name, _id)                                 \
-static struct perf_pmu_events_attr EVENT_VAR(_id) = {          \
-       .attr = __ATTR(_name, 0444, events_sysfs_show, NULL),   \
-       .id   =  PERF_COUNT_HW_##_id,                           \
-};
+#define EVENT_ATTR(_name, _id)                                         \
+       PMU_EVENT_ATTR(_name, EVENT_VAR(_id), PERF_COUNT_HW_##_id,      \
+                       events_sysfs_show)
 
 EVENT_ATTR(cpu-cycles,                 CPU_CYCLES              );
 EVENT_ATTR(instructions,               INSTRUCTIONS            );
index 115c1ea977469b0fda5b43f76e8595575effb24b..7f5c75c2afdd9552653ffd7c9babb8c871669b05 100644 (file)
@@ -325,6 +325,8 @@ struct x86_pmu {
        int             (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
        unsigned        eventsel;
        unsigned        perfctr;
+       int             (*addr_offset)(int index, bool eventsel);
+       int             (*rdpmc_index)(int index);
        u64             (*event_map)(int);
        int             max_events;
        int             num_counters;
@@ -446,28 +448,21 @@ extern u64 __read_mostly hw_cache_extra_regs
 
 u64 x86_perf_event_update(struct perf_event *event);
 
-static inline int x86_pmu_addr_offset(int index)
+static inline unsigned int x86_pmu_config_addr(int index)
 {
-       int offset;
-
-       /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
-       alternative_io(ASM_NOP2,
-                      "shll $1, %%eax",
-                      X86_FEATURE_PERFCTR_CORE,
-                      "=a" (offset),
-                      "a"  (index));
-
-       return offset;
+       return x86_pmu.eventsel + (x86_pmu.addr_offset ?
+                                  x86_pmu.addr_offset(index, true) : index);
 }
 
-static inline unsigned int x86_pmu_config_addr(int index)
+static inline unsigned int x86_pmu_event_addr(int index)
 {
-       return x86_pmu.eventsel + x86_pmu_addr_offset(index);
+       return x86_pmu.perfctr + (x86_pmu.addr_offset ?
+                                 x86_pmu.addr_offset(index, false) : index);
 }
 
-static inline unsigned int x86_pmu_event_addr(int index)
+static inline int x86_pmu_rdpmc_index(int index)
 {
-       return x86_pmu.perfctr + x86_pmu_addr_offset(index);
+       return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
 }
 
 int x86_setup_perfctr(struct perf_event *event);
index c93bc4e813a0c10303984db79cafc1d6ee5a6caf..dfdab42aed27372503d5fe33cd29a4ef97ae580b 100644 (file)
@@ -132,21 +132,102 @@ static u64 amd_pmu_event_map(int hw_event)
        return amd_perfmon_event_map[hw_event];
 }
 
-static int amd_pmu_hw_config(struct perf_event *event)
+static struct event_constraint *amd_nb_event_constraint;
+
+/*
+ * Previously calculated offsets
+ */
+static unsigned int event_offsets[X86_PMC_IDX_MAX] __read_mostly;
+static unsigned int count_offsets[X86_PMC_IDX_MAX] __read_mostly;
+static unsigned int rdpmc_indexes[X86_PMC_IDX_MAX] __read_mostly;
+
+/*
+ * Legacy CPUs:
+ *   4 counters starting at 0xc0010000 each offset by 1
+ *
+ * CPUs with core performance counter extensions:
+ *   6 counters starting at 0xc0010200 each offset by 2
+ *
+ * CPUs with north bridge performance counter extensions:
+ *   4 additional counters starting at 0xc0010240 each offset by 2
+ *   (indexed right above either one of the above core counters)
+ */
+static inline int amd_pmu_addr_offset(int index, bool eventsel)
 {
-       int ret;
+       int offset, first, base;
 
-       /* pass precise event sampling to ibs: */
-       if (event->attr.precise_ip && get_ibs_caps())
-               return -ENOENT;
+       if (!index)
+               return index;
+
+       if (eventsel)
+               offset = event_offsets[index];
+       else
+               offset = count_offsets[index];
+
+       if (offset)
+               return offset;
+
+       if (amd_nb_event_constraint &&
+           test_bit(index, amd_nb_event_constraint->idxmsk)) {
+               /*
+                * calculate the offset of NB counters with respect to
+                * base eventsel or perfctr
+                */
+
+               first = find_first_bit(amd_nb_event_constraint->idxmsk,
+                                      X86_PMC_IDX_MAX);
+
+               if (eventsel)
+                       base = MSR_F15H_NB_PERF_CTL - x86_pmu.eventsel;
+               else
+                       base = MSR_F15H_NB_PERF_CTR - x86_pmu.perfctr;
+
+               offset = base + ((index - first) << 1);
+       } else if (!cpu_has_perfctr_core)
+               offset = index;
+       else
+               offset = index << 1;
+
+       if (eventsel)
+               event_offsets[index] = offset;
+       else
+               count_offsets[index] = offset;
+
+       return offset;
+}
+
+static inline int amd_pmu_rdpmc_index(int index)
+{
+       int ret, first;
+
+       if (!index)
+               return index;
+
+       ret = rdpmc_indexes[index];
 
-       ret = x86_pmu_hw_config(event);
        if (ret)
                return ret;
 
-       if (has_branch_stack(event))
-               return -EOPNOTSUPP;
+       if (amd_nb_event_constraint &&
+           test_bit(index, amd_nb_event_constraint->idxmsk)) {
+               /*
+                * according to the mnual, ECX value of the NB counters is
+                * the index of the NB counter (0, 1, 2 or 3) plus 6
+                */
+
+               first = find_first_bit(amd_nb_event_constraint->idxmsk,
+                                      X86_PMC_IDX_MAX);
+               ret = index - first + 6;
+       } else
+               ret = index;
+
+       rdpmc_indexes[index] = ret;
+
+       return ret;
+}
 
+static int amd_core_hw_config(struct perf_event *event)
+{
        if (event->attr.exclude_host && event->attr.exclude_guest)
                /*
                 * When HO == GO == 1 the hardware treats that as GO == HO == 0
@@ -156,14 +237,37 @@ static int amd_pmu_hw_config(struct perf_event *event)
                event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
                                      ARCH_PERFMON_EVENTSEL_OS);
        else if (event->attr.exclude_host)
-               event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY;
+               event->hw.config |= AMD64_EVENTSEL_GUESTONLY;
        else if (event->attr.exclude_guest)
-               event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY;
+               event->hw.config |= AMD64_EVENTSEL_HOSTONLY;
+
+       return 0;
+}
+
+/*
+ * NB counters do not support the following event select bits:
+ *   Host/Guest only
+ *   Counter mask
+ *   Invert counter mask
+ *   Edge detect
+ *   OS/User mode
+ */
+static int amd_nb_hw_config(struct perf_event *event)
+{
+       /* for NB, we only allow system wide counting mode */
+       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+               return -EINVAL;
+
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+           event->attr.exclude_host || event->attr.exclude_guest)
+               return -EINVAL;
 
-       if (event->attr.type != PERF_TYPE_RAW)
-               return 0;
+       event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
+                             ARCH_PERFMON_EVENTSEL_OS);
 
-       event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK;
+       if (event->hw.config & ~(AMD64_RAW_EVENT_MASK_NB |
+                                ARCH_PERFMON_EVENTSEL_INT))
+               return -EINVAL;
 
        return 0;
 }
@@ -181,6 +285,11 @@ static inline int amd_is_nb_event(struct hw_perf_event *hwc)
        return (hwc->config & 0xe0) == 0xe0;
 }
 
+static inline int amd_is_perfctr_nb_event(struct hw_perf_event *hwc)
+{
+       return amd_nb_event_constraint && amd_is_nb_event(hwc);
+}
+
 static inline int amd_has_nb(struct cpu_hw_events *cpuc)
 {
        struct amd_nb *nb = cpuc->amd_nb;
@@ -188,19 +297,36 @@ static inline int amd_has_nb(struct cpu_hw_events *cpuc)
        return nb && nb->nb_id != -1;
 }
 
-static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
-                                     struct perf_event *event)
+static int amd_pmu_hw_config(struct perf_event *event)
+{
+       int ret;
+
+       /* pass precise event sampling to ibs: */
+       if (event->attr.precise_ip && get_ibs_caps())
+               return -ENOENT;
+
+       if (has_branch_stack(event))
+               return -EOPNOTSUPP;
+
+       ret = x86_pmu_hw_config(event);
+       if (ret)
+               return ret;
+
+       if (event->attr.type == PERF_TYPE_RAW)
+               event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK;
+
+       if (amd_is_perfctr_nb_event(&event->hw))
+               return amd_nb_hw_config(event);
+
+       return amd_core_hw_config(event);
+}
+
+static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+                                          struct perf_event *event)
 {
-       struct hw_perf_event *hwc = &event->hw;
        struct amd_nb *nb = cpuc->amd_nb;
        int i;
 
-       /*
-        * only care about NB events
-        */
-       if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc)))
-               return;
-
        /*
         * need to scan whole list because event may not have
         * been assigned during scheduling
@@ -215,6 +341,19 @@ static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
        }
 }
 
+static void amd_nb_interrupt_hw_config(struct hw_perf_event *hwc)
+{
+       int core_id = cpu_data(smp_processor_id()).cpu_core_id;
+
+       /* deliver interrupts only to this core */
+       if (hwc->config & ARCH_PERFMON_EVENTSEL_INT) {
+               hwc->config |= AMD64_EVENTSEL_INT_CORE_ENABLE;
+               hwc->config &= ~AMD64_EVENTSEL_INT_CORE_SEL_MASK;
+               hwc->config |= (u64)(core_id) <<
+                       AMD64_EVENTSEL_INT_CORE_SEL_SHIFT;
+       }
+}
+
  /*
   * AMD64 NorthBridge events need special treatment because
   * counter access needs to be synchronized across all cores
@@ -247,24 +386,24 @@ static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
   *
   * Given that resources are allocated (cmpxchg), they must be
   * eventually freed for others to use. This is accomplished by
-  * calling amd_put_event_constraints().
+  * calling __amd_put_nb_event_constraints()
   *
   * Non NB events are not impacted by this restriction.
   */
 static struct event_constraint *
-amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+__amd_get_nb_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
+                              struct event_constraint *c)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct amd_nb *nb = cpuc->amd_nb;
-       struct perf_event *old = NULL;
-       int max = x86_pmu.num_counters;
-       int i, j, k = -1;
+       struct perf_event *old;
+       int idx, new = -1;
 
-       /*
-        * if not NB event or no NB, then no constraints
-        */
-       if (!(amd_has_nb(cpuc) && amd_is_nb_event(hwc)))
-               return &unconstrained;
+       if (!c)
+               c = &unconstrained;
+
+       if (cpuc->is_fake)
+               return c;
 
        /*
         * detect if already present, if so reuse
@@ -276,48 +415,36 @@ amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
         * because of successive calls to x86_schedule_events() from
         * hw_perf_group_sched_in() without hw_perf_enable()
         */
-       for (i = 0; i < max; i++) {
-               /*
-                * keep track of first free slot
-                */
-               if (k == -1 && !nb->owners[i])
-                       k = i;
+       for_each_set_bit(idx, c->idxmsk, x86_pmu.num_counters) {
+               if (new == -1 || hwc->idx == idx)
+                       /* assign free slot, prefer hwc->idx */
+                       old = cmpxchg(nb->owners + idx, NULL, event);
+               else if (nb->owners[idx] == event)
+                       /* event already present */
+                       old = event;
+               else
+                       continue;
+
+               if (old && old != event)
+                       continue;
+
+               /* reassign to this slot */
+               if (new != -1)
+                       cmpxchg(nb->owners + new, event, NULL);
+               new = idx;
 
                /* already present, reuse */
-               if (nb->owners[i] == event)
-                       goto done;
-       }
-       /*
-        * not present, so grab a new slot
-        * starting either at:
-        */
-       if (hwc->idx != -1) {
-               /* previous assignment */
-               i = hwc->idx;
-       } else if (k != -1) {
-               /* start from free slot found */
-               i = k;
-       } else {
-               /*
-                * event not found, no slot found in
-                * first pass, try again from the
-                * beginning
-                */
-               i = 0;
-       }
-       j = i;
-       do {
-               old = cmpxchg(nb->owners+i, NULL, event);
-               if (!old)
+               if (old == event)
                        break;
-               if (++i == max)
-                       i = 0;
-       } while (i != j);
-done:
-       if (!old)
-               return &nb->event_constraints[i];
-
-       return &emptyconstraint;
+       }
+
+       if (new == -1)
+               return &emptyconstraint;
+
+       if (amd_is_perfctr_nb_event(hwc))
+               amd_nb_interrupt_hw_config(hwc);
+
+       return &nb->event_constraints[new];
 }
 
 static struct amd_nb *amd_alloc_nb(int cpu)
@@ -364,7 +491,7 @@ static void amd_pmu_cpu_starting(int cpu)
        struct amd_nb *nb;
        int i, nb_id;
 
-       cpuc->perf_ctr_virt_mask = AMD_PERFMON_EVENTSEL_HOSTONLY;
+       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
 
        if (boot_cpu_data.x86_max_cores < 2)
                return;
@@ -407,6 +534,26 @@ static void amd_pmu_cpu_dead(int cpu)
        }
 }
 
+static struct event_constraint *
+amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+       /*
+        * if not NB event or no NB, then no constraints
+        */
+       if (!(amd_has_nb(cpuc) && amd_is_nb_event(&event->hw)))
+               return &unconstrained;
+
+       return __amd_get_nb_event_constraints(cpuc, event,
+                                             amd_nb_event_constraint);
+}
+
+static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
+                                     struct perf_event *event)
+{
+       if (amd_has_nb(cpuc) && amd_is_nb_event(&event->hw))
+               __amd_put_nb_event_constraints(cpuc, event);
+}
+
 PMU_FORMAT_ATTR(event, "config:0-7,32-35");
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -496,6 +643,9 @@ static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT_OVERLAP(0, 0x09,
 static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
 static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
 
+static struct event_constraint amd_NBPMC96 = EVENT_CONSTRAINT(0, 0x3C0, 0);
+static struct event_constraint amd_NBPMC74 = EVENT_CONSTRAINT(0, 0xF0, 0);
+
 static struct event_constraint *
 amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
@@ -561,8 +711,8 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
                        return &amd_f15_PMC20;
                }
        case AMD_EVENT_NB:
-               /* not yet implemented */
-               return &emptyconstraint;
+               return __amd_get_nb_event_constraints(cpuc, event,
+                                                     amd_nb_event_constraint);
        default:
                return &emptyconstraint;
        }
@@ -587,6 +737,8 @@ static __initconst const struct x86_pmu amd_pmu = {
        .schedule_events        = x86_schedule_events,
        .eventsel               = MSR_K7_EVNTSEL0,
        .perfctr                = MSR_K7_PERFCTR0,
+       .addr_offset            = amd_pmu_addr_offset,
+       .rdpmc_index            = amd_pmu_rdpmc_index,
        .event_map              = amd_pmu_event_map,
        .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
        .num_counters           = AMD64_NUM_COUNTERS,
@@ -608,7 +760,7 @@ static __initconst const struct x86_pmu amd_pmu = {
 
 static int setup_event_constraints(void)
 {
-       if (boot_cpu_data.x86 >= 0x15)
+       if (boot_cpu_data.x86 == 0x15)
                x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
        return 0;
 }
@@ -638,6 +790,23 @@ static int setup_perfctr_core(void)
        return 0;
 }
 
+static int setup_perfctr_nb(void)
+{
+       if (!cpu_has_perfctr_nb)
+               return -ENODEV;
+
+       x86_pmu.num_counters += AMD64_NUM_COUNTERS_NB;
+
+       if (cpu_has_perfctr_core)
+               amd_nb_event_constraint = &amd_NBPMC96;
+       else
+               amd_nb_event_constraint = &amd_NBPMC74;
+
+       printk(KERN_INFO "perf: AMD northbridge performance counters detected\n");
+
+       return 0;
+}
+
 __init int amd_pmu_init(void)
 {
        /* Performance-monitoring supported from K7 and later: */
@@ -648,6 +817,7 @@ __init int amd_pmu_init(void)
 
        setup_event_constraints();
        setup_perfctr_core();
+       setup_perfctr_nb();
 
        /* Events are common for all AMDs */
        memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
@@ -678,7 +848,7 @@ void amd_pmu_disable_virt(void)
         * SVM is disabled the Guest-only bits still gets set and the counter
         * will not count anything.
         */
-       cpuc->perf_ctr_virt_mask = AMD_PERFMON_EVENTSEL_HOSTONLY;
+       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
 
        /* Reload all events */
        x86_pmu_disable_all();
index 93b9e1181f830ff91b9ad432e0d148a38b0e93c3..4914e94ad6e86a9565420dcac8d014ff679ab6fa 100644 (file)
@@ -2019,7 +2019,10 @@ __init int intel_pmu_init(void)
                break;
 
        case 28: /* Atom */
-       case 54: /* Cedariew */
+       case 38: /* Lincroft */
+       case 39: /* Penwell */
+       case 53: /* Cloverview */
+       case 54: /* Cedarview */
                memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
@@ -2084,6 +2087,7 @@ __init int intel_pmu_init(void)
                pr_cont("SandyBridge events, ");
                break;
        case 58: /* IvyBridge */
+       case 62: /* IvyBridge EP */
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
index 3cf3d97cce3a7ab0b02c678f2535dc5ec03d09bb..b43200dbfe7e179d65386f0dfb3b4afd3f33bf36 100644 (file)
@@ -2500,7 +2500,7 @@ static bool pcidrv_registered;
 /*
  * add a pci uncore device
  */
-static int __devinit uncore_pci_add(struct intel_uncore_type *type, struct pci_dev *pdev)
+static int uncore_pci_add(struct intel_uncore_type *type, struct pci_dev *pdev)
 {
        struct intel_uncore_pmu *pmu;
        struct intel_uncore_box *box;
@@ -2571,8 +2571,8 @@ static void uncore_pci_remove(struct pci_dev *pdev)
        kfree(box);
 }
 
-static int __devinit uncore_pci_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *id)
+static int uncore_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *id)
 {
        struct intel_uncore_type *type;
 
index f2af39f5dc3d96916f8665350445a3e8155f290b..4820c232a0b91421d1ee77b194a8881a13143753 100644 (file)
@@ -19,7 +19,7 @@ static const u64 p6_perfmon_event_map[] =
 
 };
 
-static __initconst u64 p6_hw_cache_event_ids
+static u64 p6_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
                                [PERF_COUNT_HW_CACHE_RESULT_MAX] =
index d22d0c4edcfd0ab0ef81322fbfe0ffd7e81a5d32..03a36321ec54428b098a3a874f7db83e4daafcfd 100644 (file)
@@ -33,6 +33,9 @@
 
 #define VMWARE_PORT_CMD_GETVERSION     10
 #define VMWARE_PORT_CMD_GETHZ          45
+#define VMWARE_PORT_CMD_GETVCPU_INFO   68
+#define VMWARE_PORT_CMD_LEGACY_X2APIC  3
+#define VMWARE_PORT_CMD_VCPU_RESERVED  31
 
 #define VMWARE_PORT(cmd, eax, ebx, ecx, edx)                           \
        __asm__("inl (%%dx)" :                                          \
@@ -125,10 +128,20 @@ static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)
        set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
 }
 
+/* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */
+static bool __init vmware_legacy_x2apic_available(void)
+{
+       uint32_t eax, ebx, ecx, edx;
+       VMWARE_PORT(GETVCPU_INFO, eax, ebx, ecx, edx);
+       return (eax & (1 << VMWARE_PORT_CMD_VCPU_RESERVED)) == 0 &&
+              (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
+}
+
 const __refconst struct hypervisor_x86 x86_hyper_vmware = {
        .name                   = "VMware",
        .detect                 = vmware_platform,
        .set_cpu_features       = vmware_set_cpu_features,
        .init_platform          = vmware_platform_setup,
+       .x2apic_available       = vmware_legacy_x2apic_available,
 };
 EXPORT_SYMBOL(x86_hyper_vmware);
index c763116c5359c650be0a2847ebd110bd52b3b9e2..6ed91d9980e240b73fa824f7db00d8065d145316 100644 (file)
@@ -739,7 +739,6 @@ ENTRY(ptregs_##name) ; \
 ENDPROC(ptregs_##name)
 
 PTREGSCALL1(iopl)
-PTREGSCALL2(sigaltstack)
 PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
 PTREGSCALL2(vm86)
@@ -1066,7 +1065,6 @@ ENTRY(xen_failsafe_callback)
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
-       addl $16,%esp
        jmp iret_exc
 5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
index 70641aff0c258227185b7584dfa579a9c1b4e4df..cb3c591339aa3d4242e420d181b83f3a62ced2c3 100644 (file)
@@ -864,7 +864,6 @@ END(stub_\func)
        FORK_LIKE  clone
        FORK_LIKE  fork
        FORK_LIKE  vfork
-       PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
        PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
@@ -913,8 +912,6 @@ ENTRY(stub_rt_sigreturn)
 END(stub_rt_sigreturn)
 
 #ifdef CONFIG_X86_X32_ABI
-       PTREGSCALL stub_x32_sigaltstack, sys32_sigaltstack, %rdx
-
 ENTRY(stub_x32_rt_sigreturn)
        CFI_STARTPROC
        addq $8, %rsp
@@ -1784,6 +1781,7 @@ first_nmi:
         * Leave room for the "copied" frame
         */
        subq $(5*8), %rsp
+       CFI_ADJUST_CFA_OFFSET 5*8
 
        /* Copy the stack frame to the Saved frame */
        .rept 5
@@ -1866,10 +1864,8 @@ end_repeat_nmi:
 nmi_swapgs:
        SWAPGS_UNSAFE_STACK
 nmi_restore:
-       RESTORE_ALL 8
-
-       /* Pop the extra iret frame */
-       addq $(5*8), %rsp
+       /* Pop the extra iret frame at once */
+       RESTORE_ALL 6*8
 
        /* Clear the NMI executing stack variable */
        movq $0, 5*8(%rsp)
index c18f59d10101cefc82f6638bcca758a480b70cc3..6773c918b8ccb641a02d54d3b11e3433b4b72915 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/io_apic.h>
 #include <asm/bios_ebda.h>
 #include <asm/tlbflush.h>
+#include <asm/bootparam_utils.h>
 
 static void __init i386_default_early_setup(void)
 {
@@ -30,6 +31,8 @@ static void __init i386_default_early_setup(void)
 
 void __init i386_start_kernel(void)
 {
+       sanitize_boot_params(&boot_params);
+
        memblock_reserve(__pa_symbol(&_text),
                         __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
 
index 037df57a99ac34d5ba1a5cab5abaa4554e0689d0..849fc9e63c2ffd875ba23d7bb2ea879ac756c30f 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/kdebug.h>
 #include <asm/e820.h>
 #include <asm/bios_ebda.h>
+#include <asm/bootparam_utils.h>
 
 static void __init zap_identity_mappings(void)
 {
@@ -46,6 +47,7 @@ static void __init copy_bootdata(char *real_mode_data)
        char * command_line;
 
        memcpy(&boot_params, real_mode_data, sizeof boot_params);
+       sanitize_boot_params(&boot_params);
        if (boot_params.hdr.cmd_line_ptr) {
                command_line = __va(boot_params.hdr.cmd_line_ptr);
                memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
index 8e7f6556028f7ff50d90c73eac405d3cdcb7b881..3c3f58a0808fb544987f70372d3ac202d2c75086 100644 (file)
@@ -300,37 +300,52 @@ ENTRY(startup_32_smp)
        leal -__PAGE_OFFSET(%ecx),%esp
 
 default_entry:
+#define CR0_STATE      (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
+                        X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
+                        X86_CR0_PG)
+       movl $(CR0_STATE & ~X86_CR0_PG),%eax
+       movl %eax,%cr0
+
+/*
+ * We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave
+ * bits like NT set. This would confuse the debugger if this code is traced. So
+ * initialize them properly now before switching to protected mode. That means
+ * DF in particular (even though we have cleared it earlier after copying the
+ * command line) because GCC expects it.
+ */
+       pushl $0
+       popfl
+
 /*
- *     New page tables may be in 4Mbyte page mode and may
- *     be using the global pages. 
+ * New page tables may be in 4Mbyte page mode and may 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
- *     and has flags other than the FPU flag set.
+ * NOTE! If we are on a 486 we may have no cr4 at all! Specifically, cr4 exists
+ * if and only if CPUID exists and has flags other than the FPU flag set.
  */
+       movl $-1,pa(X86_CPUID)          # preset CPUID level
        movl $X86_EFLAGS_ID,%ecx
        pushl %ecx
-       popfl
+       popfl                           # set EFLAGS=ID
        pushfl
-       popl %eax
-       pushl $0
-       popfl
-       pushfl
-       popl %edx
-       xorl %edx,%eax
-       testl %ecx,%eax
-       jz 6f                   # No ID flag = no CPUID = no CR4
+       popl %eax                       # get EFLAGS
+       testl $X86_EFLAGS_ID,%eax       # did EFLAGS.ID remained set?
+       jz enable_paging                # hw disallowed setting of ID bit
+                                       # which means no CPUID and no CR4
+
+       xorl %eax,%eax
+       cpuid
+       movl %eax,pa(X86_CPUID)         # save largest std CPUID function
 
        movl $1,%eax
        cpuid
-       andl $~1,%edx           # Ignore CPUID.FPU
-       jz 6f                   # No flags or only CPUID.FPU = no CR4
+       andl $~1,%edx                   # Ignore CPUID.FPU
+       jz enable_paging                # No flags or only CPUID.FPU = no CR4
 
        movl pa(mmu_cr4_features),%eax
        movl %eax,%cr4
 
        testb $X86_CR4_PAE, %al         # check if PAE is enabled
-       jz 6f
+       jz enable_paging
 
        /* Check if extended functions are implemented */
        movl $0x80000000, %eax
@@ -338,7 +353,7 @@ default_entry:
        /* Value must be in the range 0x80000001 to 0x8000ffff */
        subl $0x80000001, %eax
        cmpl $(0x8000ffff-0x80000001), %eax
-       ja 6f
+       ja enable_paging
 
        /* Clear bogus XD_DISABLE bits */
        call verify_cpu
@@ -347,7 +362,7 @@ default_entry:
        cpuid
        /* Execute Disable bit supported? */
        btl $(X86_FEATURE_NX & 31), %edx
-       jnc 6f
+       jnc enable_paging
 
        /* Setup EFER (Extended Feature Enable Register) */
        movl $MSR_EFER, %ecx
@@ -357,29 +372,20 @@ default_entry:
        /* Make changes effective */
        wrmsr
 
-6:
+enable_paging:
 
 /*
  * Enable paging
  */
        movl $pa(initial_page_table), %eax
        movl %eax,%cr3          /* set the page table pointer.. */
-       movl %cr0,%eax
-       orl  $X86_CR0_PG,%eax
+       movl $CR0_STATE,%eax
        movl %eax,%cr0          /* ..and set paging (PG) bit */
        ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */
 1:
        /* Shift the stack pointer to a virtual address */
        addl $__PAGE_OFFSET, %esp
 
-/*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
- */
-       pushl $0
-       popfl
-
 /*
  * start system 32-bit setup. We need to re-do some of the things done
  * in 16-bit mode for the "real" operations.
@@ -389,31 +395,11 @@ default_entry:
        jz 1f                           # Did we do this already?
        call *%eax
 1:
-       
-/* check if it is 486 or 386. */
+
 /*
- * XXX - this does a lot of unnecessary setup.  Alignment checks don't
- * apply at our cpl of 0 and the stack ought to be aligned already, and
- * we don't need to preserve eflags.
+ * Check if it is 486
  */
-       movl $-1,X86_CPUID      # -1 for no CPUID initially
-       movb $3,X86             # at least 386
-       pushfl                  # push EFLAGS
-       popl %eax               # get EFLAGS
-       movl %eax,%ecx          # save original EFLAGS
-       xorl $0x240000,%eax     # flip AC and ID bits in EFLAGS
-       pushl %eax              # copy to EFLAGS
-       popfl                   # set EFLAGS
-       pushfl                  # get new EFLAGS
-       popl %eax               # put it in eax
-       xorl %ecx,%eax          # change in flags
-       pushl %ecx              # restore original EFLAGS
-       popfl
-       testl $0x40000,%eax     # check if AC bit changed
-       je is386
-
-       movb $4,X86             # at least 486
-       testl $0x200000,%eax    # check if ID bit changed
+       cmpl $-1,X86_CPUID
        je is486
 
        /* get vendor info */
@@ -439,11 +425,10 @@ default_entry:
        movb %cl,X86_MASK
        movl %edx,X86_CAPABILITY
 
-is486: movl $0x50022,%ecx      # set AM, WP, NE and MP
-       jmp 2f
-
-is386: movl $2,%ecx            # set MP
-2:     movl %cr0,%eax
+is486:
+       movb $4,X86
+       movl $0x50022,%ecx      # set AM, WP, NE and MP
+       movl %cr0,%eax
        andl $0x80000011,%eax   # Save PG,PE,ET
        orl %ecx,%eax
        movl %eax,%cr0
@@ -468,7 +453,6 @@ is386:      movl $2,%ecx            # set MP
        xorl %eax,%eax                  # Clear LDT
        lldt %ax
 
-       cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
        jmp *(initial_code)
 
index e28670f9a589ad30d2654a9ed5983941a2c82cc9..da85a8e830a12d65e9d2f8a7f1db39b5477e9e85 100644 (file)
@@ -478,7 +478,7 @@ static int hpet_msi_next_event(unsigned long delta,
 
 static int hpet_setup_msi_irq(unsigned int irq)
 {
-       if (arch_setup_hpet_msi(irq, hpet_blockid)) {
+       if (x86_msi.setup_hpet_msi(irq, hpet_blockid)) {
                destroy_irq(irq);
                return -EINVAL;
        }
diff --git a/arch/x86/kernel/kprobes-common.h b/arch/x86/kernel/kprobes-common.h
deleted file mode 100644 (file)
index 3230b68..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef __X86_KERNEL_KPROBES_COMMON_H
-#define __X86_KERNEL_KPROBES_COMMON_H
-
-/* Kprobes and Optprobes common header */
-
-#ifdef CONFIG_X86_64
-#define SAVE_REGS_STRING                       \
-       /* Skip cs, ip, orig_ax. */             \
-       "       subq $24, %rsp\n"               \
-       "       pushq %rdi\n"                   \
-       "       pushq %rsi\n"                   \
-       "       pushq %rdx\n"                   \
-       "       pushq %rcx\n"                   \
-       "       pushq %rax\n"                   \
-       "       pushq %r8\n"                    \
-       "       pushq %r9\n"                    \
-       "       pushq %r10\n"                   \
-       "       pushq %r11\n"                   \
-       "       pushq %rbx\n"                   \
-       "       pushq %rbp\n"                   \
-       "       pushq %r12\n"                   \
-       "       pushq %r13\n"                   \
-       "       pushq %r14\n"                   \
-       "       pushq %r15\n"
-#define RESTORE_REGS_STRING                    \
-       "       popq %r15\n"                    \
-       "       popq %r14\n"                    \
-       "       popq %r13\n"                    \
-       "       popq %r12\n"                    \
-       "       popq %rbp\n"                    \
-       "       popq %rbx\n"                    \
-       "       popq %r11\n"                    \
-       "       popq %r10\n"                    \
-       "       popq %r9\n"                     \
-       "       popq %r8\n"                     \
-       "       popq %rax\n"                    \
-       "       popq %rcx\n"                    \
-       "       popq %rdx\n"                    \
-       "       popq %rsi\n"                    \
-       "       popq %rdi\n"                    \
-       /* Skip orig_ax, ip, cs */              \
-       "       addq $24, %rsp\n"
-#else
-#define SAVE_REGS_STRING                       \
-       /* Skip cs, ip, orig_ax and gs. */      \
-       "       subl $16, %esp\n"               \
-       "       pushl %fs\n"                    \
-       "       pushl %es\n"                    \
-       "       pushl %ds\n"                    \
-       "       pushl %eax\n"                   \
-       "       pushl %ebp\n"                   \
-       "       pushl %edi\n"                   \
-       "       pushl %esi\n"                   \
-       "       pushl %edx\n"                   \
-       "       pushl %ecx\n"                   \
-       "       pushl %ebx\n"
-#define RESTORE_REGS_STRING                    \
-       "       popl %ebx\n"                    \
-       "       popl %ecx\n"                    \
-       "       popl %edx\n"                    \
-       "       popl %esi\n"                    \
-       "       popl %edi\n"                    \
-       "       popl %ebp\n"                    \
-       "       popl %eax\n"                    \
-       /* Skip ds, es, fs, gs, orig_ax, and ip. Note: don't pop cs here*/\
-       "       addl $24, %esp\n"
-#endif
-
-/* Ensure if the instruction can be boostable */
-extern int can_boost(kprobe_opcode_t *instruction);
-/* Recover instruction if given address is probed */
-extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
-                                        unsigned long addr);
-/*
- * Copy an instruction and adjust the displacement if the instruction
- * uses the %rip-relative addressing mode.
- */
-extern int __copy_instruction(u8 *dest, u8 *src);
-
-/* Generate a relative-jump/call instruction */
-extern void synthesize_reljump(void *from, void *to);
-extern void synthesize_relcall(void *from, void *to);
-
-#ifdef CONFIG_OPTPROBES
-extern int arch_init_optprobes(void);
-extern int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter);
-extern unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr);
-#else  /* !CONFIG_OPTPROBES */
-static inline int arch_init_optprobes(void)
-{
-       return 0;
-}
-static inline int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
-{
-       return 0;
-}
-static inline unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
-{
-       return addr;
-}
-#endif
-#endif
diff --git a/arch/x86/kernel/kprobes-opt.c b/arch/x86/kernel/kprobes-opt.c
deleted file mode 100644 (file)
index c5e410e..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- *  Kernel Probes Jump Optimization (Optprobes)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) IBM Corporation, 2002, 2004
- * Copyright (C) Hitachi Ltd., 2012
- */
-#include <linux/kprobes.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/hardirq.h>
-#include <linux/preempt.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/kallsyms.h>
-#include <linux/ftrace.h>
-
-#include <asm/cacheflush.h>
-#include <asm/desc.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/alternative.h>
-#include <asm/insn.h>
-#include <asm/debugreg.h>
-
-#include "kprobes-common.h"
-
-unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
-{
-       struct optimized_kprobe *op;
-       struct kprobe *kp;
-       long offs;
-       int i;
-
-       for (i = 0; i < RELATIVEJUMP_SIZE; i++) {
-               kp = get_kprobe((void *)addr - i);
-               /* This function only handles jump-optimized kprobe */
-               if (kp && kprobe_optimized(kp)) {
-                       op = container_of(kp, struct optimized_kprobe, kp);
-                       /* If op->list is not empty, op is under optimizing */
-                       if (list_empty(&op->list))
-                               goto found;
-               }
-       }
-
-       return addr;
-found:
-       /*
-        * If the kprobe can be optimized, original bytes which can be
-        * overwritten by jump destination address. In this case, original
-        * bytes must be recovered from op->optinsn.copied_insn buffer.
-        */
-       memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-       if (addr == (unsigned long)kp->addr) {
-               buf[0] = kp->opcode;
-               memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
-       } else {
-               offs = addr - (unsigned long)kp->addr - 1;
-               memcpy(buf, op->optinsn.copied_insn + offs, RELATIVE_ADDR_SIZE - offs);
-       }
-
-       return (unsigned long)buf;
-}
-
-/* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
-static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
-{
-#ifdef CONFIG_X86_64
-       *addr++ = 0x48;
-       *addr++ = 0xbf;
-#else
-       *addr++ = 0xb8;
-#endif
-       *(unsigned long *)addr = val;
-}
-
-static void __used __kprobes kprobes_optinsn_template_holder(void)
-{
-       asm volatile (
-                       ".global optprobe_template_entry\n"
-                       "optprobe_template_entry:\n"
-#ifdef CONFIG_X86_64
-                       /* We don't bother saving the ss register */
-                       "       pushq %rsp\n"
-                       "       pushfq\n"
-                       SAVE_REGS_STRING
-                       "       movq %rsp, %rsi\n"
-                       ".global optprobe_template_val\n"
-                       "optprobe_template_val:\n"
-                       ASM_NOP5
-                       ASM_NOP5
-                       ".global optprobe_template_call\n"
-                       "optprobe_template_call:\n"
-                       ASM_NOP5
-                       /* Move flags to rsp */
-                       "       movq 144(%rsp), %rdx\n"
-                       "       movq %rdx, 152(%rsp)\n"
-                       RESTORE_REGS_STRING
-                       /* Skip flags entry */
-                       "       addq $8, %rsp\n"
-                       "       popfq\n"
-#else /* CONFIG_X86_32 */
-                       "       pushf\n"
-                       SAVE_REGS_STRING
-                       "       movl %esp, %edx\n"
-                       ".global optprobe_template_val\n"
-                       "optprobe_template_val:\n"
-                       ASM_NOP5
-                       ".global optprobe_template_call\n"
-                       "optprobe_template_call:\n"
-                       ASM_NOP5
-                       RESTORE_REGS_STRING
-                       "       addl $4, %esp\n"        /* skip cs */
-                       "       popf\n"
-#endif
-                       ".global optprobe_template_end\n"
-                       "optprobe_template_end:\n");
-}
-
-#define TMPL_MOVE_IDX \
-       ((long)&optprobe_template_val - (long)&optprobe_template_entry)
-#define TMPL_CALL_IDX \
-       ((long)&optprobe_template_call - (long)&optprobe_template_entry)
-#define TMPL_END_IDX \
-       ((long)&optprobe_template_end - (long)&optprobe_template_entry)
-
-#define INT3_SIZE sizeof(kprobe_opcode_t)
-
-/* Optimized kprobe call back function: called from optinsn */
-static void __kprobes optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
-{
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-       unsigned long flags;
-
-       /* This is possible if op is under delayed unoptimizing */
-       if (kprobe_disabled(&op->kp))
-               return;
-
-       local_irq_save(flags);
-       if (kprobe_running()) {
-               kprobes_inc_nmissed_count(&op->kp);
-       } else {
-               /* Save skipped registers */
-#ifdef CONFIG_X86_64
-               regs->cs = __KERNEL_CS;
-#else
-               regs->cs = __KERNEL_CS | get_kernel_rpl();
-               regs->gs = 0;
-#endif
-               regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
-               regs->orig_ax = ~0UL;
-
-               __this_cpu_write(current_kprobe, &op->kp);
-               kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-               opt_pre_handler(&op->kp, regs);
-               __this_cpu_write(current_kprobe, NULL);
-       }
-       local_irq_restore(flags);
-}
-
-static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
-{
-       int len = 0, ret;
-
-       while (len < RELATIVEJUMP_SIZE) {
-               ret = __copy_instruction(dest + len, src + len);
-               if (!ret || !can_boost(dest + len))
-                       return -EINVAL;
-               len += ret;
-       }
-       /* Check whether the address range is reserved */
-       if (ftrace_text_reserved(src, src + len - 1) ||
-           alternatives_text_reserved(src, src + len - 1) ||
-           jump_label_text_reserved(src, src + len - 1))
-               return -EBUSY;
-
-       return len;
-}
-
-/* Check whether insn is indirect jump */
-static int __kprobes insn_is_indirect_jump(struct insn *insn)
-{
-       return ((insn->opcode.bytes[0] == 0xff &&
-               (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
-               insn->opcode.bytes[0] == 0xea); /* Segment based jump */
-}
-
-/* Check whether insn jumps into specified address range */
-static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
-{
-       unsigned long target = 0;
-
-       switch (insn->opcode.bytes[0]) {
-       case 0xe0:      /* loopne */
-       case 0xe1:      /* loope */
-       case 0xe2:      /* loop */
-       case 0xe3:      /* jcxz */
-       case 0xe9:      /* near relative jump */
-       case 0xeb:      /* short relative jump */
-               break;
-       case 0x0f:
-               if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
-                       break;
-               return 0;
-       default:
-               if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
-                       break;
-               return 0;
-       }
-       target = (unsigned long)insn->next_byte + insn->immediate.value;
-
-       return (start <= target && target <= start + len);
-}
-
-/* Decode whole function to ensure any instructions don't jump into target */
-static int __kprobes can_optimize(unsigned long paddr)
-{
-       unsigned long addr, size = 0, offset = 0;
-       struct insn insn;
-       kprobe_opcode_t buf[MAX_INSN_SIZE];
-
-       /* Lookup symbol including addr */
-       if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
-               return 0;
-
-       /*
-        * Do not optimize in the entry code due to the unstable
-        * stack handling.
-        */
-       if ((paddr >= (unsigned long)__entry_text_start) &&
-           (paddr <  (unsigned long)__entry_text_end))
-               return 0;
-
-       /* Check there is enough space for a relative jump. */
-       if (size - offset < RELATIVEJUMP_SIZE)
-               return 0;
-
-       /* Decode instructions */
-       addr = paddr - offset;
-       while (addr < paddr - offset + size) { /* Decode until function end */
-               if (search_exception_tables(addr))
-                       /*
-                        * Since some fixup code will jumps into this function,
-                        * we can't optimize kprobe in this function.
-                        */
-                       return 0;
-               kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, addr));
-               insn_get_length(&insn);
-               /* Another subsystem puts a breakpoint */
-               if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
-                       return 0;
-               /* Recover address */
-               insn.kaddr = (void *)addr;
-               insn.next_byte = (void *)(addr + insn.length);
-               /* Check any instructions don't jump into target */
-               if (insn_is_indirect_jump(&insn) ||
-                   insn_jump_into_range(&insn, paddr + INT3_SIZE,
-                                        RELATIVE_ADDR_SIZE))
-                       return 0;
-               addr += insn.length;
-       }
-
-       return 1;
-}
-
-/* Check optimized_kprobe can actually be optimized. */
-int __kprobes arch_check_optimized_kprobe(struct optimized_kprobe *op)
-{
-       int i;
-       struct kprobe *p;
-
-       for (i = 1; i < op->optinsn.size; i++) {
-               p = get_kprobe(op->kp.addr + i);
-               if (p && !kprobe_disabled(p))
-                       return -EEXIST;
-       }
-
-       return 0;
-}
-
-/* Check the addr is within the optimized instructions. */
-int __kprobes
-arch_within_optimized_kprobe(struct optimized_kprobe *op, unsigned long addr)
-{
-       return ((unsigned long)op->kp.addr <= addr &&
-               (unsigned long)op->kp.addr + op->optinsn.size > addr);
-}
-
-/* Free optimized instruction slot */
-static __kprobes
-void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
-{
-       if (op->optinsn.insn) {
-               free_optinsn_slot(op->optinsn.insn, dirty);
-               op->optinsn.insn = NULL;
-               op->optinsn.size = 0;
-       }
-}
-
-void __kprobes arch_remove_optimized_kprobe(struct optimized_kprobe *op)
-{
-       __arch_remove_optimized_kprobe(op, 1);
-}
-
-/*
- * Copy replacing target instructions
- * Target instructions MUST be relocatable (checked inside)
- * This is called when new aggr(opt)probe is allocated or reused.
- */
-int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op)
-{
-       u8 *buf;
-       int ret;
-       long rel;
-
-       if (!can_optimize((unsigned long)op->kp.addr))
-               return -EILSEQ;
-
-       op->optinsn.insn = get_optinsn_slot();
-       if (!op->optinsn.insn)
-               return -ENOMEM;
-
-       /*
-        * Verify if the address gap is in 2GB range, because this uses
-        * a relative jump.
-        */
-       rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
-       if (abs(rel) > 0x7fffffff)
-               return -ERANGE;
-
-       buf = (u8 *)op->optinsn.insn;
-
-       /* Copy instructions into the out-of-line buffer */
-       ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
-       if (ret < 0) {
-               __arch_remove_optimized_kprobe(op, 0);
-               return ret;
-       }
-       op->optinsn.size = ret;
-
-       /* Copy arch-dep-instance from template */
-       memcpy(buf, &optprobe_template_entry, TMPL_END_IDX);
-
-       /* Set probe information */
-       synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
-
-       /* Set probe function call */
-       synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback);
-
-       /* Set returning jmp instruction at the tail of out-of-line buffer */
-       synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
-                          (u8 *)op->kp.addr + op->optinsn.size);
-
-       flush_icache_range((unsigned long) buf,
-                          (unsigned long) buf + TMPL_END_IDX +
-                          op->optinsn.size + RELATIVEJUMP_SIZE);
-       return 0;
-}
-
-#define MAX_OPTIMIZE_PROBES 256
-static struct text_poke_param *jump_poke_params;
-static struct jump_poke_buffer {
-       u8 buf[RELATIVEJUMP_SIZE];
-} *jump_poke_bufs;
-
-static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm,
-                                           u8 *insn_buf,
-                                           struct optimized_kprobe *op)
-{
-       s32 rel = (s32)((long)op->optinsn.insn -
-                       ((long)op->kp.addr + RELATIVEJUMP_SIZE));
-
-       /* Backup instructions which will be replaced by jump address */
-       memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
-              RELATIVE_ADDR_SIZE);
-
-       insn_buf[0] = RELATIVEJUMP_OPCODE;
-       *(s32 *)(&insn_buf[1]) = rel;
-
-       tprm->addr = op->kp.addr;
-       tprm->opcode = insn_buf;
-       tprm->len = RELATIVEJUMP_SIZE;
-}
-
-/*
- * Replace breakpoints (int3) with relative jumps.
- * Caller must call with locking kprobe_mutex and text_mutex.
- */
-void __kprobes arch_optimize_kprobes(struct list_head *oplist)
-{
-       struct optimized_kprobe *op, *tmp;
-       int c = 0;
-
-       list_for_each_entry_safe(op, tmp, oplist, list) {
-               WARN_ON(kprobe_disabled(&op->kp));
-               /* Setup param */
-               setup_optimize_kprobe(&jump_poke_params[c],
-                                     jump_poke_bufs[c].buf, op);
-               list_del_init(&op->list);
-               if (++c >= MAX_OPTIMIZE_PROBES)
-                       break;
-       }
-
-       /*
-        * text_poke_smp doesn't support NMI/MCE code modifying.
-        * However, since kprobes itself also doesn't support NMI/MCE
-        * code probing, it's not a problem.
-        */
-       text_poke_smp_batch(jump_poke_params, c);
-}
-
-static void __kprobes setup_unoptimize_kprobe(struct text_poke_param *tprm,
-                                             u8 *insn_buf,
-                                             struct optimized_kprobe *op)
-{
-       /* Set int3 to first byte for kprobes */
-       insn_buf[0] = BREAKPOINT_INSTRUCTION;
-       memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
-
-       tprm->addr = op->kp.addr;
-       tprm->opcode = insn_buf;
-       tprm->len = RELATIVEJUMP_SIZE;
-}
-
-/*
- * Recover original instructions and breakpoints from relative jumps.
- * Caller must call with locking kprobe_mutex.
- */
-extern void arch_unoptimize_kprobes(struct list_head *oplist,
-                                   struct list_head *done_list)
-{
-       struct optimized_kprobe *op, *tmp;
-       int c = 0;
-
-       list_for_each_entry_safe(op, tmp, oplist, list) {
-               /* Setup param */
-               setup_unoptimize_kprobe(&jump_poke_params[c],
-                                       jump_poke_bufs[c].buf, op);
-               list_move(&op->list, done_list);
-               if (++c >= MAX_OPTIMIZE_PROBES)
-                       break;
-       }
-
-       /*
-        * text_poke_smp doesn't support NMI/MCE code modifying.
-        * However, since kprobes itself also doesn't support NMI/MCE
-        * code probing, it's not a problem.
-        */
-       text_poke_smp_batch(jump_poke_params, c);
-}
-
-/* Replace a relative jump with a breakpoint (int3).  */
-void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op)
-{
-       u8 buf[RELATIVEJUMP_SIZE];
-
-       /* Set int3 to first byte for kprobes */
-       buf[0] = BREAKPOINT_INSTRUCTION;
-       memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
-       text_poke_smp(op->kp.addr, buf, RELATIVEJUMP_SIZE);
-}
-
-int  __kprobes
-setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
-{
-       struct optimized_kprobe *op;
-
-       if (p->flags & KPROBE_FLAG_OPTIMIZED) {
-               /* This kprobe is really able to run optimized path. */
-               op = container_of(p, struct optimized_kprobe, kp);
-               /* Detour through copied instructions */
-               regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
-               if (!reenter)
-                       reset_current_kprobe();
-               preempt_enable_no_resched();
-               return 1;
-       }
-       return 0;
-}
-
-int __kprobes arch_init_optprobes(void)
-{
-       /* Allocate code buffer and parameter array */
-       jump_poke_bufs = kmalloc(sizeof(struct jump_poke_buffer) *
-                                MAX_OPTIMIZE_PROBES, GFP_KERNEL);
-       if (!jump_poke_bufs)
-               return -ENOMEM;
-
-       jump_poke_params = kmalloc(sizeof(struct text_poke_param) *
-                                  MAX_OPTIMIZE_PROBES, GFP_KERNEL);
-       if (!jump_poke_params) {
-               kfree(jump_poke_bufs);
-               jump_poke_bufs = NULL;
-               return -ENOMEM;
-       }
-
-       return 0;
-}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
deleted file mode 100644 (file)
index 57916c0..0000000
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- *  Kernel Probes (KProbes)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) IBM Corporation, 2002, 2004
- *
- * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
- *             Probes initial implementation ( includes contributions from
- *             Rusty Russell).
- * 2004-July   Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
- *             interface to access function arguments.
- * 2004-Oct    Jim Keniston <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
- *             <prasanna@in.ibm.com> adapted for x86_64 from i386.
- * 2005-Mar    Roland McGrath <roland@redhat.com>
- *             Fixed to handle %rip-relative addressing mode correctly.
- * 2005-May    Hien Nguyen <hien@us.ibm.com>, Jim Keniston
- *             <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
- *             <prasanna@in.ibm.com> added function-return probes.
- * 2005-May    Rusty Lynch <rusty.lynch@intel.com>
- *             Added function return probes functionality
- * 2006-Feb    Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp> added
- *             kprobe-booster and kretprobe-booster for i386.
- * 2007-Dec    Masami Hiramatsu <mhiramat@redhat.com> added kprobe-booster
- *             and kretprobe-booster for x86-64
- * 2007-Dec    Masami Hiramatsu <mhiramat@redhat.com>, Arjan van de Ven
- *             <arjan@infradead.org> and Jim Keniston <jkenisto@us.ibm.com>
- *             unified x86 kprobes code.
- */
-#include <linux/kprobes.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/hardirq.h>
-#include <linux/preempt.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/kallsyms.h>
-#include <linux/ftrace.h>
-
-#include <asm/cacheflush.h>
-#include <asm/desc.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/alternative.h>
-#include <asm/insn.h>
-#include <asm/debugreg.h>
-
-#include "kprobes-common.h"
-
-void jprobe_return_end(void);
-
-DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
-DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
-
-#define stack_addr(regs) ((unsigned long *)kernel_stack_pointer(regs))
-
-#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
-       (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
-         (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
-         (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
-         (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
-        << (row % 32))
-       /*
-        * Undefined/reserved opcodes, conditional jump, Opcode Extension
-        * Groups, and some special opcodes can not boost.
-        * This is non-const and volatile to keep gcc from statically
-        * optimizing it out, as variable_test_bit makes gcc think only
-        * *(unsigned long*) is used. 
-        */
-static volatile u32 twobyte_is_boostable[256 / 32] = {
-       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
-       /*      ----------------------------------------------          */
-       W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
-       W(0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 10 */
-       W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 20 */
-       W(0x30, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */
-       W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
-       W(0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 50 */
-       W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1) | /* 60 */
-       W(0x70, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */
-       W(0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 80 */
-       W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
-       W(0xa0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) | /* a0 */
-       W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1) , /* b0 */
-       W(0xc0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */
-       W(0xd0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) , /* d0 */
-       W(0xe0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) | /* e0 */
-       W(0xf0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0)   /* f0 */
-       /*      -----------------------------------------------         */
-       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
-};
-#undef W
-
-struct kretprobe_blackpoint kretprobe_blacklist[] = {
-       {"__switch_to", }, /* This function switches only current task, but
-                             doesn't switch kernel stack.*/
-       {NULL, NULL}    /* Terminator */
-};
-
-const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
-
-static void __kprobes __synthesize_relative_insn(void *from, void *to, u8 op)
-{
-       struct __arch_relative_insn {
-               u8 op;
-               s32 raddr;
-       } __attribute__((packed)) *insn;
-
-       insn = (struct __arch_relative_insn *)from;
-       insn->raddr = (s32)((long)(to) - ((long)(from) + 5));
-       insn->op = op;
-}
-
-/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
-void __kprobes synthesize_reljump(void *from, void *to)
-{
-       __synthesize_relative_insn(from, to, RELATIVEJUMP_OPCODE);
-}
-
-/* Insert a call instruction at address 'from', which calls address 'to'.*/
-void __kprobes synthesize_relcall(void *from, void *to)
-{
-       __synthesize_relative_insn(from, to, RELATIVECALL_OPCODE);
-}
-
-/*
- * Skip the prefixes of the instruction.
- */
-static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn)
-{
-       insn_attr_t attr;
-
-       attr = inat_get_opcode_attribute((insn_byte_t)*insn);
-       while (inat_is_legacy_prefix(attr)) {
-               insn++;
-               attr = inat_get_opcode_attribute((insn_byte_t)*insn);
-       }
-#ifdef CONFIG_X86_64
-       if (inat_is_rex_prefix(attr))
-               insn++;
-#endif
-       return insn;
-}
-
-/*
- * Returns non-zero if opcode is boostable.
- * RIP relative instructions are adjusted at copying time in 64 bits mode
- */
-int __kprobes can_boost(kprobe_opcode_t *opcodes)
-{
-       kprobe_opcode_t opcode;
-       kprobe_opcode_t *orig_opcodes = opcodes;
-
-       if (search_exception_tables((unsigned long)opcodes))
-               return 0;       /* Page fault may occur on this address. */
-
-retry:
-       if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
-               return 0;
-       opcode = *(opcodes++);
-
-       /* 2nd-byte opcode */
-       if (opcode == 0x0f) {
-               if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
-                       return 0;
-               return test_bit(*opcodes,
-                               (unsigned long *)twobyte_is_boostable);
-       }
-
-       switch (opcode & 0xf0) {
-#ifdef CONFIG_X86_64
-       case 0x40:
-               goto retry; /* REX prefix is boostable */
-#endif
-       case 0x60:
-               if (0x63 < opcode && opcode < 0x67)
-                       goto retry; /* prefixes */
-               /* can't boost Address-size override and bound */
-               return (opcode != 0x62 && opcode != 0x67);
-       case 0x70:
-               return 0; /* can't boost conditional jump */
-       case 0xc0:
-               /* can't boost software-interruptions */
-               return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
-       case 0xd0:
-               /* can boost AA* and XLAT */
-               return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
-       case 0xe0:
-               /* can boost in/out and absolute jmps */
-               return ((opcode & 0x04) || opcode == 0xea);
-       case 0xf0:
-               if ((opcode & 0x0c) == 0 && opcode != 0xf1)
-                       goto retry; /* lock/rep(ne) prefix */
-               /* clear and set flags are boostable */
-               return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
-       default:
-               /* segment override prefixes are boostable */
-               if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
-                       goto retry; /* prefixes */
-               /* CS override prefix and call are not boostable */
-               return (opcode != 0x2e && opcode != 0x9a);
-       }
-}
-
-static unsigned long
-__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
-{
-       struct kprobe *kp;
-
-       kp = get_kprobe((void *)addr);
-       /* There is no probe, return original address */
-       if (!kp)
-               return addr;
-
-       /*
-        *  Basically, kp->ainsn.insn has an original instruction.
-        *  However, RIP-relative instruction can not do single-stepping
-        *  at different place, __copy_instruction() tweaks the displacement of
-        *  that instruction. In that case, we can't recover the instruction
-        *  from the kp->ainsn.insn.
-        *
-        *  On the other hand, kp->opcode has a copy of the first byte of
-        *  the probed instruction, which is overwritten by int3. And
-        *  the instruction at kp->addr is not modified by kprobes except
-        *  for the first byte, we can recover the original instruction
-        *  from it and kp->opcode.
-        */
-       memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-       buf[0] = kp->opcode;
-       return (unsigned long)buf;
-}
-
-/*
- * Recover the probed instruction at addr for further analysis.
- * Caller must lock kprobes by kprobe_mutex, or disable preemption
- * for preventing to release referencing kprobes.
- */
-unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
-{
-       unsigned long __addr;
-
-       __addr = __recover_optprobed_insn(buf, addr);
-       if (__addr != addr)
-               return __addr;
-
-       return __recover_probed_insn(buf, addr);
-}
-
-/* Check if paddr is at an instruction boundary */
-static int __kprobes can_probe(unsigned long paddr)
-{
-       unsigned long addr, __addr, offset = 0;
-       struct insn insn;
-       kprobe_opcode_t buf[MAX_INSN_SIZE];
-
-       if (!kallsyms_lookup_size_offset(paddr, NULL, &offset))
-               return 0;
-
-       /* Decode instructions */
-       addr = paddr - offset;
-       while (addr < paddr) {
-               /*
-                * Check if the instruction has been modified by another
-                * kprobe, in which case we replace the breakpoint by the
-                * original instruction in our buffer.
-                * Also, jump optimization will change the breakpoint to
-                * relative-jump. Since the relative-jump itself is
-                * normally used, we just go through if there is no kprobe.
-                */
-               __addr = recover_probed_instruction(buf, addr);
-               kernel_insn_init(&insn, (void *)__addr);
-               insn_get_length(&insn);
-
-               /*
-                * Another debugging subsystem might insert this breakpoint.
-                * In that case, we can't recover it.
-                */
-               if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
-                       return 0;
-               addr += insn.length;
-       }
-
-       return (addr == paddr);
-}
-
-/*
- * Returns non-zero if opcode modifies the interrupt flag.
- */
-static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
-{
-       /* Skip prefixes */
-       insn = skip_prefixes(insn);
-
-       switch (*insn) {
-       case 0xfa:              /* cli */
-       case 0xfb:              /* sti */
-       case 0xcf:              /* iret/iretd */
-       case 0x9d:              /* popf/popfd */
-               return 1;
-       }
-
-       return 0;
-}
-
-/*
- * Copy an instruction and adjust the displacement if the instruction
- * uses the %rip-relative addressing mode.
- * If it does, Return the address of the 32-bit displacement word.
- * If not, return null.
- * Only applicable to 64-bit x86.
- */
-int __kprobes __copy_instruction(u8 *dest, u8 *src)
-{
-       struct insn insn;
-       kprobe_opcode_t buf[MAX_INSN_SIZE];
-
-       kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, (unsigned long)src));
-       insn_get_length(&insn);
-       /* Another subsystem puts a breakpoint, failed to recover */
-       if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
-               return 0;
-       memcpy(dest, insn.kaddr, insn.length);
-
-#ifdef CONFIG_X86_64
-       if (insn_rip_relative(&insn)) {
-               s64 newdisp;
-               u8 *disp;
-               kernel_insn_init(&insn, dest);
-               insn_get_displacement(&insn);
-               /*
-                * The copied instruction uses the %rip-relative addressing
-                * mode.  Adjust the displacement for the difference between
-                * the original location of this instruction and the location
-                * of the copy that will actually be run.  The tricky bit here
-                * is making sure that the sign extension happens correctly in
-                * this calculation, since we need a signed 32-bit result to
-                * be sign-extended to 64 bits when it's added to the %rip
-                * value and yield the same 64-bit result that the sign-
-                * extension of the original signed 32-bit displacement would
-                * have given.
-                */
-               newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest;
-               BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check.  */
-               disp = (u8 *) dest + insn_offset_displacement(&insn);
-               *(s32 *) disp = (s32) newdisp;
-       }
-#endif
-       return insn.length;
-}
-
-static void __kprobes arch_copy_kprobe(struct kprobe *p)
-{
-       /* Copy an instruction with recovering if other optprobe modifies it.*/
-       __copy_instruction(p->ainsn.insn, p->addr);
-
-       /*
-        * __copy_instruction can modify the displacement of the instruction,
-        * but it doesn't affect boostable check.
-        */
-       if (can_boost(p->ainsn.insn))
-               p->ainsn.boostable = 0;
-       else
-               p->ainsn.boostable = -1;
-
-       /* Also, displacement change doesn't affect the first byte */
-       p->opcode = p->ainsn.insn[0];
-}
-
-int __kprobes arch_prepare_kprobe(struct kprobe *p)
-{
-       if (alternatives_text_reserved(p->addr, p->addr))
-               return -EINVAL;
-
-       if (!can_probe((unsigned long)p->addr))
-               return -EILSEQ;
-       /* insn: must be on special executable page on x86. */
-       p->ainsn.insn = get_insn_slot();
-       if (!p->ainsn.insn)
-               return -ENOMEM;
-       arch_copy_kprobe(p);
-       return 0;
-}
-
-void __kprobes arch_arm_kprobe(struct kprobe *p)
-{
-       text_poke(p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION}), 1);
-}
-
-void __kprobes arch_disarm_kprobe(struct kprobe *p)
-{
-       text_poke(p->addr, &p->opcode, 1);
-}
-
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-       if (p->ainsn.insn) {
-               free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
-               p->ainsn.insn = NULL;
-       }
-}
-
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
-{
-       kcb->prev_kprobe.kp = kprobe_running();
-       kcb->prev_kprobe.status = kcb->kprobe_status;
-       kcb->prev_kprobe.old_flags = kcb->kprobe_old_flags;
-       kcb->prev_kprobe.saved_flags = kcb->kprobe_saved_flags;
-}
-
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
-{
-       __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
-       kcb->kprobe_status = kcb->prev_kprobe.status;
-       kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags;
-       kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
-}
-
-static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
-                               struct kprobe_ctlblk *kcb)
-{
-       __this_cpu_write(current_kprobe, p);
-       kcb->kprobe_saved_flags = kcb->kprobe_old_flags
-               = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF));
-       if (is_IF_modifier(p->ainsn.insn))
-               kcb->kprobe_saved_flags &= ~X86_EFLAGS_IF;
-}
-
-static void __kprobes clear_btf(void)
-{
-       if (test_thread_flag(TIF_BLOCKSTEP)) {
-               unsigned long debugctl = get_debugctlmsr();
-
-               debugctl &= ~DEBUGCTLMSR_BTF;
-               update_debugctlmsr(debugctl);
-       }
-}
-
-static void __kprobes restore_btf(void)
-{
-       if (test_thread_flag(TIF_BLOCKSTEP)) {
-               unsigned long debugctl = get_debugctlmsr();
-
-               debugctl |= DEBUGCTLMSR_BTF;
-               update_debugctlmsr(debugctl);
-       }
-}
-
-void __kprobes
-arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
-{
-       unsigned long *sara = stack_addr(regs);
-
-       ri->ret_addr = (kprobe_opcode_t *) *sara;
-
-       /* Replace the return addr with trampoline addr */
-       *sara = (unsigned long) &kretprobe_trampoline;
-}
-
-static void __kprobes
-setup_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb, int reenter)
-{
-       if (setup_detour_execution(p, regs, reenter))
-               return;
-
-#if !defined(CONFIG_PREEMPT)
-       if (p->ainsn.boostable == 1 && !p->post_handler) {
-               /* Boost up -- we can execute copied instructions directly */
-               if (!reenter)
-                       reset_current_kprobe();
-               /*
-                * Reentering boosted probe doesn't reset current_kprobe,
-                * nor set current_kprobe, because it doesn't use single
-                * stepping.
-                */
-               regs->ip = (unsigned long)p->ainsn.insn;
-               preempt_enable_no_resched();
-               return;
-       }
-#endif
-       if (reenter) {
-               save_previous_kprobe(kcb);
-               set_current_kprobe(p, regs, kcb);
-               kcb->kprobe_status = KPROBE_REENTER;
-       } else
-               kcb->kprobe_status = KPROBE_HIT_SS;
-       /* Prepare real single stepping */
-       clear_btf();
-       regs->flags |= X86_EFLAGS_TF;
-       regs->flags &= ~X86_EFLAGS_IF;
-       /* single step inline if the instruction is an int3 */
-       if (p->opcode == BREAKPOINT_INSTRUCTION)
-               regs->ip = (unsigned long)p->addr;
-       else
-               regs->ip = (unsigned long)p->ainsn.insn;
-}
-
-/*
- * We have reentered the kprobe_handler(), since another probe was hit while
- * within the handler. We save the original kprobes variables and just single
- * step on the instruction of the new probe without calling any user handlers.
- */
-static int __kprobes
-reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
-{
-       switch (kcb->kprobe_status) {
-       case KPROBE_HIT_SSDONE:
-       case KPROBE_HIT_ACTIVE:
-               kprobes_inc_nmissed_count(p);
-               setup_singlestep(p, regs, kcb, 1);
-               break;
-       case KPROBE_HIT_SS:
-               /* A probe has been hit in the codepath leading up to, or just
-                * after, single-stepping of a probed instruction. This entire
-                * codepath should strictly reside in .kprobes.text section.
-                * Raise a BUG or we'll continue in an endless reentering loop
-                * and eventually a stack overflow.
-                */
-               printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
-                      p->addr);
-               dump_kprobe(p);
-               BUG();
-       default:
-               /* impossible cases */
-               WARN_ON(1);
-               return 0;
-       }
-
-       return 1;
-}
-
-#ifdef KPROBES_CAN_USE_FTRACE
-static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs,
-                                     struct kprobe_ctlblk *kcb)
-{
-       /*
-        * Emulate singlestep (and also recover regs->ip)
-        * as if there is a 5byte nop
-        */
-       regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
-       if (unlikely(p->post_handler)) {
-               kcb->kprobe_status = KPROBE_HIT_SSDONE;
-               p->post_handler(p, regs, 0);
-       }
-       __this_cpu_write(current_kprobe, NULL);
-}
-#endif
-
-/*
- * Interrupts are disabled on entry as trap3 is an interrupt gate and they
- * remain disabled throughout this function.
- */
-static int __kprobes kprobe_handler(struct pt_regs *regs)
-{
-       kprobe_opcode_t *addr;
-       struct kprobe *p;
-       struct kprobe_ctlblk *kcb;
-
-       addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
-       /*
-        * We don't want to be preempted for the entire
-        * duration of kprobe processing. We conditionally
-        * re-enable preemption at the end of this function,
-        * and also in reenter_kprobe() and setup_singlestep().
-        */
-       preempt_disable();
-
-       kcb = get_kprobe_ctlblk();
-       p = get_kprobe(addr);
-
-       if (p) {
-               if (kprobe_running()) {
-                       if (reenter_kprobe(p, regs, kcb))
-                               return 1;
-               } else {
-                       set_current_kprobe(p, regs, kcb);
-                       kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-
-                       /*
-                        * If we have no pre-handler or it returned 0, we
-                        * continue with normal processing.  If we have a
-                        * pre-handler and it returned non-zero, it prepped
-                        * for calling the break_handler below on re-entry
-                        * for jprobe processing, so get out doing nothing
-                        * more here.
-                        */
-                       if (!p->pre_handler || !p->pre_handler(p, regs))
-                               setup_singlestep(p, regs, kcb, 0);
-                       return 1;
-               }
-       } else if (*addr != BREAKPOINT_INSTRUCTION) {
-               /*
-                * The breakpoint instruction was removed right
-                * after we hit it.  Another cpu has removed
-                * either a probepoint or a debugger breakpoint
-                * at this address.  In either case, no further
-                * handling of this interrupt is appropriate.
-                * Back up over the (now missing) int3 and run
-                * the original instruction.
-                */
-               regs->ip = (unsigned long)addr;
-               preempt_enable_no_resched();
-               return 1;
-       } else if (kprobe_running()) {
-               p = __this_cpu_read(current_kprobe);
-               if (p->break_handler && p->break_handler(p, regs)) {
-#ifdef KPROBES_CAN_USE_FTRACE
-                       if (kprobe_ftrace(p)) {
-                               skip_singlestep(p, regs, kcb);
-                               return 1;
-                       }
-#endif
-                       setup_singlestep(p, regs, kcb, 0);
-                       return 1;
-               }
-       } /* else: not a kprobe fault; let the kernel handle it */
-
-       preempt_enable_no_resched();
-       return 0;
-}
-
-/*
- * When a retprobed function returns, this code saves registers and
- * calls trampoline_handler() runs, which calls the kretprobe's handler.
- */
-static void __used __kprobes kretprobe_trampoline_holder(void)
-{
-       asm volatile (
-                       ".global kretprobe_trampoline\n"
-                       "kretprobe_trampoline: \n"
-#ifdef CONFIG_X86_64
-                       /* We don't bother saving the ss register */
-                       "       pushq %rsp\n"
-                       "       pushfq\n"
-                       SAVE_REGS_STRING
-                       "       movq %rsp, %rdi\n"
-                       "       call trampoline_handler\n"
-                       /* Replace saved sp with true return address. */
-                       "       movq %rax, 152(%rsp)\n"
-                       RESTORE_REGS_STRING
-                       "       popfq\n"
-#else
-                       "       pushf\n"
-                       SAVE_REGS_STRING
-                       "       movl %esp, %eax\n"
-                       "       call trampoline_handler\n"
-                       /* Move flags to cs */
-                       "       movl 56(%esp), %edx\n"
-                       "       movl %edx, 52(%esp)\n"
-                       /* Replace saved flags with true return address. */
-                       "       movl %eax, 56(%esp)\n"
-                       RESTORE_REGS_STRING
-                       "       popf\n"
-#endif
-                       "       ret\n");
-}
-
-/*
- * Called from kretprobe_trampoline
- */
-static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
-{
-       struct kretprobe_instance *ri = NULL;
-       struct hlist_head *head, empty_rp;
-       struct hlist_node *node, *tmp;
-       unsigned long flags, orig_ret_address = 0;
-       unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
-       kprobe_opcode_t *correct_ret_addr = NULL;
-
-       INIT_HLIST_HEAD(&empty_rp);
-       kretprobe_hash_lock(current, &head, &flags);
-       /* fixup registers */
-#ifdef CONFIG_X86_64
-       regs->cs = __KERNEL_CS;
-#else
-       regs->cs = __KERNEL_CS | get_kernel_rpl();
-       regs->gs = 0;
-#endif
-       regs->ip = trampoline_address;
-       regs->orig_ax = ~0UL;
-
-       /*
-        * It is possible to have multiple instances associated with a given
-        * task either because multiple functions in the call path have
-        * return probes installed on them, and/or more than one
-        * return probe was registered for a target function.
-        *
-        * We can handle this because:
-        *     - instances are always pushed into the head of the list
-        *     - when multiple return probes are registered for the same
-        *       function, the (chronologically) first instance's ret_addr
-        *       will be the real return address, and all the rest will
-        *       point to kretprobe_trampoline.
-        */
-       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
-               if (ri->task != current)
-                       /* another task is sharing our hash bucket */
-                       continue;
-
-               orig_ret_address = (unsigned long)ri->ret_addr;
-
-               if (orig_ret_address != trampoline_address)
-                       /*
-                        * This is the real return address. Any other
-                        * instances associated with this task are for
-                        * other calls deeper on the call stack
-                        */
-                       break;
-       }
-
-       kretprobe_assert(ri, orig_ret_address, trampoline_address);
-
-       correct_ret_addr = ri->ret_addr;
-       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
-               if (ri->task != current)
-                       /* another task is sharing our hash bucket */
-                       continue;
-
-               orig_ret_address = (unsigned long)ri->ret_addr;
-               if (ri->rp && ri->rp->handler) {
-                       __this_cpu_write(current_kprobe, &ri->rp->kp);
-                       get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
-                       ri->ret_addr = correct_ret_addr;
-                       ri->rp->handler(ri, regs);
-                       __this_cpu_write(current_kprobe, NULL);
-               }
-
-               recycle_rp_inst(ri, &empty_rp);
-
-               if (orig_ret_address != trampoline_address)
-                       /*
-                        * This is the real return address. Any other
-                        * instances associated with this task are for
-                        * other calls deeper on the call stack
-                        */
-                       break;
-       }
-
-       kretprobe_hash_unlock(current, &flags);
-
-       hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
-               hlist_del(&ri->hlist);
-               kfree(ri);
-       }
-       return (void *)orig_ret_address;
-}
-
-/*
- * Called after single-stepping.  p->addr is the address of the
- * instruction whose first byte has been replaced by the "int 3"
- * instruction.  To avoid the SMP problems that can occur when we
- * temporarily put back the original opcode to single-step, we
- * single-stepped a copy of the instruction.  The address of this
- * copy is p->ainsn.insn.
- *
- * This function prepares to return from the post-single-step
- * interrupt.  We have to fix up the stack as follows:
- *
- * 0) Except in the case of absolute or indirect jump or call instructions,
- * the new ip is relative to the copied instruction.  We need to make
- * it relative to the original instruction.
- *
- * 1) If the single-stepped instruction was pushfl, then the TF and IF
- * flags are set in the just-pushed flags, and may need to be cleared.
- *
- * 2) If the single-stepped instruction was a call, the return address
- * that is atop the stack is the address following the copied instruction.
- * We need to make it the address following the original instruction.
- *
- * If this is the first time we've single-stepped the instruction at
- * this probepoint, and the instruction is boostable, boost it: add a
- * jump instruction after the copied instruction, that jumps to the next
- * instruction after the probepoint.
- */
-static void __kprobes
-resume_execution(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
-{
-       unsigned long *tos = stack_addr(regs);
-       unsigned long copy_ip = (unsigned long)p->ainsn.insn;
-       unsigned long orig_ip = (unsigned long)p->addr;
-       kprobe_opcode_t *insn = p->ainsn.insn;
-
-       /* Skip prefixes */
-       insn = skip_prefixes(insn);
-
-       regs->flags &= ~X86_EFLAGS_TF;
-       switch (*insn) {
-       case 0x9c:      /* pushfl */
-               *tos &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF);
-               *tos |= kcb->kprobe_old_flags;
-               break;
-       case 0xc2:      /* iret/ret/lret */
-       case 0xc3:
-       case 0xca:
-       case 0xcb:
-       case 0xcf:
-       case 0xea:      /* jmp absolute -- ip is correct */
-               /* ip is already adjusted, no more changes required */
-               p->ainsn.boostable = 1;
-               goto no_change;
-       case 0xe8:      /* call relative - Fix return addr */
-               *tos = orig_ip + (*tos - copy_ip);
-               break;
-#ifdef CONFIG_X86_32
-       case 0x9a:      /* call absolute -- same as call absolute, indirect */
-               *tos = orig_ip + (*tos - copy_ip);
-               goto no_change;
-#endif
-       case 0xff:
-               if ((insn[1] & 0x30) == 0x10) {
-                       /*
-                        * call absolute, indirect
-                        * Fix return addr; ip is correct.
-                        * But this is not boostable
-                        */
-                       *tos = orig_ip + (*tos - copy_ip);
-                       goto no_change;
-               } else if (((insn[1] & 0x31) == 0x20) ||
-                          ((insn[1] & 0x31) == 0x21)) {
-                       /*
-                        * jmp near and far, absolute indirect
-                        * ip is correct. And this is boostable
-                        */
-                       p->ainsn.boostable = 1;
-                       goto no_change;
-               }
-       default:
-               break;
-       }
-
-       if (p->ainsn.boostable == 0) {
-               if ((regs->ip > copy_ip) &&
-                   (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
-                       /*
-                        * These instructions can be executed directly if it
-                        * jumps back to correct address.
-                        */
-                       synthesize_reljump((void *)regs->ip,
-                               (void *)orig_ip + (regs->ip - copy_ip));
-                       p->ainsn.boostable = 1;
-               } else {
-                       p->ainsn.boostable = -1;
-               }
-       }
-
-       regs->ip += orig_ip - copy_ip;
-
-no_change:
-       restore_btf();
-}
-
-/*
- * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled throughout this function.
- */
-static int __kprobes post_kprobe_handler(struct pt_regs *regs)
-{
-       struct kprobe *cur = kprobe_running();
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-       if (!cur)
-               return 0;
-
-       resume_execution(cur, regs, kcb);
-       regs->flags |= kcb->kprobe_saved_flags;
-
-       if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
-               kcb->kprobe_status = KPROBE_HIT_SSDONE;
-               cur->post_handler(cur, regs, 0);
-       }
-
-       /* Restore back the original saved kprobes variables and continue. */
-       if (kcb->kprobe_status == KPROBE_REENTER) {
-               restore_previous_kprobe(kcb);
-               goto out;
-       }
-       reset_current_kprobe();
-out:
-       preempt_enable_no_resched();
-
-       /*
-        * if somebody else is singlestepping across a probe point, flags
-        * will have TF set, in which case, continue the remaining processing
-        * of do_debug, as if this is not a probe hit.
-        */
-       if (regs->flags & X86_EFLAGS_TF)
-               return 0;
-
-       return 1;
-}
-
-int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
-{
-       struct kprobe *cur = kprobe_running();
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-       switch (kcb->kprobe_status) {
-       case KPROBE_HIT_SS:
-       case KPROBE_REENTER:
-               /*
-                * We are here because the instruction being single
-                * stepped caused a page fault. We reset the current
-                * kprobe and the ip points back to the probe address
-                * and allow the page fault handler to continue as a
-                * normal page fault.
-                */
-               regs->ip = (unsigned long)cur->addr;
-               regs->flags |= kcb->kprobe_old_flags;
-               if (kcb->kprobe_status == KPROBE_REENTER)
-                       restore_previous_kprobe(kcb);
-               else
-                       reset_current_kprobe();
-               preempt_enable_no_resched();
-               break;
-       case KPROBE_HIT_ACTIVE:
-       case KPROBE_HIT_SSDONE:
-               /*
-                * We increment the nmissed count for accounting,
-                * we can also use npre/npostfault count for accounting
-                * these specific fault cases.
-                */
-               kprobes_inc_nmissed_count(cur);
-
-               /*
-                * We come here because instructions in the pre/post
-                * handler caused the page_fault, this could happen
-                * if handler tries to access user space by
-                * copy_from_user(), get_user() etc. Let the
-                * user-specified handler try to fix it first.
-                */
-               if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
-                       return 1;
-
-               /*
-                * In case the user-specified fault handler returned
-                * zero, try to fix up.
-                */
-               if (fixup_exception(regs))
-                       return 1;
-
-               /*
-                * fixup routine could not handle it,
-                * Let do_page_fault() fix it.
-                */
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-/*
- * Wrapper routine for handling exceptions.
- */
-int __kprobes
-kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data)
-{
-       struct die_args *args = data;
-       int ret = NOTIFY_DONE;
-
-       if (args->regs && user_mode_vm(args->regs))
-               return ret;
-
-       switch (val) {
-       case DIE_INT3:
-               if (kprobe_handler(args->regs))
-                       ret = NOTIFY_STOP;
-               break;
-       case DIE_DEBUG:
-               if (post_kprobe_handler(args->regs)) {
-                       /*
-                        * Reset the BS bit in dr6 (pointed by args->err) to
-                        * denote completion of processing
-                        */
-                       (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
-                       ret = NOTIFY_STOP;
-               }
-               break;
-       case DIE_GPF:
-               /*
-                * To be potentially processing a kprobe fault and to
-                * trust the result from kprobe_running(), we have
-                * be non-preemptible.
-                */
-               if (!preemptible() && kprobe_running() &&
-                   kprobe_fault_handler(args->regs, args->trapnr))
-                       ret = NOTIFY_STOP;
-               break;
-       default:
-               break;
-       }
-       return ret;
-}
-
-int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
-{
-       struct jprobe *jp = container_of(p, struct jprobe, kp);
-       unsigned long addr;
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-       kcb->jprobe_saved_regs = *regs;
-       kcb->jprobe_saved_sp = stack_addr(regs);
-       addr = (unsigned long)(kcb->jprobe_saved_sp);
-
-       /*
-        * As Linus pointed out, gcc assumes that the callee
-        * owns the argument space and could overwrite it, e.g.
-        * tailcall optimization. So, to be absolutely safe
-        * we also save and restore enough stack bytes to cover
-        * the argument area.
-        */
-       memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
-              MIN_STACK_SIZE(addr));
-       regs->flags &= ~X86_EFLAGS_IF;
-       trace_hardirqs_off();
-       regs->ip = (unsigned long)(jp->entry);
-       return 1;
-}
-
-void __kprobes jprobe_return(void)
-{
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-       asm volatile (
-#ifdef CONFIG_X86_64
-                       "       xchg   %%rbx,%%rsp      \n"
-#else
-                       "       xchgl   %%ebx,%%esp     \n"
-#endif
-                       "       int3                    \n"
-                       "       .globl jprobe_return_end\n"
-                       "       jprobe_return_end:      \n"
-                       "       nop                     \n"::"b"
-                       (kcb->jprobe_saved_sp):"memory");
-}
-
-int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
-{
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-       u8 *addr = (u8 *) (regs->ip - 1);
-       struct jprobe *jp = container_of(p, struct jprobe, kp);
-
-       if ((addr > (u8 *) jprobe_return) &&
-           (addr < (u8 *) jprobe_return_end)) {
-               if (stack_addr(regs) != kcb->jprobe_saved_sp) {
-                       struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
-                       printk(KERN_ERR
-                              "current sp %p does not match saved sp %p\n",
-                              stack_addr(regs), kcb->jprobe_saved_sp);
-                       printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
-                       show_regs(saved_regs);
-                       printk(KERN_ERR "Current registers\n");
-                       show_regs(regs);
-                       BUG();
-               }
-               *regs = kcb->jprobe_saved_regs;
-               memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
-                      kcb->jprobes_stack,
-                      MIN_STACK_SIZE(kcb->jprobe_saved_sp));
-               preempt_enable_no_resched();
-               return 1;
-       }
-       return 0;
-}
-
-#ifdef KPROBES_CAN_USE_FTRACE
-/* Ftrace callback handler for kprobes */
-void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
-                                    struct ftrace_ops *ops, struct pt_regs *regs)
-{
-       struct kprobe *p;
-       struct kprobe_ctlblk *kcb;
-       unsigned long flags;
-
-       /* Disable irq for emulating a breakpoint and avoiding preempt */
-       local_irq_save(flags);
-
-       p = get_kprobe((kprobe_opcode_t *)ip);
-       if (unlikely(!p) || kprobe_disabled(p))
-               goto end;
-
-       kcb = get_kprobe_ctlblk();
-       if (kprobe_running()) {
-               kprobes_inc_nmissed_count(p);
-       } else {
-               /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
-               regs->ip = ip + sizeof(kprobe_opcode_t);
-
-               __this_cpu_write(current_kprobe, p);
-               kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-               if (!p->pre_handler || !p->pre_handler(p, regs))
-                       skip_singlestep(p, regs, kcb);
-               /*
-                * If pre_handler returns !0, it sets regs->ip and
-                * resets current kprobe.
-                */
-       }
-end:
-       local_irq_restore(flags);
-}
-
-int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p)
-{
-       p->ainsn.insn = NULL;
-       p->ainsn.boostable = -1;
-       return 0;
-}
-#endif
-
-int __init arch_init_kprobes(void)
-{
-       return arch_init_optprobes();
-}
-
-int __kprobes arch_trampoline_kprobe(struct kprobe *p)
-{
-       return 0;
-}
diff --git a/arch/x86/kernel/kprobes/Makefile b/arch/x86/kernel/kprobes/Makefile
new file mode 100644 (file)
index 0000000..0d33169
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for kernel probes
+#
+
+obj-$(CONFIG_KPROBES)          += core.o
+obj-$(CONFIG_OPTPROBES)                += opt.o
+obj-$(CONFIG_KPROBES_ON_FTRACE)        += ftrace.o
diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h
new file mode 100644 (file)
index 0000000..2e9d4b5
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef __X86_KERNEL_KPROBES_COMMON_H
+#define __X86_KERNEL_KPROBES_COMMON_H
+
+/* Kprobes and Optprobes common header */
+
+#ifdef CONFIG_X86_64
+#define SAVE_REGS_STRING                       \
+       /* Skip cs, ip, orig_ax. */             \
+       "       subq $24, %rsp\n"               \
+       "       pushq %rdi\n"                   \
+       "       pushq %rsi\n"                   \
+       "       pushq %rdx\n"                   \
+       "       pushq %rcx\n"                   \
+       "       pushq %rax\n"                   \
+       "       pushq %r8\n"                    \
+       "       pushq %r9\n"                    \
+       "       pushq %r10\n"                   \
+       "       pushq %r11\n"                   \
+       "       pushq %rbx\n"                   \
+       "       pushq %rbp\n"                   \
+       "       pushq %r12\n"                   \
+       "       pushq %r13\n"                   \
+       "       pushq %r14\n"                   \
+       "       pushq %r15\n"
+#define RESTORE_REGS_STRING                    \
+       "       popq %r15\n"                    \
+       "       popq %r14\n"                    \
+       "       popq %r13\n"                    \
+       "       popq %r12\n"                    \
+       "       popq %rbp\n"                    \
+       "       popq %rbx\n"                    \
+       "       popq %r11\n"                    \
+       "       popq %r10\n"                    \
+       "       popq %r9\n"                     \
+       "       popq %r8\n"                     \
+       "       popq %rax\n"                    \
+       "       popq %rcx\n"                    \
+       "       popq %rdx\n"                    \
+       "       popq %rsi\n"                    \
+       "       popq %rdi\n"                    \
+       /* Skip orig_ax, ip, cs */              \
+       "       addq $24, %rsp\n"
+#else
+#define SAVE_REGS_STRING                       \
+       /* Skip cs, ip, orig_ax and gs. */      \
+       "       subl $16, %esp\n"               \
+       "       pushl %fs\n"                    \
+       "       pushl %es\n"                    \
+       "       pushl %ds\n"                    \
+       "       pushl %eax\n"                   \
+       "       pushl %ebp\n"                   \
+       "       pushl %edi\n"                   \
+       "       pushl %esi\n"                   \
+       "       pushl %edx\n"                   \
+       "       pushl %ecx\n"                   \
+       "       pushl %ebx\n"
+#define RESTORE_REGS_STRING                    \
+       "       popl %ebx\n"                    \
+       "       popl %ecx\n"                    \
+       "       popl %edx\n"                    \
+       "       popl %esi\n"                    \
+       "       popl %edi\n"                    \
+       "       popl %ebp\n"                    \
+       "       popl %eax\n"                    \
+       /* Skip ds, es, fs, gs, orig_ax, and ip. Note: don't pop cs here*/\
+       "       addl $24, %esp\n"
+#endif
+
+/* Ensure if the instruction can be boostable */
+extern int can_boost(kprobe_opcode_t *instruction);
+/* Recover instruction if given address is probed */
+extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
+                                        unsigned long addr);
+/*
+ * Copy an instruction and adjust the displacement if the instruction
+ * uses the %rip-relative addressing mode.
+ */
+extern int __copy_instruction(u8 *dest, u8 *src);
+
+/* Generate a relative-jump/call instruction */
+extern void synthesize_reljump(void *from, void *to);
+extern void synthesize_relcall(void *from, void *to);
+
+#ifdef CONFIG_OPTPROBES
+extern int arch_init_optprobes(void);
+extern int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter);
+extern unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr);
+#else  /* !CONFIG_OPTPROBES */
+static inline int arch_init_optprobes(void)
+{
+       return 0;
+}
+static inline int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
+{
+       return 0;
+}
+static inline unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
+{
+       return addr;
+}
+#endif
+
+#ifdef CONFIG_KPROBES_ON_FTRACE
+extern int skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                          struct kprobe_ctlblk *kcb);
+#else
+static inline int skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                                 struct kprobe_ctlblk *kcb)
+{
+       return 0;
+}
+#endif
+#endif
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
new file mode 100644 (file)
index 0000000..e124554
--- /dev/null
@@ -0,0 +1,1064 @@
+/*
+ *  Kernel Probes (KProbes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *             Probes initial implementation ( includes contributions from
+ *             Rusty Russell).
+ * 2004-July   Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *             interface to access function arguments.
+ * 2004-Oct    Jim Keniston <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ *             <prasanna@in.ibm.com> adapted for x86_64 from i386.
+ * 2005-Mar    Roland McGrath <roland@redhat.com>
+ *             Fixed to handle %rip-relative addressing mode correctly.
+ * 2005-May    Hien Nguyen <hien@us.ibm.com>, Jim Keniston
+ *             <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ *             <prasanna@in.ibm.com> added function-return probes.
+ * 2005-May    Rusty Lynch <rusty.lynch@intel.com>
+ *             Added function return probes functionality
+ * 2006-Feb    Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp> added
+ *             kprobe-booster and kretprobe-booster for i386.
+ * 2007-Dec    Masami Hiramatsu <mhiramat@redhat.com> added kprobe-booster
+ *             and kretprobe-booster for x86-64
+ * 2007-Dec    Masami Hiramatsu <mhiramat@redhat.com>, Arjan van de Ven
+ *             <arjan@infradead.org> and Jim Keniston <jkenisto@us.ibm.com>
+ *             unified x86 kprobes code.
+ */
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <linux/kallsyms.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/desc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/alternative.h>
+#include <asm/insn.h>
+#include <asm/debugreg.h>
+
+#include "common.h"
+
+void jprobe_return_end(void);
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+#define stack_addr(regs) ((unsigned long *)kernel_stack_pointer(regs))
+
+#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
+       (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
+         (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
+         (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
+         (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
+        << (row % 32))
+       /*
+        * Undefined/reserved opcodes, conditional jump, Opcode Extension
+        * Groups, and some special opcodes can not boost.
+        * This is non-const and volatile to keep gcc from statically
+        * optimizing it out, as variable_test_bit makes gcc think only
+        * *(unsigned long*) is used.
+        */
+static volatile u32 twobyte_is_boostable[256 / 32] = {
+       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
+       /*      ----------------------------------------------          */
+       W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
+       W(0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 10 */
+       W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 20 */
+       W(0x30, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */
+       W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
+       W(0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 50 */
+       W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1) | /* 60 */
+       W(0x70, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */
+       W(0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 80 */
+       W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
+       W(0xa0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) | /* a0 */
+       W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1) , /* b0 */
+       W(0xc0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */
+       W(0xd0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) , /* d0 */
+       W(0xe0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1) | /* e0 */
+       W(0xf0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0)   /* f0 */
+       /*      -----------------------------------------------         */
+       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
+};
+#undef W
+
+struct kretprobe_blackpoint kretprobe_blacklist[] = {
+       {"__switch_to", }, /* This function switches only current task, but
+                             doesn't switch kernel stack.*/
+       {NULL, NULL}    /* Terminator */
+};
+
+const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
+
+static void __kprobes __synthesize_relative_insn(void *from, void *to, u8 op)
+{
+       struct __arch_relative_insn {
+               u8 op;
+               s32 raddr;
+       } __packed *insn;
+
+       insn = (struct __arch_relative_insn *)from;
+       insn->raddr = (s32)((long)(to) - ((long)(from) + 5));
+       insn->op = op;
+}
+
+/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
+void __kprobes synthesize_reljump(void *from, void *to)
+{
+       __synthesize_relative_insn(from, to, RELATIVEJUMP_OPCODE);
+}
+
+/* Insert a call instruction at address 'from', which calls address 'to'.*/
+void __kprobes synthesize_relcall(void *from, void *to)
+{
+       __synthesize_relative_insn(from, to, RELATIVECALL_OPCODE);
+}
+
+/*
+ * Skip the prefixes of the instruction.
+ */
+static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn)
+{
+       insn_attr_t attr;
+
+       attr = inat_get_opcode_attribute((insn_byte_t)*insn);
+       while (inat_is_legacy_prefix(attr)) {
+               insn++;
+               attr = inat_get_opcode_attribute((insn_byte_t)*insn);
+       }
+#ifdef CONFIG_X86_64
+       if (inat_is_rex_prefix(attr))
+               insn++;
+#endif
+       return insn;
+}
+
+/*
+ * Returns non-zero if opcode is boostable.
+ * RIP relative instructions are adjusted at copying time in 64 bits mode
+ */
+int __kprobes can_boost(kprobe_opcode_t *opcodes)
+{
+       kprobe_opcode_t opcode;
+       kprobe_opcode_t *orig_opcodes = opcodes;
+
+       if (search_exception_tables((unsigned long)opcodes))
+               return 0;       /* Page fault may occur on this address. */
+
+retry:
+       if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
+               return 0;
+       opcode = *(opcodes++);
+
+       /* 2nd-byte opcode */
+       if (opcode == 0x0f) {
+               if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
+                       return 0;
+               return test_bit(*opcodes,
+                               (unsigned long *)twobyte_is_boostable);
+       }
+
+       switch (opcode & 0xf0) {
+#ifdef CONFIG_X86_64
+       case 0x40:
+               goto retry; /* REX prefix is boostable */
+#endif
+       case 0x60:
+               if (0x63 < opcode && opcode < 0x67)
+                       goto retry; /* prefixes */
+               /* can't boost Address-size override and bound */
+               return (opcode != 0x62 && opcode != 0x67);
+       case 0x70:
+               return 0; /* can't boost conditional jump */
+       case 0xc0:
+               /* can't boost software-interruptions */
+               return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
+       case 0xd0:
+               /* can boost AA* and XLAT */
+               return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
+       case 0xe0:
+               /* can boost in/out and absolute jmps */
+               return ((opcode & 0x04) || opcode == 0xea);
+       case 0xf0:
+               if ((opcode & 0x0c) == 0 && opcode != 0xf1)
+                       goto retry; /* lock/rep(ne) prefix */
+               /* clear and set flags are boostable */
+               return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
+       default:
+               /* segment override prefixes are boostable */
+               if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
+                       goto retry; /* prefixes */
+               /* CS override prefix and call are not boostable */
+               return (opcode != 0x2e && opcode != 0x9a);
+       }
+}
+
+static unsigned long
+__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
+{
+       struct kprobe *kp;
+
+       kp = get_kprobe((void *)addr);
+       /* There is no probe, return original address */
+       if (!kp)
+               return addr;
+
+       /*
+        *  Basically, kp->ainsn.insn has an original instruction.
+        *  However, RIP-relative instruction can not do single-stepping
+        *  at different place, __copy_instruction() tweaks the displacement of
+        *  that instruction. In that case, we can't recover the instruction
+        *  from the kp->ainsn.insn.
+        *
+        *  On the other hand, kp->opcode has a copy of the first byte of
+        *  the probed instruction, which is overwritten by int3. And
+        *  the instruction at kp->addr is not modified by kprobes except
+        *  for the first byte, we can recover the original instruction
+        *  from it and kp->opcode.
+        */
+       memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       buf[0] = kp->opcode;
+       return (unsigned long)buf;
+}
+
+/*
+ * Recover the probed instruction at addr for further analysis.
+ * Caller must lock kprobes by kprobe_mutex, or disable preemption
+ * for preventing to release referencing kprobes.
+ */
+unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
+{
+       unsigned long __addr;
+
+       __addr = __recover_optprobed_insn(buf, addr);
+       if (__addr != addr)
+               return __addr;
+
+       return __recover_probed_insn(buf, addr);
+}
+
+/* Check if paddr is at an instruction boundary */
+static int __kprobes can_probe(unsigned long paddr)
+{
+       unsigned long addr, __addr, offset = 0;
+       struct insn insn;
+       kprobe_opcode_t buf[MAX_INSN_SIZE];
+
+       if (!kallsyms_lookup_size_offset(paddr, NULL, &offset))
+               return 0;
+
+       /* Decode instructions */
+       addr = paddr - offset;
+       while (addr < paddr) {
+               /*
+                * Check if the instruction has been modified by another
+                * kprobe, in which case we replace the breakpoint by the
+                * original instruction in our buffer.
+                * Also, jump optimization will change the breakpoint to
+                * relative-jump. Since the relative-jump itself is
+                * normally used, we just go through if there is no kprobe.
+                */
+               __addr = recover_probed_instruction(buf, addr);
+               kernel_insn_init(&insn, (void *)__addr);
+               insn_get_length(&insn);
+
+               /*
+                * Another debugging subsystem might insert this breakpoint.
+                * In that case, we can't recover it.
+                */
+               if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
+                       return 0;
+               addr += insn.length;
+       }
+
+       return (addr == paddr);
+}
+
+/*
+ * Returns non-zero if opcode modifies the interrupt flag.
+ */
+static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
+{
+       /* Skip prefixes */
+       insn = skip_prefixes(insn);
+
+       switch (*insn) {
+       case 0xfa:              /* cli */
+       case 0xfb:              /* sti */
+       case 0xcf:              /* iret/iretd */
+       case 0x9d:              /* popf/popfd */
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Copy an instruction and adjust the displacement if the instruction
+ * uses the %rip-relative addressing mode.
+ * If it does, Return the address of the 32-bit displacement word.
+ * If not, return null.
+ * Only applicable to 64-bit x86.
+ */
+int __kprobes __copy_instruction(u8 *dest, u8 *src)
+{
+       struct insn insn;
+       kprobe_opcode_t buf[MAX_INSN_SIZE];
+
+       kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, (unsigned long)src));
+       insn_get_length(&insn);
+       /* Another subsystem puts a breakpoint, failed to recover */
+       if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
+               return 0;
+       memcpy(dest, insn.kaddr, insn.length);
+
+#ifdef CONFIG_X86_64
+       if (insn_rip_relative(&insn)) {
+               s64 newdisp;
+               u8 *disp;
+               kernel_insn_init(&insn, dest);
+               insn_get_displacement(&insn);
+               /*
+                * The copied instruction uses the %rip-relative addressing
+                * mode.  Adjust the displacement for the difference between
+                * the original location of this instruction and the location
+                * of the copy that will actually be run.  The tricky bit here
+                * is making sure that the sign extension happens correctly in
+                * this calculation, since we need a signed 32-bit result to
+                * be sign-extended to 64 bits when it's added to the %rip
+                * value and yield the same 64-bit result that the sign-
+                * extension of the original signed 32-bit displacement would
+                * have given.
+                */
+               newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest;
+               BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check.  */
+               disp = (u8 *) dest + insn_offset_displacement(&insn);
+               *(s32 *) disp = (s32) newdisp;
+       }
+#endif
+       return insn.length;
+}
+
+static void __kprobes arch_copy_kprobe(struct kprobe *p)
+{
+       /* Copy an instruction with recovering if other optprobe modifies it.*/
+       __copy_instruction(p->ainsn.insn, p->addr);
+
+       /*
+        * __copy_instruction can modify the displacement of the instruction,
+        * but it doesn't affect boostable check.
+        */
+       if (can_boost(p->ainsn.insn))
+               p->ainsn.boostable = 0;
+       else
+               p->ainsn.boostable = -1;
+
+       /* Also, displacement change doesn't affect the first byte */
+       p->opcode = p->ainsn.insn[0];
+}
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+       if (alternatives_text_reserved(p->addr, p->addr))
+               return -EINVAL;
+
+       if (!can_probe((unsigned long)p->addr))
+               return -EILSEQ;
+       /* insn: must be on special executable page on x86. */
+       p->ainsn.insn = get_insn_slot();
+       if (!p->ainsn.insn)
+               return -ENOMEM;
+       arch_copy_kprobe(p);
+       return 0;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+       text_poke(p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION}), 1);
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+       text_poke(p->addr, &p->opcode, 1);
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
+               p->ainsn.insn = NULL;
+       }
+}
+
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+       kcb->prev_kprobe.kp = kprobe_running();
+       kcb->prev_kprobe.status = kcb->kprobe_status;
+       kcb->prev_kprobe.old_flags = kcb->kprobe_old_flags;
+       kcb->prev_kprobe.saved_flags = kcb->kprobe_saved_flags;
+}
+
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+       __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
+       kcb->kprobe_status = kcb->prev_kprobe.status;
+       kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags;
+       kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
+}
+
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+                               struct kprobe_ctlblk *kcb)
+{
+       __this_cpu_write(current_kprobe, p);
+       kcb->kprobe_saved_flags = kcb->kprobe_old_flags
+               = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF));
+       if (is_IF_modifier(p->ainsn.insn))
+               kcb->kprobe_saved_flags &= ~X86_EFLAGS_IF;
+}
+
+static void __kprobes clear_btf(void)
+{
+       if (test_thread_flag(TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+       }
+}
+
+static void __kprobes restore_btf(void)
+{
+       if (test_thread_flag(TIF_BLOCKSTEP)) {
+               unsigned long debugctl = get_debugctlmsr();
+
+               debugctl |= DEBUGCTLMSR_BTF;
+               update_debugctlmsr(debugctl);
+       }
+}
+
+void __kprobes
+arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+       unsigned long *sara = stack_addr(regs);
+
+       ri->ret_addr = (kprobe_opcode_t *) *sara;
+
+       /* Replace the return addr with trampoline addr */
+       *sara = (unsigned long) &kretprobe_trampoline;
+}
+
+static void __kprobes
+setup_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb, int reenter)
+{
+       if (setup_detour_execution(p, regs, reenter))
+               return;
+
+#if !defined(CONFIG_PREEMPT)
+       if (p->ainsn.boostable == 1 && !p->post_handler) {
+               /* Boost up -- we can execute copied instructions directly */
+               if (!reenter)
+                       reset_current_kprobe();
+               /*
+                * Reentering boosted probe doesn't reset current_kprobe,
+                * nor set current_kprobe, because it doesn't use single
+                * stepping.
+                */
+               regs->ip = (unsigned long)p->ainsn.insn;
+               preempt_enable_no_resched();
+               return;
+       }
+#endif
+       if (reenter) {
+               save_previous_kprobe(kcb);
+               set_current_kprobe(p, regs, kcb);
+               kcb->kprobe_status = KPROBE_REENTER;
+       } else
+               kcb->kprobe_status = KPROBE_HIT_SS;
+       /* Prepare real single stepping */
+       clear_btf();
+       regs->flags |= X86_EFLAGS_TF;
+       regs->flags &= ~X86_EFLAGS_IF;
+       /* single step inline if the instruction is an int3 */
+       if (p->opcode == BREAKPOINT_INSTRUCTION)
+               regs->ip = (unsigned long)p->addr;
+       else
+               regs->ip = (unsigned long)p->ainsn.insn;
+}
+
+/*
+ * We have reentered the kprobe_handler(), since another probe was hit while
+ * within the handler. We save the original kprobes variables and just single
+ * step on the instruction of the new probe without calling any user handlers.
+ */
+static int __kprobes
+reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+{
+       switch (kcb->kprobe_status) {
+       case KPROBE_HIT_SSDONE:
+       case KPROBE_HIT_ACTIVE:
+               kprobes_inc_nmissed_count(p);
+               setup_singlestep(p, regs, kcb, 1);
+               break;
+       case KPROBE_HIT_SS:
+               /* A probe has been hit in the codepath leading up to, or just
+                * after, single-stepping of a probed instruction. This entire
+                * codepath should strictly reside in .kprobes.text section.
+                * Raise a BUG or we'll continue in an endless reentering loop
+                * and eventually a stack overflow.
+                */
+               printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
+                      p->addr);
+               dump_kprobe(p);
+               BUG();
+       default:
+               /* impossible cases */
+               WARN_ON(1);
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Interrupts are disabled on entry as trap3 is an interrupt gate and they
+ * remain disabled throughout this function.
+ */
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+       kprobe_opcode_t *addr;
+       struct kprobe *p;
+       struct kprobe_ctlblk *kcb;
+
+       addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing. We conditionally
+        * re-enable preemption at the end of this function,
+        * and also in reenter_kprobe() and setup_singlestep().
+        */
+       preempt_disable();
+
+       kcb = get_kprobe_ctlblk();
+       p = get_kprobe(addr);
+
+       if (p) {
+               if (kprobe_running()) {
+                       if (reenter_kprobe(p, regs, kcb))
+                               return 1;
+               } else {
+                       set_current_kprobe(p, regs, kcb);
+                       kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+                       /*
+                        * If we have no pre-handler or it returned 0, we
+                        * continue with normal processing.  If we have a
+                        * pre-handler and it returned non-zero, it prepped
+                        * for calling the break_handler below on re-entry
+                        * for jprobe processing, so get out doing nothing
+                        * more here.
+                        */
+                       if (!p->pre_handler || !p->pre_handler(p, regs))
+                               setup_singlestep(p, regs, kcb, 0);
+                       return 1;
+               }
+       } else if (*addr != BREAKPOINT_INSTRUCTION) {
+               /*
+                * The breakpoint instruction was removed right
+                * after we hit it.  Another cpu has removed
+                * either a probepoint or a debugger breakpoint
+                * at this address.  In either case, no further
+                * handling of this interrupt is appropriate.
+                * Back up over the (now missing) int3 and run
+                * the original instruction.
+                */
+               regs->ip = (unsigned long)addr;
+               preempt_enable_no_resched();
+               return 1;
+       } else if (kprobe_running()) {
+               p = __this_cpu_read(current_kprobe);
+               if (p->break_handler && p->break_handler(p, regs)) {
+                       if (!skip_singlestep(p, regs, kcb))
+                               setup_singlestep(p, regs, kcb, 0);
+                       return 1;
+               }
+       } /* else: not a kprobe fault; let the kernel handle it */
+
+       preempt_enable_no_resched();
+       return 0;
+}
+
+/*
+ * When a retprobed function returns, this code saves registers and
+ * calls trampoline_handler() runs, which calls the kretprobe's handler.
+ */
+static void __used __kprobes kretprobe_trampoline_holder(void)
+{
+       asm volatile (
+                       ".global kretprobe_trampoline\n"
+                       "kretprobe_trampoline: \n"
+#ifdef CONFIG_X86_64
+                       /* We don't bother saving the ss register */
+                       "       pushq %rsp\n"
+                       "       pushfq\n"
+                       SAVE_REGS_STRING
+                       "       movq %rsp, %rdi\n"
+                       "       call trampoline_handler\n"
+                       /* Replace saved sp with true return address. */
+                       "       movq %rax, 152(%rsp)\n"
+                       RESTORE_REGS_STRING
+                       "       popfq\n"
+#else
+                       "       pushf\n"
+                       SAVE_REGS_STRING
+                       "       movl %esp, %eax\n"
+                       "       call trampoline_handler\n"
+                       /* Move flags to cs */
+                       "       movl 56(%esp), %edx\n"
+                       "       movl %edx, 52(%esp)\n"
+                       /* Replace saved flags with true return address. */
+                       "       movl %eax, 56(%esp)\n"
+                       RESTORE_REGS_STRING
+                       "       popf\n"
+#endif
+                       "       ret\n");
+}
+
+/*
+ * Called from kretprobe_trampoline
+ */
+static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
+{
+       struct kretprobe_instance *ri = NULL;
+       struct hlist_head *head, empty_rp;
+       struct hlist_node *node, *tmp;
+       unsigned long flags, orig_ret_address = 0;
+       unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
+       kprobe_opcode_t *correct_ret_addr = NULL;
+
+       INIT_HLIST_HEAD(&empty_rp);
+       kretprobe_hash_lock(current, &head, &flags);
+       /* fixup registers */
+#ifdef CONFIG_X86_64
+       regs->cs = __KERNEL_CS;
+#else
+       regs->cs = __KERNEL_CS | get_kernel_rpl();
+       regs->gs = 0;
+#endif
+       regs->ip = trampoline_address;
+       regs->orig_ax = ~0UL;
+
+       /*
+        * It is possible to have multiple instances associated with a given
+        * task either because multiple functions in the call path have
+        * return probes installed on them, and/or more than one
+        * return probe was registered for a target function.
+        *
+        * We can handle this because:
+        *     - instances are always pushed into the head of the list
+        *     - when multiple return probes are registered for the same
+        *       function, the (chronologically) first instance's ret_addr
+        *       will be the real return address, and all the rest will
+        *       point to kretprobe_trampoline.
+        */
+       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task != current)
+                       /* another task is sharing our hash bucket */
+                       continue;
+
+               orig_ret_address = (unsigned long)ri->ret_addr;
+
+               if (orig_ret_address != trampoline_address)
+                       /*
+                        * This is the real return address. Any other
+                        * instances associated with this task are for
+                        * other calls deeper on the call stack
+                        */
+                       break;
+       }
+
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
+
+       correct_ret_addr = ri->ret_addr;
+       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task != current)
+                       /* another task is sharing our hash bucket */
+                       continue;
+
+               orig_ret_address = (unsigned long)ri->ret_addr;
+               if (ri->rp && ri->rp->handler) {
+                       __this_cpu_write(current_kprobe, &ri->rp->kp);
+                       get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
+                       ri->ret_addr = correct_ret_addr;
+                       ri->rp->handler(ri, regs);
+                       __this_cpu_write(current_kprobe, NULL);
+               }
+
+               recycle_rp_inst(ri, &empty_rp);
+
+               if (orig_ret_address != trampoline_address)
+                       /*
+                        * This is the real return address. Any other
+                        * instances associated with this task are for
+                        * other calls deeper on the call stack
+                        */
+                       break;
+       }
+
+       kretprobe_hash_unlock(current, &flags);
+
+       hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+               hlist_del(&ri->hlist);
+               kfree(ri);
+       }
+       return (void *)orig_ret_address;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "int 3"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->ainsn.insn.
+ *
+ * This function prepares to return from the post-single-step
+ * interrupt.  We have to fix up the stack as follows:
+ *
+ * 0) Except in the case of absolute or indirect jump or call instructions,
+ * the new ip is relative to the copied instruction.  We need to make
+ * it relative to the original instruction.
+ *
+ * 1) If the single-stepped instruction was pushfl, then the TF and IF
+ * flags are set in the just-pushed flags, and may need to be cleared.
+ *
+ * 2) If the single-stepped instruction was a call, the return address
+ * that is atop the stack is the address following the copied instruction.
+ * We need to make it the address following the original instruction.
+ *
+ * If this is the first time we've single-stepped the instruction at
+ * this probepoint, and the instruction is boostable, boost it: add a
+ * jump instruction after the copied instruction, that jumps to the next
+ * instruction after the probepoint.
+ */
+static void __kprobes
+resume_execution(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+{
+       unsigned long *tos = stack_addr(regs);
+       unsigned long copy_ip = (unsigned long)p->ainsn.insn;
+       unsigned long orig_ip = (unsigned long)p->addr;
+       kprobe_opcode_t *insn = p->ainsn.insn;
+
+       /* Skip prefixes */
+       insn = skip_prefixes(insn);
+
+       regs->flags &= ~X86_EFLAGS_TF;
+       switch (*insn) {
+       case 0x9c:      /* pushfl */
+               *tos &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF);
+               *tos |= kcb->kprobe_old_flags;
+               break;
+       case 0xc2:      /* iret/ret/lret */
+       case 0xc3:
+       case 0xca:
+       case 0xcb:
+       case 0xcf:
+       case 0xea:      /* jmp absolute -- ip is correct */
+               /* ip is already adjusted, no more changes required */
+               p->ainsn.boostable = 1;
+               goto no_change;
+       case 0xe8:      /* call relative - Fix return addr */
+               *tos = orig_ip + (*tos - copy_ip);
+               break;
+#ifdef CONFIG_X86_32
+       case 0x9a:      /* call absolute -- same as call absolute, indirect */
+               *tos = orig_ip + (*tos - copy_ip);
+               goto no_change;
+#endif
+       case 0xff:
+               if ((insn[1] & 0x30) == 0x10) {
+                       /*
+                        * call absolute, indirect
+                        * Fix return addr; ip is correct.
+                        * But this is not boostable
+                        */
+                       *tos = orig_ip + (*tos - copy_ip);
+                       goto no_change;
+               } else if (((insn[1] & 0x31) == 0x20) ||
+                          ((insn[1] & 0x31) == 0x21)) {
+                       /*
+                        * jmp near and far, absolute indirect
+                        * ip is correct. And this is boostable
+                        */
+                       p->ainsn.boostable = 1;
+                       goto no_change;
+               }
+       default:
+               break;
+       }
+
+       if (p->ainsn.boostable == 0) {
+               if ((regs->ip > copy_ip) &&
+                   (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
+                       /*
+                        * These instructions can be executed directly if it
+                        * jumps back to correct address.
+                        */
+                       synthesize_reljump((void *)regs->ip,
+                               (void *)orig_ip + (regs->ip - copy_ip));
+                       p->ainsn.boostable = 1;
+               } else {
+                       p->ainsn.boostable = -1;
+               }
+       }
+
+       regs->ip += orig_ip - copy_ip;
+
+no_change:
+       restore_btf();
+}
+
+/*
+ * Interrupts are disabled on entry as trap1 is an interrupt gate and they
+ * remain disabled throughout this function.
+ */
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+       struct kprobe *cur = kprobe_running();
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       if (!cur)
+               return 0;
+
+       resume_execution(cur, regs, kcb);
+       regs->flags |= kcb->kprobe_saved_flags;
+
+       if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+               kcb->kprobe_status = KPROBE_HIT_SSDONE;
+               cur->post_handler(cur, regs, 0);
+       }
+
+       /* Restore back the original saved kprobes variables and continue. */
+       if (kcb->kprobe_status == KPROBE_REENTER) {
+               restore_previous_kprobe(kcb);
+               goto out;
+       }
+       reset_current_kprobe();
+out:
+       preempt_enable_no_resched();
+
+       /*
+        * if somebody else is singlestepping across a probe point, flags
+        * will have TF set, in which case, continue the remaining processing
+        * of do_debug, as if this is not a probe hit.
+        */
+       if (regs->flags & X86_EFLAGS_TF)
+               return 0;
+
+       return 1;
+}
+
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       struct kprobe *cur = kprobe_running();
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       switch (kcb->kprobe_status) {
+       case KPROBE_HIT_SS:
+       case KPROBE_REENTER:
+               /*
+                * We are here because the instruction being single
+                * stepped caused a page fault. We reset the current
+                * kprobe and the ip points back to the probe address
+                * and allow the page fault handler to continue as a
+                * normal page fault.
+                */
+               regs->ip = (unsigned long)cur->addr;
+               regs->flags |= kcb->kprobe_old_flags;
+               if (kcb->kprobe_status == KPROBE_REENTER)
+                       restore_previous_kprobe(kcb);
+               else
+                       reset_current_kprobe();
+               preempt_enable_no_resched();
+               break;
+       case KPROBE_HIT_ACTIVE:
+       case KPROBE_HIT_SSDONE:
+               /*
+                * We increment the nmissed count for accounting,
+                * we can also use npre/npostfault count for accounting
+                * these specific fault cases.
+                */
+               kprobes_inc_nmissed_count(cur);
+
+               /*
+                * We come here because instructions in the pre/post
+                * handler caused the page_fault, this could happen
+                * if handler tries to access user space by
+                * copy_from_user(), get_user() etc. Let the
+                * user-specified handler try to fix it first.
+                */
+               if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+                       return 1;
+
+               /*
+                * In case the user-specified fault handler returned
+                * zero, try to fix up.
+                */
+               if (fixup_exception(regs))
+                       return 1;
+
+               /*
+                * fixup routine could not handle it,
+                * Let do_page_fault() fix it.
+                */
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
+/*
+ * Wrapper routine for handling exceptions.
+ */
+int __kprobes
+kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data)
+{
+       struct die_args *args = data;
+       int ret = NOTIFY_DONE;
+
+       if (args->regs && user_mode_vm(args->regs))
+               return ret;
+
+       switch (val) {
+       case DIE_INT3:
+               if (kprobe_handler(args->regs))
+                       ret = NOTIFY_STOP;
+               break;
+       case DIE_DEBUG:
+               if (post_kprobe_handler(args->regs)) {
+                       /*
+                        * Reset the BS bit in dr6 (pointed by args->err) to
+                        * denote completion of processing
+                        */
+                       (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
+                       ret = NOTIFY_STOP;
+               }
+               break;
+       case DIE_GPF:
+               /*
+                * To be potentially processing a kprobe fault and to
+                * trust the result from kprobe_running(), we have
+                * be non-preemptible.
+                */
+               if (!preemptible() && kprobe_running() &&
+                   kprobe_fault_handler(args->regs, args->trapnr))
+                       ret = NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+       unsigned long addr;
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       kcb->jprobe_saved_regs = *regs;
+       kcb->jprobe_saved_sp = stack_addr(regs);
+       addr = (unsigned long)(kcb->jprobe_saved_sp);
+
+       /*
+        * As Linus pointed out, gcc assumes that the callee
+        * owns the argument space and could overwrite it, e.g.
+        * tailcall optimization. So, to be absolutely safe
+        * we also save and restore enough stack bytes to cover
+        * the argument area.
+        */
+       memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
+              MIN_STACK_SIZE(addr));
+       regs->flags &= ~X86_EFLAGS_IF;
+       trace_hardirqs_off();
+       regs->ip = (unsigned long)(jp->entry);
+       return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       asm volatile (
+#ifdef CONFIG_X86_64
+                       "       xchg   %%rbx,%%rsp      \n"
+#else
+                       "       xchgl   %%ebx,%%esp     \n"
+#endif
+                       "       int3                    \n"
+                       "       .globl jprobe_return_end\n"
+                       "       jprobe_return_end:      \n"
+                       "       nop                     \n"::"b"
+                       (kcb->jprobe_saved_sp):"memory");
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       u8 *addr = (u8 *) (regs->ip - 1);
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+       if ((addr > (u8 *) jprobe_return) &&
+           (addr < (u8 *) jprobe_return_end)) {
+               if (stack_addr(regs) != kcb->jprobe_saved_sp) {
+                       struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
+                       printk(KERN_ERR
+                              "current sp %p does not match saved sp %p\n",
+                              stack_addr(regs), kcb->jprobe_saved_sp);
+                       printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
+                       show_regs(saved_regs);
+                       printk(KERN_ERR "Current registers\n");
+                       show_regs(regs);
+                       BUG();
+               }
+               *regs = kcb->jprobe_saved_regs;
+               memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
+                      kcb->jprobes_stack,
+                      MIN_STACK_SIZE(kcb->jprobe_saved_sp));
+               preempt_enable_no_resched();
+               return 1;
+       }
+       return 0;
+}
+
+int __init arch_init_kprobes(void)
+{
+       return arch_init_optprobes();
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       return 0;
+}
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
new file mode 100644 (file)
index 0000000..23ef5c5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Dynamic Ftrace based Kprobes Optimization
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Hitachi Ltd., 2012
+ */
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <linux/ftrace.h>
+
+#include "common.h"
+
+static int __skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                            struct kprobe_ctlblk *kcb)
+{
+       /*
+        * Emulate singlestep (and also recover regs->ip)
+        * as if there is a 5byte nop
+        */
+       regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
+       if (unlikely(p->post_handler)) {
+               kcb->kprobe_status = KPROBE_HIT_SSDONE;
+               p->post_handler(p, regs, 0);
+       }
+       __this_cpu_write(current_kprobe, NULL);
+       return 1;
+}
+
+int __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                             struct kprobe_ctlblk *kcb)
+{
+       if (kprobe_ftrace(p))
+               return __skip_singlestep(p, regs, kcb);
+       else
+               return 0;
+}
+
+/* Ftrace callback handler for kprobes */
+void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+                                    struct ftrace_ops *ops, struct pt_regs *regs)
+{
+       struct kprobe *p;
+       struct kprobe_ctlblk *kcb;
+       unsigned long flags;
+
+       /* Disable irq for emulating a breakpoint and avoiding preempt */
+       local_irq_save(flags);
+
+       p = get_kprobe((kprobe_opcode_t *)ip);
+       if (unlikely(!p) || kprobe_disabled(p))
+               goto end;
+
+       kcb = get_kprobe_ctlblk();
+       if (kprobe_running()) {
+               kprobes_inc_nmissed_count(p);
+       } else {
+               /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
+               regs->ip = ip + sizeof(kprobe_opcode_t);
+
+               __this_cpu_write(current_kprobe, p);
+               kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+               if (!p->pre_handler || !p->pre_handler(p, regs))
+                       __skip_singlestep(p, regs, kcb);
+               /*
+                * If pre_handler returns !0, it sets regs->ip and
+                * resets current kprobe.
+                */
+       }
+end:
+       local_irq_restore(flags);
+}
+
+int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+       p->ainsn.insn = NULL;
+       p->ainsn.boostable = -1;
+       return 0;
+}
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
new file mode 100644 (file)
index 0000000..76dc6f0
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *  Kernel Probes Jump Optimization (Optprobes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ * Copyright (C) Hitachi Ltd., 2012
+ */
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <linux/kallsyms.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/desc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/alternative.h>
+#include <asm/insn.h>
+#include <asm/debugreg.h>
+
+#include "common.h"
+
+unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
+{
+       struct optimized_kprobe *op;
+       struct kprobe *kp;
+       long offs;
+       int i;
+
+       for (i = 0; i < RELATIVEJUMP_SIZE; i++) {
+               kp = get_kprobe((void *)addr - i);
+               /* This function only handles jump-optimized kprobe */
+               if (kp && kprobe_optimized(kp)) {
+                       op = container_of(kp, struct optimized_kprobe, kp);
+                       /* If op->list is not empty, op is under optimizing */
+                       if (list_empty(&op->list))
+                               goto found;
+               }
+       }
+
+       return addr;
+found:
+       /*
+        * If the kprobe can be optimized, original bytes which can be
+        * overwritten by jump destination address. In this case, original
+        * bytes must be recovered from op->optinsn.copied_insn buffer.
+        */
+       memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       if (addr == (unsigned long)kp->addr) {
+               buf[0] = kp->opcode;
+               memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
+       } else {
+               offs = addr - (unsigned long)kp->addr - 1;
+               memcpy(buf, op->optinsn.copied_insn + offs, RELATIVE_ADDR_SIZE - offs);
+       }
+
+       return (unsigned long)buf;
+}
+
+/* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
+static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
+{
+#ifdef CONFIG_X86_64
+       *addr++ = 0x48;
+       *addr++ = 0xbf;
+#else
+       *addr++ = 0xb8;
+#endif
+       *(unsigned long *)addr = val;
+}
+
+static void __used __kprobes kprobes_optinsn_template_holder(void)
+{
+       asm volatile (
+                       ".global optprobe_template_entry\n"
+                       "optprobe_template_entry:\n"
+#ifdef CONFIG_X86_64
+                       /* We don't bother saving the ss register */
+                       "       pushq %rsp\n"
+                       "       pushfq\n"
+                       SAVE_REGS_STRING
+                       "       movq %rsp, %rsi\n"
+                       ".global optprobe_template_val\n"
+                       "optprobe_template_val:\n"
+                       ASM_NOP5
+                       ASM_NOP5
+                       ".global optprobe_template_call\n"
+                       "optprobe_template_call:\n"
+                       ASM_NOP5
+                       /* Move flags to rsp */
+                       "       movq 144(%rsp), %rdx\n"
+                       "       movq %rdx, 152(%rsp)\n"
+                       RESTORE_REGS_STRING
+                       /* Skip flags entry */
+                       "       addq $8, %rsp\n"
+                       "       popfq\n"
+#else /* CONFIG_X86_32 */
+                       "       pushf\n"
+                       SAVE_REGS_STRING
+                       "       movl %esp, %edx\n"
+                       ".global optprobe_template_val\n"
+                       "optprobe_template_val:\n"
+                       ASM_NOP5
+                       ".global optprobe_template_call\n"
+                       "optprobe_template_call:\n"
+                       ASM_NOP5
+                       RESTORE_REGS_STRING
+                       "       addl $4, %esp\n"        /* skip cs */
+                       "       popf\n"
+#endif
+                       ".global optprobe_template_end\n"
+                       "optprobe_template_end:\n");
+}
+
+#define TMPL_MOVE_IDX \
+       ((long)&optprobe_template_val - (long)&optprobe_template_entry)
+#define TMPL_CALL_IDX \
+       ((long)&optprobe_template_call - (long)&optprobe_template_entry)
+#define TMPL_END_IDX \
+       ((long)&optprobe_template_end - (long)&optprobe_template_entry)
+
+#define INT3_SIZE sizeof(kprobe_opcode_t)
+
+/* Optimized kprobe call back function: called from optinsn */
+static void __kprobes optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
+{
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       unsigned long flags;
+
+       /* This is possible if op is under delayed unoptimizing */
+       if (kprobe_disabled(&op->kp))
+               return;
+
+       local_irq_save(flags);
+       if (kprobe_running()) {
+               kprobes_inc_nmissed_count(&op->kp);
+       } else {
+               /* Save skipped registers */
+#ifdef CONFIG_X86_64
+               regs->cs = __KERNEL_CS;
+#else
+               regs->cs = __KERNEL_CS | get_kernel_rpl();
+               regs->gs = 0;
+#endif
+               regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
+               regs->orig_ax = ~0UL;
+
+               __this_cpu_write(current_kprobe, &op->kp);
+               kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+               opt_pre_handler(&op->kp, regs);
+               __this_cpu_write(current_kprobe, NULL);
+       }
+       local_irq_restore(flags);
+}
+
+static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
+{
+       int len = 0, ret;
+
+       while (len < RELATIVEJUMP_SIZE) {
+               ret = __copy_instruction(dest + len, src + len);
+               if (!ret || !can_boost(dest + len))
+                       return -EINVAL;
+               len += ret;
+       }
+       /* Check whether the address range is reserved */
+       if (ftrace_text_reserved(src, src + len - 1) ||
+           alternatives_text_reserved(src, src + len - 1) ||
+           jump_label_text_reserved(src, src + len - 1))
+               return -EBUSY;
+
+       return len;
+}
+
+/* Check whether insn is indirect jump */
+static int __kprobes insn_is_indirect_jump(struct insn *insn)
+{
+       return ((insn->opcode.bytes[0] == 0xff &&
+               (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
+               insn->opcode.bytes[0] == 0xea); /* Segment based jump */
+}
+
+/* Check whether insn jumps into specified address range */
+static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
+{
+       unsigned long target = 0;
+
+       switch (insn->opcode.bytes[0]) {
+       case 0xe0:      /* loopne */
+       case 0xe1:      /* loope */
+       case 0xe2:      /* loop */
+       case 0xe3:      /* jcxz */
+       case 0xe9:      /* near relative jump */
+       case 0xeb:      /* short relative jump */
+               break;
+       case 0x0f:
+               if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
+                       break;
+               return 0;
+       default:
+               if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
+                       break;
+               return 0;
+       }
+       target = (unsigned long)insn->next_byte + insn->immediate.value;
+
+       return (start <= target && target <= start + len);
+}
+
+/* Decode whole function to ensure any instructions don't jump into target */
+static int __kprobes can_optimize(unsigned long paddr)
+{
+       unsigned long addr, size = 0, offset = 0;
+       struct insn insn;
+       kprobe_opcode_t buf[MAX_INSN_SIZE];
+
+       /* Lookup symbol including addr */
+       if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
+               return 0;
+
+       /*
+        * Do not optimize in the entry code due to the unstable
+        * stack handling.
+        */
+       if ((paddr >= (unsigned long)__entry_text_start) &&
+           (paddr <  (unsigned long)__entry_text_end))
+               return 0;
+
+       /* Check there is enough space for a relative jump. */
+       if (size - offset < RELATIVEJUMP_SIZE)
+               return 0;
+
+       /* Decode instructions */
+       addr = paddr - offset;
+       while (addr < paddr - offset + size) { /* Decode until function end */
+               if (search_exception_tables(addr))
+                       /*
+                        * Since some fixup code will jumps into this function,
+                        * we can't optimize kprobe in this function.
+                        */
+                       return 0;
+               kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, addr));
+               insn_get_length(&insn);
+               /* Another subsystem puts a breakpoint */
+               if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
+                       return 0;
+               /* Recover address */
+               insn.kaddr = (void *)addr;
+               insn.next_byte = (void *)(addr + insn.length);
+               /* Check any instructions don't jump into target */
+               if (insn_is_indirect_jump(&insn) ||
+                   insn_jump_into_range(&insn, paddr + INT3_SIZE,
+                                        RELATIVE_ADDR_SIZE))
+                       return 0;
+               addr += insn.length;
+       }
+
+       return 1;
+}
+
+/* Check optimized_kprobe can actually be optimized. */
+int __kprobes arch_check_optimized_kprobe(struct optimized_kprobe *op)
+{
+       int i;
+       struct kprobe *p;
+
+       for (i = 1; i < op->optinsn.size; i++) {
+               p = get_kprobe(op->kp.addr + i);
+               if (p && !kprobe_disabled(p))
+                       return -EEXIST;
+       }
+
+       return 0;
+}
+
+/* Check the addr is within the optimized instructions. */
+int __kprobes
+arch_within_optimized_kprobe(struct optimized_kprobe *op, unsigned long addr)
+{
+       return ((unsigned long)op->kp.addr <= addr &&
+               (unsigned long)op->kp.addr + op->optinsn.size > addr);
+}
+
+/* Free optimized instruction slot */
+static __kprobes
+void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
+{
+       if (op->optinsn.insn) {
+               free_optinsn_slot(op->optinsn.insn, dirty);
+               op->optinsn.insn = NULL;
+               op->optinsn.size = 0;
+       }
+}
+
+void __kprobes arch_remove_optimized_kprobe(struct optimized_kprobe *op)
+{
+       __arch_remove_optimized_kprobe(op, 1);
+}
+
+/*
+ * Copy replacing target instructions
+ * Target instructions MUST be relocatable (checked inside)
+ * This is called when new aggr(opt)probe is allocated or reused.
+ */
+int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op)
+{
+       u8 *buf;
+       int ret;
+       long rel;
+
+       if (!can_optimize((unsigned long)op->kp.addr))
+               return -EILSEQ;
+
+       op->optinsn.insn = get_optinsn_slot();
+       if (!op->optinsn.insn)
+               return -ENOMEM;
+
+       /*
+        * Verify if the address gap is in 2GB range, because this uses
+        * a relative jump.
+        */
+       rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
+       if (abs(rel) > 0x7fffffff)
+               return -ERANGE;
+
+       buf = (u8 *)op->optinsn.insn;
+
+       /* Copy instructions into the out-of-line buffer */
+       ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
+       if (ret < 0) {
+               __arch_remove_optimized_kprobe(op, 0);
+               return ret;
+       }
+       op->optinsn.size = ret;
+
+       /* Copy arch-dep-instance from template */
+       memcpy(buf, &optprobe_template_entry, TMPL_END_IDX);
+
+       /* Set probe information */
+       synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
+
+       /* Set probe function call */
+       synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback);
+
+       /* Set returning jmp instruction at the tail of out-of-line buffer */
+       synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
+                          (u8 *)op->kp.addr + op->optinsn.size);
+
+       flush_icache_range((unsigned long) buf,
+                          (unsigned long) buf + TMPL_END_IDX +
+                          op->optinsn.size + RELATIVEJUMP_SIZE);
+       return 0;
+}
+
+#define MAX_OPTIMIZE_PROBES 256
+static struct text_poke_param *jump_poke_params;
+static struct jump_poke_buffer {
+       u8 buf[RELATIVEJUMP_SIZE];
+} *jump_poke_bufs;
+
+static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm,
+                                           u8 *insn_buf,
+                                           struct optimized_kprobe *op)
+{
+       s32 rel = (s32)((long)op->optinsn.insn -
+                       ((long)op->kp.addr + RELATIVEJUMP_SIZE));
+
+       /* Backup instructions which will be replaced by jump address */
+       memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
+              RELATIVE_ADDR_SIZE);
+
+       insn_buf[0] = RELATIVEJUMP_OPCODE;
+       *(s32 *)(&insn_buf[1]) = rel;
+
+       tprm->addr = op->kp.addr;
+       tprm->opcode = insn_buf;
+       tprm->len = RELATIVEJUMP_SIZE;
+}
+
+/*
+ * Replace breakpoints (int3) with relative jumps.
+ * Caller must call with locking kprobe_mutex and text_mutex.
+ */
+void __kprobes arch_optimize_kprobes(struct list_head *oplist)
+{
+       struct optimized_kprobe *op, *tmp;
+       int c = 0;
+
+       list_for_each_entry_safe(op, tmp, oplist, list) {
+               WARN_ON(kprobe_disabled(&op->kp));
+               /* Setup param */
+               setup_optimize_kprobe(&jump_poke_params[c],
+                                     jump_poke_bufs[c].buf, op);
+               list_del_init(&op->list);
+               if (++c >= MAX_OPTIMIZE_PROBES)
+                       break;
+       }
+
+       /*
+        * text_poke_smp doesn't support NMI/MCE code modifying.
+        * However, since kprobes itself also doesn't support NMI/MCE
+        * code probing, it's not a problem.
+        */
+       text_poke_smp_batch(jump_poke_params, c);
+}
+
+static void __kprobes setup_unoptimize_kprobe(struct text_poke_param *tprm,
+                                             u8 *insn_buf,
+                                             struct optimized_kprobe *op)
+{
+       /* Set int3 to first byte for kprobes */
+       insn_buf[0] = BREAKPOINT_INSTRUCTION;
+       memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
+
+       tprm->addr = op->kp.addr;
+       tprm->opcode = insn_buf;
+       tprm->len = RELATIVEJUMP_SIZE;
+}
+
+/*
+ * Recover original instructions and breakpoints from relative jumps.
+ * Caller must call with locking kprobe_mutex.
+ */
+extern void arch_unoptimize_kprobes(struct list_head *oplist,
+                                   struct list_head *done_list)
+{
+       struct optimized_kprobe *op, *tmp;
+       int c = 0;
+
+       list_for_each_entry_safe(op, tmp, oplist, list) {
+               /* Setup param */
+               setup_unoptimize_kprobe(&jump_poke_params[c],
+                                       jump_poke_bufs[c].buf, op);
+               list_move(&op->list, done_list);
+               if (++c >= MAX_OPTIMIZE_PROBES)
+                       break;
+       }
+
+       /*
+        * text_poke_smp doesn't support NMI/MCE code modifying.
+        * However, since kprobes itself also doesn't support NMI/MCE
+        * code probing, it's not a problem.
+        */
+       text_poke_smp_batch(jump_poke_params, c);
+}
+
+/* Replace a relative jump with a breakpoint (int3).  */
+void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op)
+{
+       u8 buf[RELATIVEJUMP_SIZE];
+
+       /* Set int3 to first byte for kprobes */
+       buf[0] = BREAKPOINT_INSTRUCTION;
+       memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
+       text_poke_smp(op->kp.addr, buf, RELATIVEJUMP_SIZE);
+}
+
+int  __kprobes
+setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
+{
+       struct optimized_kprobe *op;
+
+       if (p->flags & KPROBE_FLAG_OPTIMIZED) {
+               /* This kprobe is really able to run optimized path. */
+               op = container_of(p, struct optimized_kprobe, kp);
+               /* Detour through copied instructions */
+               regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
+               if (!reenter)
+                       reset_current_kprobe();
+               preempt_enable_no_resched();
+               return 1;
+       }
+       return 0;
+}
+
+int __kprobes arch_init_optprobes(void)
+{
+       /* Allocate code buffer and parameter array */
+       jump_poke_bufs = kmalloc(sizeof(struct jump_poke_buffer) *
+                                MAX_OPTIMIZE_PROBES, GFP_KERNEL);
+       if (!jump_poke_bufs)
+               return -ENOMEM;
+
+       jump_poke_params = kmalloc(sizeof(struct text_poke_param) *
+                                  MAX_OPTIMIZE_PROBES, GFP_KERNEL);
+       if (!jump_poke_params) {
+               kfree(jump_poke_bufs);
+               jump_poke_bufs = NULL;
+               return -ENOMEM;
+       }
+
+       return 0;
+}
index 08b973f64032ba31f5e91a0558e2dc003904531a..2b44ea5f269dbb3b22b649b5461163195653da80 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
 #include <asm/kvm_guest.h>
+#include <asm/context_tracking.h>
 
 static int kvmapf = 1;
 
@@ -121,6 +122,8 @@ void kvm_async_pf_task_wait(u32 token)
        struct kvm_task_sleep_node n, *e;
        DEFINE_WAIT(wait);
 
+       rcu_irq_enter();
+
        spin_lock(&b->lock);
        e = _find_apf_task(b, token);
        if (e) {
@@ -128,6 +131,8 @@ void kvm_async_pf_task_wait(u32 token)
                hlist_del(&e->link);
                kfree(e);
                spin_unlock(&b->lock);
+
+               rcu_irq_exit();
                return;
        }
 
@@ -152,13 +157,16 @@ void kvm_async_pf_task_wait(u32 token)
                        /*
                         * We cannot reschedule. So halt.
                         */
+                       rcu_irq_exit();
                        native_safe_halt();
+                       rcu_irq_enter();
                        local_irq_disable();
                }
        }
        if (!n.halted)
                finish_wait(&n.wq, &wait);
 
+       rcu_irq_exit();
        return;
 }
 EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait);
@@ -252,10 +260,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();
+               exception_enter(regs);
                exit_idle();
                kvm_async_pf_task_wait((u32)read_cr2());
-               rcu_irq_exit();
+               exception_exit(regs);
                break;
        case KVM_PV_REASON_PAGE_READY:
                rcu_irq_enter();
@@ -497,6 +505,7 @@ static bool __init kvm_detect(void)
 const struct hypervisor_x86 x86_hyper_kvm __refconst = {
        .name                   = "KVM",
        .detect                 = kvm_detect,
+       .x2apic_available       = kvm_para_available,
 };
 EXPORT_SYMBOL_GPL(x86_hyper_kvm);
 
index a7c5661f84962a2f6eb80509c1791392352a6fc8..4929502c1372db979d7e1b176b22a9981e8ec96e 100644 (file)
@@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file)
        unsigned int cpu;
        struct cpuinfo_x86 *c;
 
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
        cpu = iminor(file->f_path.dentry->d_inode);
        if (cpu >= nr_cpu_ids || !cpu_online(cpu))
                return -ENXIO;  /* No such CPU */
index de2b7ad70273134e1c3882d9829b387d6aa6c299..872079a67e4d262151dfdbe74f537033be5ebcc0 100644 (file)
@@ -56,7 +56,7 @@ struct device x86_dma_fallback_dev = {
 EXPORT_SYMBOL(x86_dma_fallback_dev);
 
 /* Number of entries preallocated for DMA-API debugging */
-#define PREALLOC_DMA_DEBUG_ENTRIES       32768
+#define PREALLOC_DMA_DEBUG_ENTRIES       65536
 
 int dma_set_mask(struct device *dev, u64 mask)
 {
@@ -265,7 +265,7 @@ rootfs_initcall(pci_iommu_init);
 #ifdef CONFIG_PCI
 /* Many VIA bridges seem to corrupt data for DAC. Disable it here */
 
-static __devinit void via_no_dac(struct pci_dev *dev)
+static void via_no_dac(struct pci_dev *dev)
 {
        if (forbid_dac == 0) {
                dev_info(&dev->dev, "disabling DAC on VIA PCI bridge\n");
index 1b27de563561ae1d6d0d58d0f29f224a4c6602a3..26ee48a33dc42f65f74c13dfb7227c97877b93e5 100644 (file)
@@ -8,7 +8,7 @@
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
 
-static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+static void quirk_intel_irqbalance(struct pci_dev *dev)
 {
        u8 config;
        u16 word;
@@ -512,7 +512,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
 
 #if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
 /* Set correct numa_node information for AMD NB functions */
-static void __devinit quirk_amd_nb_node(struct pci_dev *dev)
+static void quirk_amd_nb_node(struct pci_dev *dev)
 {
        struct pci_dev *nb_ht;
        unsigned int devfn;
index 4e8ba39eaf0fd93cbca557eaecf3efcd954ee05b..76fa1e9a2b39399b1944e4a13c68a054c9a5c386 100644 (file)
@@ -584,7 +584,7 @@ static void native_machine_emergency_restart(void)
                        break;
 
                case BOOT_EFI:
-                       if (efi_enabled)
+                       if (efi_enabled(EFI_RUNTIME_SERVICES))
                                efi.reset_system(reboot_mode ?
                                                 EFI_RESET_WARM :
                                                 EFI_RESET_COLD,
index 801602b5d745adeb1eb892294588bbcb8de1a88d..2e8f3d3b56410a0eb10bbc0fe1d18877a46ff2fc 100644 (file)
@@ -149,7 +149,6 @@ unsigned long mach_get_cmos_time(void)
        if (century) {
                century = bcd2bin(century);
                year += century * 100;
-               printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
        } else
                year += CMOS_YEARS_OFFS;
 
index 23ddd558fbd52d1376576b200122448d94165708..8b24289cc10c0f2239623918e587810b81c43c9b 100644 (file)
@@ -610,6 +610,83 @@ static __init void reserve_ibft_region(void)
 
 static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
 
+static bool __init snb_gfx_workaround_needed(void)
+{
+#ifdef CONFIG_PCI
+       int i;
+       u16 vendor, devid;
+       static const __initconst u16 snb_ids[] = {
+               0x0102,
+               0x0112,
+               0x0122,
+               0x0106,
+               0x0116,
+               0x0126,
+               0x010a,
+       };
+
+       /* Assume no if something weird is going on with PCI */
+       if (!early_pci_allowed())
+               return false;
+
+       vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID);
+       if (vendor != 0x8086)
+               return false;
+
+       devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID);
+       for (i = 0; i < ARRAY_SIZE(snb_ids); i++)
+               if (devid == snb_ids[i])
+                       return true;
+#endif
+
+       return false;
+}
+
+/*
+ * Sandy Bridge graphics has trouble with certain ranges, exclude
+ * them from allocation.
+ */
+static void __init trim_snb_memory(void)
+{
+       static const __initconst unsigned long bad_pages[] = {
+               0x20050000,
+               0x20110000,
+               0x20130000,
+               0x20138000,
+               0x40004000,
+       };
+       int i;
+
+       if (!snb_gfx_workaround_needed())
+               return;
+
+       printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");
+
+       /*
+        * Reserve all memory below the 1 MB mark that has not
+        * already been reserved.
+        */
+       memblock_reserve(0, 1<<20);
+       
+       for (i = 0; i < ARRAY_SIZE(bad_pages); i++) {
+               if (memblock_reserve(bad_pages[i], PAGE_SIZE))
+                       printk(KERN_WARNING "failed to reserve 0x%08lx\n",
+                              bad_pages[i]);
+       }
+}
+
+/*
+ * Here we put platform-specific memory range workarounds, i.e.
+ * memory known to be corrupt or otherwise in need to be reserved on
+ * specific platforms.
+ *
+ * If this gets used more widely it could use a real dispatch mechanism.
+ */
+static void __init trim_platform_memory_ranges(void)
+{
+       trim_snb_memory();
+}
+
 static void __init trim_bios_range(void)
 {
        /*
@@ -630,6 +707,7 @@ static void __init trim_bios_range(void)
         * take them out.
         */
        e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
+
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
@@ -729,15 +807,15 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_EFI
        if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
                     "EL32", 4)) {
-               efi_enabled = 1;
-               efi_64bit = false;
+               set_bit(EFI_BOOT, &x86_efi_facility);
        } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
                     "EL64", 4)) {
-               efi_enabled = 1;
-               efi_64bit = true;
+               set_bit(EFI_BOOT, &x86_efi_facility);
+               set_bit(EFI_64BIT, &x86_efi_facility);
        }
-       if (efi_enabled && efi_memblock_x86_reserve_range())
-               efi_enabled = 0;
+
+       if (efi_enabled(EFI_BOOT))
+               efi_memblock_x86_reserve_range();
 #endif
 
        x86_init.oem.arch_setup();
@@ -810,7 +888,7 @@ void __init setup_arch(char **cmdline_p)
 
        finish_e820_parsing();
 
-       if (efi_enabled)
+       if (efi_enabled(EFI_BOOT))
                efi_init();
 
        dmi_scan_machine();
@@ -893,7 +971,7 @@ void __init setup_arch(char **cmdline_p)
         * The EFI specification says that boot service code won't be called
         * after ExitBootServices(). This is, in fact, a lie.
         */
-       if (efi_enabled)
+       if (efi_enabled(EFI_MEMMAP))
                efi_reserve_boot_services();
 
        /* preallocate 4k for mptable mpc */
@@ -908,6 +986,8 @@ void __init setup_arch(char **cmdline_p)
 
        setup_real_mode();
 
+       trim_platform_memory_ranges();
+
        init_gbpages();
 
        /* max_pfn_mapped is updated here */
@@ -1034,7 +1114,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-       if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+       if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
                conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
        conswitchp = &dummy_con;
@@ -1051,14 +1131,14 @@ void __init setup_arch(char **cmdline_p)
        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.
+       /* Once setup is done above, unmap the EFI memory map on
+        * mismatched firmware/kernel archtectures since there is no
+        * support for runtime services.
         */
-       if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+       if (efi_enabled(EFI_BOOT) &&
+           IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) {
                pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
                efi_unmap_memmap();
-               efi_enabled = 0;
        }
 #endif
 }
index fbbb604313a249c139298bccfcd9bfa97ea3e32b..d6bf1f34a6e90b396c11d457dec9600eb6a9af87 100644 (file)
@@ -364,10 +364,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-               put_user_ex(sas_ss_flags(regs->sp),
-                           &frame->uc.uc_stack.ss_flags);
-               put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
 
                /* Set up to return from userspace.  */
                restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
@@ -414,7 +411,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        struct rt_sigframe __user *frame;
        void __user *fp = NULL;
        int err = 0;
-       struct task_struct *me = current;
 
        frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe), &fp);
 
@@ -433,10 +429,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-               put_user_ex(sas_ss_flags(regs->sp),
-                           &frame->uc.uc_stack.ss_flags);
-               put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
 
                /* Set up to return from userspace.  If provided, use a stub
                   already in userspace.  */
@@ -503,10 +496,7 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-               put_user_ex(sas_ss_flags(regs->sp),
-                           &frame->uc.uc_stack.ss_flags);
-               put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
                put_user_ex(0, &frame->uc.uc__pad0);
 
                if (ka->sa.sa_flags & SA_RESTORER) {
@@ -603,13 +593,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 }
 #endif /* CONFIG_X86_32 */
 
-long
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
-               struct pt_regs *regs)
-{
-       return do_sigaltstack(uss, uoss, regs->sp);
-}
-
 /*
  * Do a signal return; undo the signal stack.
  */
@@ -659,7 +642,7 @@ long sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+       if (restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
        return ax;
@@ -865,7 +848,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe_x32 __user *frame;
        sigset_t set;
        unsigned long ax;
-       struct pt_regs tregs;
 
        frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
 
@@ -879,8 +861,7 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-       tregs = *regs;
-       if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
+       if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
        return ax;
index cd3b2438a9800b8568b0d79788ef3fdb438aa1ca..9b4d51d0c0d013274f7ba46c2e58319f0d1d9145 100644 (file)
@@ -165,10 +165,11 @@ void set_task_blockstep(struct task_struct *task, bool on)
         * Ensure irq/preemption can't change debugctl in between.
         * Note also that both TIF_BLOCKSTEP and debugctl should
         * be changed atomically wrt preemption.
-        * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
-        * wrong if task != current, SIGKILL can wakeup the stopped
-        * tracee and set/clear can play with the running task, this
-        * can confuse the next __switch_to_xtra().
+        *
+        * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if
+        * task is current or it can't be running, otherwise we can race
+        * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but
+        * PTRACE_KILL is not safe.
         */
        local_irq_disable();
        debugctl = get_debugctlmsr();
index 97ef74b88e0f8f6213308c6168303779302adec0..dbded5aedb818d511a46967ccb1d26d77233110f 100644 (file)
@@ -157,7 +157,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        if (flags & MAP_FIXED)
                return addr;
 
-       /* for MAP_32BIT mappings we force the legact mmap base */
+       /* for MAP_32BIT mappings we force the legacy mmap base */
        if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT))
                goto bottomup;
 
index 06ccb5073a3f7280f1f71b20cbf7edc68d7d278c..4b9ea101fe3b2923744b5b0b5b61c15ff1c3f296 100644 (file)
@@ -623,7 +623,8 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
        ns_now = __cycles_2_ns(tsc_now);
 
        if (cpu_khz) {
-               *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+               *scale = ((NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR) +
+                               cpu_khz / 2) / cpu_khz;
                *offset = ns_now - mult_frac(tsc_now, *scale,
                                             (1UL << CYC2NS_SCALE_FACTOR));
        }
index c71025b674623133219377a70b1e27f380a95ffa..0ba4cfb4f412dcc960e26107083535bf1ba10181 100644 (file)
@@ -680,8 +680,10 @@ static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
                if (auprobe->insn[i] == 0x66)
                        continue;
 
-               if (auprobe->insn[i] == 0x90)
+               if (auprobe->insn[i] == 0x90) {
+                       regs->ip += i + 1;
                        return true;
+               }
 
                break;
        }
index 7a3d075a814a9c83a603df93b5961f247049e624..d065d67c267230fcb386250fd1261e95c521cae8 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/io_apic.h>
+#include <asm/hpet.h>
 #include <asm/pat.h>
 #include <asm/tsc.h>
 #include <asm/iommu.h>
@@ -111,15 +112,22 @@ struct x86_platform_ops x86_platform = {
 
 EXPORT_SYMBOL_GPL(x86_platform);
 struct x86_msi_ops x86_msi = {
-       .setup_msi_irqs = native_setup_msi_irqs,
-       .teardown_msi_irq = native_teardown_msi_irq,
-       .teardown_msi_irqs = default_teardown_msi_irqs,
-       .restore_msi_irqs = default_restore_msi_irqs,
+       .setup_msi_irqs         = native_setup_msi_irqs,
+       .compose_msi_msg        = native_compose_msi_msg,
+       .teardown_msi_irq       = native_teardown_msi_irq,
+       .teardown_msi_irqs      = default_teardown_msi_irqs,
+       .restore_msi_irqs       = default_restore_msi_irqs,
+       .setup_hpet_msi         = default_setup_hpet_msi,
 };
 
 struct x86_io_apic_ops x86_io_apic_ops = {
-       .init   = native_io_apic_init_mappings,
-       .read   = native_io_apic_read,
-       .write  = native_io_apic_write,
-       .modify = native_io_apic_modify,
+       .init                   = native_io_apic_init_mappings,
+       .read                   = native_io_apic_read,
+       .write                  = native_io_apic_write,
+       .modify                 = native_io_apic_modify,
+       .disable                = native_disable_io_apic,
+       .print_entries          = native_io_apic_print_entries,
+       .set_affinity           = native_ioapic_set_affinity,
+       .setup_entry            = native_setup_ioapic_entry,
+       .eoi_ioapic_pin         = native_eoi_ioapic_pin,
 };
index 76f54461f7cb83a13a0ec8e76add8968532a1eae..c243b81e3c74b56bb69d7d26e692ac4181d73320 100644 (file)
@@ -120,7 +120,7 @@ struct kvm_shared_msrs {
 };
 
 static struct kvm_shared_msrs_global __read_mostly shared_msrs_global;
-static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs);
+static struct kvm_shared_msrs __percpu *shared_msrs;
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "pf_fixed", VCPU_STAT(pf_fixed) },
@@ -191,10 +191,10 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
 
 static void shared_msr_update(unsigned slot, u32 msr)
 {
-       struct kvm_shared_msrs *smsr;
        u64 value;
+       unsigned int cpu = smp_processor_id();
+       struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
-       smsr = &__get_cpu_var(shared_msrs);
        /* only read, and nobody should modify it at this time,
         * so don't need lock */
        if (slot >= shared_msrs_global.nr) {
@@ -226,7 +226,8 @@ static void kvm_shared_msr_cpu_online(void)
 
 void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
 {
-       struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
+       unsigned int cpu = smp_processor_id();
+       struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
        if (((value ^ smsr->values[slot].curr) & mask) == 0)
                return;
@@ -242,7 +243,8 @@ EXPORT_SYMBOL_GPL(kvm_set_shared_msr);
 
 static void drop_user_return_notifiers(void *ignore)
 {
-       struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
+       unsigned int cpu = smp_processor_id();
+       struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
        if (smsr->registered)
                kvm_on_user_return(&smsr->urn);
@@ -5233,9 +5235,16 @@ int kvm_arch_init(void *opaque)
                goto out;
        }
 
+       r = -ENOMEM;
+       shared_msrs = alloc_percpu(struct kvm_shared_msrs);
+       if (!shared_msrs) {
+               printk(KERN_ERR "kvm: failed to allocate percpu kvm_shared_msrs\n");
+               goto out;
+       }
+
        r = kvm_mmu_module_init();
        if (r)
-               goto out;
+               goto out_free_percpu;
 
        kvm_set_mmio_spte_mask();
        kvm_init_msr_list();
@@ -5258,6 +5267,8 @@ int kvm_arch_init(void *opaque)
 
        return 0;
 
+out_free_percpu:
+       free_percpu(shared_msrs);
 out:
        return r;
 }
@@ -5275,6 +5286,7 @@ void kvm_arch_exit(void)
 #endif
        kvm_x86_ops = NULL;
        kvm_mmu_module_exit();
+       free_percpu(shared_msrs);
 }
 
 int kvm_emulate_halt(struct kvm_vcpu *vcpu)
index e395693abdb16068cd2b268f258d9c79d3d0f3f3..7c3bee636e2fc31bd4021d308da7e5af2bc65519 100644 (file)
@@ -98,7 +98,7 @@ void use_tsc_delay(void)
        delay_fn = delay_tsc;
 }
 
-int __devinit read_current_timer(unsigned long *timer_val)
+int read_current_timer(unsigned long *timer_val)
 {
        if (delay_fn == delay_tsc) {
                rdtscll(*timer_val);
index 027088f2f7dd9b6b836abfe410088579106a7324..fb674fd3fc2258f75400564acea0a835430f5988 100644 (file)
@@ -748,13 +748,15 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                                return;
                }
 #endif
+               /* Kernel addresses are always protection faults: */
+               if (address >= TASK_SIZE)
+                       error_code |= PF_PROT;
 
-               if (unlikely(show_unhandled_signals))
+               if (likely(show_unhandled_signals))
                        show_signal_msg(regs, error_code, address, tsk);
 
-               /* Kernel addresses are always protection faults: */
                tsk->thread.cr2         = address;
-               tsk->thread.error_code  = error_code | (address >= TASK_SIZE);
+               tsk->thread.error_code  = error_code;
                tsk->thread.trap_nr     = X86_TRAP_PF;
 
                force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0);
index 2ead3c8a4c8419da92a61fbba35eb695e5205dde..d6eeead437584c0afcdcf1e8e3c8963b20a77192 100644 (file)
@@ -605,7 +605,7 @@ kernel_physical_mapping_init(unsigned long start,
        }
 
        if (pgd_changed)
-               sync_global_pgds(addr, end);
+               sync_global_pgds(addr, end - 1);
 
        __flush_tlb_all();
 
@@ -831,6 +831,9 @@ int kern_addr_valid(unsigned long addr)
        if (pud_none(*pud))
                return 0;
 
+       if (pud_large(*pud))
+               return pfn_valid(pud_pfn(*pud));
+
        pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd))
                return 0;
@@ -981,7 +984,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
                }
 
        }
-       sync_global_pgds((unsigned long)start_page, end);
+       sync_global_pgds((unsigned long)start_page, end - 1);
        return 0;
 }
 
index 0c01261fe5a846bc2500fc24c1ff56c2b432e86f..53ea60458e01c941a4a9c7113fbb9eebae24efa2 100644 (file)
@@ -145,7 +145,7 @@ void __init pci_acpi_crs_quirks(void)
 }
 
 #ifdef CONFIG_PCI_MMCONFIG
-static int __devinit check_segment(u16 seg, struct device *dev, char *estr)
+static int check_segment(u16 seg, struct device *dev, char *estr)
 {
        if (seg) {
                dev_err(dev,
@@ -168,9 +168,8 @@ static int __devinit check_segment(u16 seg, struct device *dev, char *estr)
        return 0;
 }
 
-static int __devinit setup_mcfg_map(struct pci_root_info *info,
-                                   u16 seg, u8 start, u8 end,
-                                   phys_addr_t addr)
+static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
+                         u8 end, phys_addr_t addr)
 {
        int result;
        struct device *dev = &info->bridge->dev;
@@ -208,7 +207,7 @@ static void teardown_mcfg_map(struct pci_root_info *info)
        }
 }
 #else
-static int __devinit setup_mcfg_map(struct pci_root_info *info,
+static int setup_mcfg_map(struct pci_root_info *info,
                                    u16 seg, u8 start, u8 end,
                                    phys_addr_t addr)
 {
@@ -474,7 +473,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
                                info);
 }
 
-struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
        struct acpi_device *device = root->device;
        struct pci_root_info *info = NULL;
index d37e2fec97e58fd3b4c3d35a5903fd6cf78060d1..c2735feb2508148ec16efab887ec1aab2dcc0aec 100644 (file)
@@ -93,8 +93,8 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
        return info;
 }
 
-void __devinit update_res(struct pci_root_info *info, resource_size_t start,
-                         resource_size_t end, unsigned long flags, int merge)
+void update_res(struct pci_root_info *info, resource_size_t start,
+               resource_size_t end, unsigned long flags, int merge)
 {
        struct resource *res;
        struct pci_root_res *root_res;
index 1b1dda90a945ede1550294e83dfc51d7a2f9f663..ccd0ab3ab8996b764b0166f91e84e15f0dbe8ba7 100644 (file)
@@ -81,14 +81,14 @@ struct pci_ops pci_root_ops = {
  */
 DEFINE_RAW_SPINLOCK(pci_config_lock);
 
-static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
+static int can_skip_ioresource_align(const struct dmi_system_id *d)
 {
        pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
        printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
        return 0;
 }
 
-static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitconst = {
+static const struct dmi_system_id can_skip_pciprobe_dmi_table[] = {
 /*
  * Systems where PCI IO resource ISA alignment can be skipped
  * when the ISA enable bit in the bridge control is not set
@@ -125,7 +125,7 @@ void __init dmi_check_skip_isa_align(void)
        dmi_check_system(can_skip_pciprobe_dmi_table);
 }
 
-static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+static void pcibios_fixup_device_resources(struct pci_dev *dev)
 {
        struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
        struct resource *bar_r;
@@ -162,7 +162,7 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
  *  are examined.
  */
 
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
+void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
@@ -176,7 +176,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
  * on the kernel command line (which was parsed earlier).
  */
 
-static int __devinit set_bf_sort(const struct dmi_system_id *d)
+static int set_bf_sort(const struct dmi_system_id *d)
 {
        if (pci_bf_sort == pci_bf_sort_default) {
                pci_bf_sort = pci_dmi_bf;
@@ -185,7 +185,7 @@ static int __devinit set_bf_sort(const struct dmi_system_id *d)
        return 0;
 }
 
-static void __devinit read_dmi_type_b1(const struct dmi_header *dm,
+static void read_dmi_type_b1(const struct dmi_header *dm,
                                       void *private_data)
 {
        u8 *d = (u8 *)dm + 4;
@@ -207,7 +207,7 @@ static void __devinit read_dmi_type_b1(const struct dmi_header *dm,
        }
 }
 
-static int __devinit find_sort_method(const struct dmi_system_id *d)
+static int find_sort_method(const struct dmi_system_id *d)
 {
        dmi_walk(read_dmi_type_b1, NULL);
 
@@ -222,7 +222,7 @@ static int __devinit find_sort_method(const struct dmi_system_id *d)
  * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
  */
 #ifdef __i386__
-static int __devinit assign_all_busses(const struct dmi_system_id *d)
+static int assign_all_busses(const struct dmi_system_id *d)
 {
        pci_probe |= PCI_ASSIGN_ALL_BUSSES;
        printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
@@ -231,7 +231,7 @@ static int __devinit assign_all_busses(const struct dmi_system_id *d)
 }
 #endif
 
-static int __devinit set_scan_all(const struct dmi_system_id *d)
+static int set_scan_all(const struct dmi_system_id *d)
 {
        printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n",
               d->ident);
@@ -239,7 +239,7 @@ static int __devinit set_scan_all(const struct dmi_system_id *d)
        return 0;
 }
 
-static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
+static const struct dmi_system_id pciprobe_dmi_table[] = {
 #ifdef __i386__
 /*
  * Laptops which need pci=assign-busses to see Cardbus cards
@@ -434,7 +434,8 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
                .callback = set_scan_all,
                .ident = "Stratus/NEC ftServer",
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ftServer"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Stratus"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"),
                },
        },
        {}
@@ -445,7 +446,7 @@ void __init dmi_check_pciprobe(void)
        dmi_check_system(pciprobe_dmi_table);
 }
 
-struct pci_bus * __devinit pcibios_scan_root(int busnum)
+struct pci_bus *pcibios_scan_root(int busnum)
 {
        struct pci_bus *bus = NULL;
 
@@ -664,7 +665,7 @@ int pci_ext_cfg_avail(void)
                return 0;
 }
 
-struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
+struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
 {
        LIST_HEAD(resources);
        struct pci_bus *bus = NULL;
@@ -692,7 +693,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
        return bus;
 }
 
-struct pci_bus * __devinit pci_scan_bus_with_sysdata(int busno)
+struct pci_bus *pci_scan_bus_with_sysdata(int busno)
 {
        return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
 }
index af8a224db216adcae94b2957240ea96758bd4325..f5809fa2753e69246f8d361d844c212e03d139e9 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/vgaarb.h>
 #include <asm/pci_x86.h>
 
-static void __devinit pci_fixup_i450nx(struct pci_dev *d)
+static void pci_fixup_i450nx(struct pci_dev *d)
 {
        /*
         * i450NX -- Find and scan all secondary buses on all PXB's.
@@ -34,7 +34,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
-static void __devinit pci_fixup_i450gx(struct pci_dev *d)
+static void pci_fixup_i450gx(struct pci_dev *d)
 {
        /*
         * i450GX and i450KX -- Find and scan all secondary buses.
@@ -48,7 +48,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
 
-static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
+static void pci_fixup_umc_ide(struct pci_dev *d)
 {
        /*
         * UM8886BF IDE controller sets region type bits incorrectly,
@@ -62,7 +62,7 @@ static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
 
-static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
+static void pci_fixup_ncr53c810(struct pci_dev *d)
 {
        /*
         * NCR 53C810 returns class code 0 (at least on some systems).
@@ -75,7 +75,7 @@ static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
 
-static void __devinit  pci_fixup_latency(struct pci_dev *d)
+static void pci_fixup_latency(struct pci_dev *d)
 {
        /*
         *  SiS 5597 and 5598 chipsets require latency timer set to
@@ -87,7 +87,7 @@ static void __devinit  pci_fixup_latency(struct pci_dev *d)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
 
-static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
+static void pci_fixup_piix4_acpi(struct pci_dev *d)
 {
        /*
         * PIIX4 ACPI device: hardwired IRQ9
@@ -163,7 +163,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_
  * system to PCI bus no matter what are their window settings, so they are
  * "transparent" (or subtractive decoding) from programmers point of view.
  */
-static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
+static void pci_fixup_transparent_bridge(struct pci_dev *dev)
 {
        if ((dev->device & 0xff00) == 0x2400)
                dev->transparent = 1;
@@ -317,7 +317,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,        PCI_DEVICE_ID_INTEL_MCH_PC1,    pcie_r
  * video device at this point.
  */
 
-static void __devinit pci_fixup_video(struct pci_dev *pdev)
+static void pci_fixup_video(struct pci_dev *pdev)
 {
        struct pci_dev *bridge;
        struct pci_bus *bus;
@@ -357,7 +357,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
                                PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
 
 
-static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = {
+static const struct dmi_system_id msi_k8t_dmi_table[] = {
        {
                .ident = "MSI-K8T-Neo2Fir",
                .matches = {
@@ -378,7 +378,7 @@ static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = {
  * The soundcard is only enabled, if the mainborad is identified
  * via DMI-tables and the soundcard is detected to be off.
  */
-static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
+static void pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
 {
        unsigned char val;
        if (!dmi_check_system(msi_k8t_dmi_table))
@@ -414,7 +414,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
  */
 static u16 toshiba_line_size;
 
-static const struct dmi_system_id __devinitconst toshiba_ohci1394_dmi_table[] = {
+static const struct dmi_system_id toshiba_ohci1394_dmi_table[] = {
        {
                .ident = "Toshiba PS5 based laptop",
                .matches = {
@@ -439,7 +439,7 @@ static const struct dmi_system_id __devinitconst toshiba_ohci1394_dmi_table[] =
        { }
 };
 
-static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
+static void pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
 {
        if (!dmi_check_system(toshiba_ohci1394_dmi_table))
                return; /* only applies to certain Toshibas (so far) */
@@ -450,7 +450,7 @@ static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
                         pci_pre_fixup_toshiba_ohci1394);
 
-static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
+static void pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
 {
        if (!dmi_check_system(toshiba_ohci1394_dmi_table))
                return; /* only applies to certain Toshibas (so far) */
@@ -488,7 +488,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
  * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:
  * prevent update of the BAR0, which doesn't look like a normal BAR.
  */
-static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
+static void pci_siemens_interrupt_controller(struct pci_dev *dev)
 {
        dev->resource[0].flags |= IORESOURCE_PCI_FIXED;
 }
@@ -531,7 +531,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar);
  *
  * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor)
  */
-static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev)
+static void twinhead_reserve_killing_zone(struct pci_dev *dev)
 {
         if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) {
                 pr_info("Reserving memory on Twinhead H12Y\n");
index a1df191129d30154e3386dc46ba78e5b540bbb74..4a2ab9cb36591235541a63b7e3c07513b2be641a 100644 (file)
@@ -10,7 +10,7 @@
  * Discover remaining PCI buses in case there are peer host bridges.
  * We use the number of last PCI bus provided by the PCI BIOS.
  */
-static void __devinit pcibios_fixup_peer_bridges(void)
+static void pcibios_fixup_peer_bridges(void)
 {
        int n;
 
@@ -34,7 +34,7 @@ int __init pci_legacy_init(void)
        return 0;
 }
 
-void __devinit pcibios_scan_specific_bus(int busn)
+void pcibios_scan_specific_bus(int busn)
 {
        int devfn;
        long node;
index 704b9ec043d709d787ffd732dc21c2200653de04..fb29968a7cd54c164286a09f9f8721144180f3d0 100644 (file)
@@ -49,7 +49,7 @@ static __init void free_all_mmcfg(void)
                pci_mmconfig_remove(cfg);
 }
 
-static __devinit void list_add_sorted(struct pci_mmcfg_region *new)
+static void list_add_sorted(struct pci_mmcfg_region *new)
 {
        struct pci_mmcfg_region *cfg;
 
@@ -65,9 +65,8 @@ static __devinit void list_add_sorted(struct pci_mmcfg_region *new)
        list_add_tail_rcu(&new->list, &pci_mmcfg_list);
 }
 
-static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
-                                                            int start,
-                                                            int end, u64 addr)
+static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
+                                                  int end, u64 addr)
 {
        struct pci_mmcfg_region *new;
        struct resource *res;
@@ -371,8 +370,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
        return !list_empty(&pci_mmcfg_list);
 }
 
-static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
-                                                void *data)
+static acpi_status check_mcfg_resource(struct acpi_resource *res, void *data)
 {
        struct resource *mcfg_res = data;
        struct acpi_resource_address64 address;
@@ -408,8 +406,8 @@ static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
        return AE_OK;
 }
 
-static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
-                                                 void *context, void **rv)
+static acpi_status find_mboard_resource(acpi_handle handle, u32 lvl,
+                                       void *context, void **rv)
 {
        struct resource *mcfg_res = context;
 
@@ -422,7 +420,7 @@ static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
        return AE_OK;
 }
 
-static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used)
+static int is_acpi_reserved(u64 start, u64 end, unsigned not_used)
 {
        struct resource mcfg_res;
 
@@ -693,9 +691,8 @@ static int __init pci_mmcfg_late_insert_resources(void)
 late_initcall(pci_mmcfg_late_insert_resources);
 
 /* Add MMCFG information for host bridges */
-int __devinit pci_mmconfig_insert(struct device *dev,
-                                 u16 seg, u8 start, u8 end,
-                                 phys_addr_t addr)
+int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
+                       phys_addr_t addr)
 {
        int rc;
        struct resource *tmp = NULL;
index db63ac23e3d935d886948da8957bd372456cd19a..5c90975cdf0f8242db167fa9c471c1ea2bf3e512 100644 (file)
@@ -142,7 +142,7 @@ void __init pci_mmcfg_arch_free(void)
 {
 }
 
-int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
+int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
 {
        return 0;
 }
index d4ebd07c306dd0a9abb9bdf69da927aa69d55bca..bea52496aea682f0b2c86e152d23ca52aae31662 100644 (file)
@@ -95,7 +95,7 @@ const struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg)
+static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg)
 {
        void __iomem *addr;
        u64 start, size;
@@ -133,7 +133,7 @@ void __init pci_mmcfg_arch_free(void)
                pci_mmcfg_arch_unmap(cfg);
 }
 
-int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
+int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
 {
        cfg->virt = mcfg_ioremap(cfg);
        if (!cfg->virt) {
index e14a2ff708b5b3642ad5cde03dc27d852d297947..6eb18c42a28a3584546e87a57f9cccf5af3473e3 100644 (file)
@@ -247,7 +247,7 @@ int __init pci_mrst_init(void)
 /* Langwell devices are not true pci devices, they are not subject to 10 ms
  * d3 to d0 delay required by pci spec.
  */
-static void __devinit pci_d3delay_fixup(struct pci_dev *dev)
+static void pci_d3delay_fixup(struct pci_dev *dev)
 {
        /* PCI fixups are effectively decided compile time. If we have a dual
           SoC/non-SoC kernel we don't want to mangle d3 on non SoC devices */
@@ -262,7 +262,7 @@ static void __devinit pci_d3delay_fixup(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup);
 
-static void __devinit mrst_power_off_unused_dev(struct pci_dev *dev)
+static void mrst_power_off_unused_dev(struct pci_dev *dev)
 {
        pci_set_power_state(dev, PCI_D3hot);
 }
@@ -275,7 +275,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0815, mrst_power_off_unused_dev);
 /*
  * Langwell devices reside at fixed offsets, don't try to move them.
  */
-static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev)
+static void pci_fixed_bar_fixup(struct pci_dev *dev)
 {
        unsigned long offset;
        u32 size;
index 83e125b95ca6d6502c9b6d12babbe5ea77a464d4..b96b14c250b6d3a9129116440ea662eb19d641de 100644 (file)
@@ -116,7 +116,7 @@ static const struct pci_raw_ops pci_direct_conf1_mq = {
 };
 
 
-static void __devinit pci_fixup_i450nx(struct pci_dev *d)
+static void pci_fixup_i450nx(struct pci_dev *d)
 {
        /*
         * i450NX -- Find and scan all secondary buses on all PXB's.
index da8fe0535ff48950789ed8f1588d0ab7e650fbba..c77b24a8b2daf499e07527be6f27d5b8c2df20d0 100644 (file)
@@ -124,7 +124,7 @@ static struct {
 
 static int pci_bios_present;
 
-static int __devinit check_pcibios(void)
+static int check_pcibios(void)
 {
        u32 signature, eax, ebx, ecx;
        u8 status, major_ver, minor_ver, hw_mech;
@@ -312,7 +312,7 @@ static const struct pci_raw_ops pci_bios_access = {
  * Try to find PCI BIOS.
  */
 
-static const struct pci_raw_ops * __devinit pci_find_bios(void)
+static const struct pci_raw_ops *pci_find_bios(void)
 {
        union bios32 *check;
        unsigned char sum;
index ad4439145f858314dfe518cf7cd9336c5fe9c96d..928bf837040a273f673e6bcb9b7f017284985a7b 100644 (file)
@@ -51,9 +51,6 @@
 
 #define EFI_DEBUG      1
 
-int efi_enabled;
-EXPORT_SYMBOL(efi_enabled);
-
 struct efi __read_mostly efi = {
        .mps        = EFI_INVALID_TABLE_ADDR,
        .acpi       = EFI_INVALID_TABLE_ADDR,
@@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi);
 
 struct efi_memory_map memmap;
 
-bool efi_64bit;
-
 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;
+       return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
+}
+
+unsigned long x86_efi_facility;
+
+/*
+ * Returns 1 if 'facility' is enabled, 0 otherwise.
+ */
+int efi_enabled(int facility)
+{
+       return test_bit(facility, &x86_efi_facility) != 0;
 }
+EXPORT_SYMBOL(efi_enabled);
 
 static int __init setup_noefi(char *arg)
 {
-       efi_enabled = 0;
+       clear_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        return 0;
 }
 early_param("noefi", setup_noefi);
@@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void)
 
 void __init efi_unmap_memmap(void)
 {
+       clear_bit(EFI_MEMMAP, &x86_efi_facility);
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
                memmap.map = NULL;
@@ -460,7 +467,7 @@ void __init efi_free_boot_services(void)
 
 static int __init efi_systab_init(void *phys)
 {
-       if (efi_64bit) {
+       if (efi_enabled(EFI_64BIT)) {
                efi_system_table_64_t *systab64;
                u64 tmp = 0;
 
@@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)
        void *config_tables, *tablep;
        int i, sz;
 
-       if (efi_64bit)
+       if (efi_enabled(EFI_64BIT))
                sz = sizeof(efi_config_table_64_t);
        else
                sz = sizeof(efi_config_table_32_t);
@@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)
                efi_guid_t guid;
                unsigned long table;
 
-               if (efi_64bit) {
+               if (efi_enabled(EFI_64BIT)) {
                        u64 table64;
                        guid = ((efi_config_table_64_t *)tablep)->guid;
                        table64 = ((efi_config_table_64_t *)tablep)->table;
@@ -684,7 +691,6 @@ void __init efi_init(void)
        if (boot_params.efi_info.efi_systab_hi ||
            boot_params.efi_info.efi_memmap_hi) {
                pr_info("Table located above 4GB, disabling EFI.\n");
-               efi_enabled = 0;
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
@@ -694,10 +700,10 @@ void __init efi_init(void)
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
 #endif
 
-       if (efi_systab_init(efi_phys.systab)) {
-               efi_enabled = 0;
+       if (efi_systab_init(efi_phys.systab))
                return;
-       }
+
+       set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
 
        /*
         * Show what we know for posterity
@@ -715,10 +721,10 @@ void __init efi_init(void)
                efi.systab->hdr.revision >> 16,
                efi.systab->hdr.revision & 0xffff, vendor);
 
-       if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) {
-               efi_enabled = 0;
+       if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
                return;
-       }
+
+       set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
 
        /*
         * Note: We currently don't support runtime services on an EFI
@@ -727,15 +733,17 @@ void __init efi_init(void)
 
        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;
-               return;
+       else {
+               if (efi_runtime_init())
+                       return;
+               set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        }
 
-       if (efi_memmap_init()) {
-               efi_enabled = 0;
+       if (efi_memmap_init())
                return;
-       }
+
+       set_bit(EFI_MEMMAP, &x86_efi_facility);
+
 #ifdef CONFIG_X86_32
        if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
@@ -941,7 +949,7 @@ void __init efi_enter_virtual_mode(void)
         *
         * Call EFI services through wrapper functions.
         */
-       efi.runtime_version = efi_systab.fw_revision;
+       efi.runtime_version = efi_systab.hdr.revision;
        efi.get_time = virt_efi_get_time;
        efi.set_time = virt_efi_set_time;
        efi.get_wakeup_time = virt_efi_get_wakeup_time;
@@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr)
        efi_memory_desc_t *md;
        void *p;
 
+       if (!efi_enabled(EFI_MEMMAP))
+               return 0;
+
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
                if ((md->phys_addr <= phys_addr) &&
index 95fd505dfeb6e43dd37b0c41954f0b0db6535d1c..2b2003860615fbc5e24ef12e1c1fa3d855a1f09d 100644 (file)
@@ -38,7 +38,7 @@
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 
-static pgd_t save_pgd __initdata;
+static pgd_t *save_pgd __initdata;
 static unsigned long efi_flags __initdata;
 
 static void __init early_code_mapping_set_exec(int executable)
@@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable)
 void __init efi_call_phys_prelog(void)
 {
        unsigned long vaddress;
+       int pgd;
+       int n_pgds;
 
        early_code_mapping_set_exec(1);
        local_irq_save(efi_flags);
-       vaddress = (unsigned long)__va(0x0UL);
-       save_pgd = *pgd_offset_k(0x0UL);
-       set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress));
+
+       n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
+       save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
+
+       for (pgd = 0; pgd < n_pgds; pgd++) {
+               save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE);
+               vaddress = (unsigned long)__va(pgd * PGDIR_SIZE);
+               set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
+       }
        __flush_tlb_all();
 }
 
@@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void)
        /*
         * After the lock is released, the original page table is restored.
         */
-       set_pgd(pgd_offset_k(0x0UL), save_pgd);
+       int pgd;
+       int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+       for (pgd = 0; pgd < n_pgds; pgd++)
+               set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
+       kfree(save_pgd);
        __flush_tlb_all();
        local_irq_restore(efi_flags);
        early_code_mapping_set_exec(0);
index fd41a9262d657ee672be6700b0dcc1fb8c147127..e31bcd8f2eeef2af6d2db13b824864b74867767d 100644 (file)
@@ -782,7 +782,7 @@ BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
 EXPORT_SYMBOL_GPL(intel_scu_notifier);
 
 /* Called by IPC driver */
-void __devinit intel_scu_devices_create(void)
+void intel_scu_devices_create(void)
 {
        int i;
 
index d75582d1aa5560c657a98a419ac89c31047f0965..ff0174dda810fd026bfde830747d52f48ffbdb0d 100644 (file)
@@ -121,7 +121,7 @@ static const struct platform_suspend_ops xo1_suspend_ops = {
        .enter = xo1_power_state_enter,
 };
 
-static int __devinit xo1_pm_probe(struct platform_device *pdev)
+static int xo1_pm_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int err;
@@ -154,7 +154,7 @@ static int __devinit xo1_pm_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit xo1_pm_remove(struct platform_device *pdev)
+static int xo1_pm_remove(struct platform_device *pdev)
 {
        mfd_cell_disable(pdev);
 
@@ -173,7 +173,7 @@ static struct platform_driver cs5535_pms_driver = {
                .owner = THIS_MODULE,
        },
        .probe = xo1_pm_probe,
-       .remove = __devexit_p(xo1_pm_remove),
+       .remove = xo1_pm_remove,
 };
 
 static struct platform_driver cs5535_acpi_driver = {
@@ -182,7 +182,7 @@ static struct platform_driver cs5535_acpi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = xo1_pm_probe,
-       .remove = __devexit_p(xo1_pm_remove),
+       .remove = xo1_pm_remove,
 };
 
 static int __init xo1_pm_init(void)
index 63d4aa40956e33abe7f98f5ed3c36916a6c7b94f..74704be7b1fe85a4400cc4404a5748f070e39b0a 100644 (file)
@@ -309,7 +309,7 @@ static int xo1_sci_resume(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit setup_sci_interrupt(struct platform_device *pdev)
+static int setup_sci_interrupt(struct platform_device *pdev)
 {
        u32 lo, hi;
        u32 sts;
@@ -351,7 +351,7 @@ static int __devinit setup_sci_interrupt(struct platform_device *pdev)
        return r;
 }
 
-static int __devinit setup_ec_sci(void)
+static int setup_ec_sci(void)
 {
        int r;
 
@@ -395,7 +395,7 @@ static void free_ec_sci(void)
        gpio_free(OLPC_GPIO_ECSCI);
 }
 
-static int __devinit setup_lid_events(void)
+static int setup_lid_events(void)
 {
        int r;
 
@@ -432,7 +432,7 @@ static void free_lid_events(void)
        gpio_free(OLPC_GPIO_LID);
 }
 
-static int __devinit setup_power_button(struct platform_device *pdev)
+static int setup_power_button(struct platform_device *pdev)
 {
        int r;
 
@@ -463,7 +463,7 @@ static void free_power_button(void)
        input_free_device(power_button_idev);
 }
 
-static int __devinit setup_ebook_switch(struct platform_device *pdev)
+static int setup_ebook_switch(struct platform_device *pdev)
 {
        int r;
 
@@ -494,7 +494,7 @@ static void free_ebook_switch(void)
        input_free_device(ebook_switch_idev);
 }
 
-static int __devinit setup_lid_switch(struct platform_device *pdev)
+static int setup_lid_switch(struct platform_device *pdev)
 {
        int r;
 
@@ -538,7 +538,7 @@ static void free_lid_switch(void)
        input_free_device(lid_switch_idev);
 }
 
-static int __devinit xo1_sci_probe(struct platform_device *pdev)
+static int xo1_sci_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int r;
@@ -613,7 +613,7 @@ err_ebook:
        return r;
 }
 
-static int __devexit xo1_sci_remove(struct platform_device *pdev)
+static int xo1_sci_remove(struct platform_device *pdev)
 {
        mfd_cell_disable(pdev);
        free_irq(sci_irq, pdev);
@@ -632,7 +632,7 @@ static struct platform_driver xo1_sci_driver = {
                .name = "olpc-xo1-sci-acpi",
        },
        .probe = xo1_sci_probe,
-       .remove = __devexit_p(xo1_sci_remove),
+       .remove = xo1_sci_remove,
        .suspend = xo1_sci_suspend,
        .resume = xo1_sci_resume,
 };
index 7a9ad30d6c9f60b47623fcd9b9e72291e7e9a8fd..3dc9aee41d913de3c59a3c04fee8dac814467ca5 100644 (file)
@@ -35,7 +35,7 @@ static struct pci_device_id scx200_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci,scx200_tbl);
 
-static int __devinit scx200_probe(struct pci_dev *, const struct pci_device_id *);
+static int scx200_probe(struct pci_dev *, const struct pci_device_id *);
 
 static struct pci_driver scx200_pci_driver = {
        .name = "scx200",
@@ -45,7 +45,7 @@ static struct pci_driver scx200_pci_driver = {
 
 static DEFINE_MUTEX(scx200_gpio_config_lock);
 
-static void __devinit scx200_init_shadow(void)
+static void scx200_init_shadow(void)
 {
        int bank;
 
@@ -54,7 +54,7 @@ static void __devinit scx200_init_shadow(void)
                scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
 }
 
-static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned base;
 
index 933bea5a601d565b9affe8699a212b8275d789ad..0f92173a12b6ee1a1d5512c867585cd1ee07fc12 100644 (file)
@@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
  * globally purge translation cache of a virtual address or all TLB's
  * @cpumask: mask of all cpu's in which the address is to be removed
  * @mm: mm_struct containing virtual address range
- * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu)
+ * @start: start virtual address to be removed from TLB
+ * @end: end virtual address to be remove from TLB
  * @cpu: the current cpu
  *
  * This is the entry point for initiating any UV global TLB shootdown.
@@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
  */
 const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                                struct mm_struct *mm, unsigned long start,
-                               unsigned end, unsigned int cpu)
+                               unsigned long end, unsigned int cpu)
 {
        int locals = 0;
        int remotes = 0;
@@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 
        record_send_statistics(stat, locals, hubs, remotes, bau_desc);
 
-       bau_desc->payload.address = start;
+       if (!end || (end - start) <= PAGE_SIZE)
+               bau_desc->payload.address = start;
+       else
+               bau_desc->payload.address = TLB_FLUSH_ALL;
        bau_desc->payload.sending_cpu = cpu;
        /*
         * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
index 05f404f53f59ceeade47d9fad8694d20599ee88b..28e3fa9056ea6de9dbf73b512e1ea7deb647d1fa 100644 (file)
 183    i386    getcwd                  sys_getcwd
 184    i386    capget                  sys_capget
 185    i386    capset                  sys_capset
-186    i386    sigaltstack             ptregs_sigaltstack              stub32_sigaltstack
+186    i386    sigaltstack             sys_sigaltstack                 compat_sys_sigaltstack
 187    i386    sendfile                sys_sendfile                    sys32_sendfile
 188    i386    getpmsg
 189    i386    putpmsg
index 7c58c84b7bc8dae578f7cee7dc2433ad46e69f03..dc97328bd90ad189f10d3f8c44684e66ac937782 100644 (file)
 128    64      rt_sigtimedwait         sys_rt_sigtimedwait
 129    64      rt_sigqueueinfo         sys_rt_sigqueueinfo
 130    common  rt_sigsuspend           sys_rt_sigsuspend
-131    64      sigaltstack             stub_sigaltstack
+131    64      sigaltstack             sys_sigaltstack
 132    common  utime                   sys_utime
 133    common  mknod                   sys_mknod
 134    64      uselib
 522    x32     rt_sigpending           sys32_rt_sigpending
 523    x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait
 524    x32     rt_sigqueueinfo         sys32_rt_sigqueueinfo
-525    x32     sigaltstack             stub_x32_sigaltstack
+525    x32     sigaltstack             compat_sys_sigaltstack
 526    x32     timer_create            compat_sys_timer_create
 527    x32     mq_notify               compat_sys_mq_notify
 528    x32     kexec_load              compat_sys_kexec_load
index cc2f8c1312862e96006a546ae355292391039958..872eb60e78064a90900e9133a29728a6c3774cee 100644 (file)
@@ -55,7 +55,7 @@ static FILE           *input_file;    /* Input file name */
 static void usage(const char *err)
 {
        if (err)
-               fprintf(stderr, "Error: %s\n\n", err);
+               fprintf(stderr, "%s: Error: %s\n\n", prog, err);
        fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog);
        fprintf(stderr, "\t-y   64bit mode\n");
        fprintf(stderr, "\t-n   32bit mode\n");
@@ -269,7 +269,13 @@ int main(int argc, char **argv)
                insns++;
        }
 
-       fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed);
+       fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+               prog,
+               (errors) ? "Failure" : "Success",
+               insns,
+               (input_file) ? "given" : "random",
+               errors,
+               seed);
 
        return errors ? 1 : 0;
 }
index 5a1847d619306e5f0ed5ed5570c53c69a8ce2315..79d67bd507fa6c5bd779defa312943b1d99a47f6 100644 (file)
@@ -814,12 +814,14 @@ int main(int argc, char **argv)
        read_relocs(fp);
        if (show_absolute_syms) {
                print_absolute_symbols();
-               return 0;
+               goto out;
        }
        if (show_absolute_relocs) {
                print_absolute_relocs();
-               return 0;
+               goto out;
        }
        emit_relocs(as_text, use_real_mode);
+out:
+       fclose(fp);
        return 0;
 }
index 983997041963840039ec12a076e9b879cfdae0c7..53c90fd412d1a4637fcb17aeaf1a5d5978a2160a 100644 (file)
@@ -13,8 +13,7 @@ endmenu
 config UML_X86
        def_bool y
        select GENERIC_FIND_FIRST_BIT
-       select GENERIC_KERNEL_THREAD
-       select GENERIC_KERNEL_EXECVE
+       select GENERIC_SIGALTSTACK
 
 config 64BIT
        bool "64-bit kernel" if SUBARCH = "x86"
index 755133258c45bd0d1b9a1997e6ac272738c64954..54f8102ccde5d2774f375f6584c31c712f46d915 100644 (file)
@@ -86,4 +86,5 @@ extern long arch_prctl(struct task_struct *task, int code,
                       unsigned long __user *addr);
 
 #endif
+#define user_stack_pointer(regs) PT_REGS_SP(regs)
 #endif /* __UM_X86_PTRACE_H */
index bdaa08cfbcf4bc38eecc3ec57e34c5b0e62ecf2c..71cef48ea5cd5b84abb1216d24ff04b18911eaec 100644 (file)
@@ -342,9 +342,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc,
 {
        int err = 0;
 
-       err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
-       err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
-       err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
+       err |= __save_altstack(&uc->uc_stack, sp);
        err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
        err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
        return err;
@@ -529,10 +527,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __put_user(0, &frame->uc.uc_link);
-       err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-       err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
-                         &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+       err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs));
        err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
                               set->sig[0]);
        err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
index 812e98c098e40eeb771212dc40f9d6955d2e7de8..a0c3b0d1a1220082a64d8c977b61e607c7db428c 100644 (file)
@@ -27,7 +27,6 @@
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
 #define ptregs_vm86 sys_vm86
-#define ptregs_sigaltstack sys_sigaltstack
 
 #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
 #include <asm/syscalls_32.h>
index 170bd926a69cd4eddbd64d03f0da41d719879bd0..f2f0723070caea848a88fe1f96863943fc3df121 100644 (file)
@@ -31,7 +31,6 @@
 #define stub_fork sys_fork
 #define stub_vfork sys_vfork
 #define stub_execve sys_execve
-#define stub_sigaltstack sys_sigaltstack
 #define stub_rt_sigreturn sys_rt_sigreturn
 
 #define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
index 205ad328aa52810975dd332771a16911f5e6935b..c74436e687bf8984b722efa1a657e1a6a8b47f3b 100644 (file)
@@ -60,7 +60,7 @@ notrace static cycle_t vread_tsc(void)
 
 static notrace cycle_t vread_hpet(void)
 {
-       return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+       return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + HPET_COUNTER);
 }
 
 #ifdef CONFIG_PARAVIRT_CLOCK
index 138e5667409a3415492e860c8cfa708028d6d467..39928d16be3bf86e671426387504ee68b86d08cd 100644 (file)
@@ -1517,72 +1517,51 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 }
 
-#ifdef CONFIG_XEN_PVHVM
-#define HVM_SHARED_INFO_ADDR 0xFE700000UL
-static struct shared_info *xen_hvm_shared_info;
-static unsigned long xen_hvm_sip_phys;
-static int xen_major, xen_minor;
-
-static void xen_hvm_connect_shared_info(unsigned long pfn)
+void __ref xen_hvm_init_shared_info(void)
 {
+       int cpu;
        struct xen_add_to_physmap xatp;
+       static struct shared_info *shared_info_page = 0;
 
+       if (!shared_info_page)
+               shared_info_page = (struct shared_info *)
+                       extend_brk(PAGE_SIZE, PAGE_SIZE);
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;
-       xatp.gpfn = pfn;
+       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
        if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
                BUG();
 
-}
-static void __init xen_hvm_set_shared_info(struct shared_info *sip)
-{
-       int cpu;
-
-       HYPERVISOR_shared_info = sip;
+       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
 
        /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
         * page, we use it in the event channel upcall and in some pvclock
         * related functions. We don't need the vcpu_info placement
         * optimizations because we don't use any pv_mmu or pv_irq op on
-        * HVM. */
-       for_each_online_cpu(cpu)
+        * HVM.
+        * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
+        * online but xen_hvm_init_shared_info is run at resume time too and
+        * in that case multiple vcpus might be online. */
+       for_each_online_cpu(cpu) {
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
-}
-
-/* Reconnect the shared_info pfn to a (new) mfn */
-void xen_hvm_resume_shared_info(void)
-{
-       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
-}
-
-/* Xen tools prior to Xen 4 do not provide a E820_Reserved area for guest usage.
- * On these old tools the shared info page will be placed in E820_Ram.
- * Xen 4 provides a E820_Reserved area at 0xFC000000, and this code expects
- * that nothing is mapped up to HVM_SHARED_INFO_ADDR.
- * Xen 4.3+ provides an explicit 1MB area at HVM_SHARED_INFO_ADDR which is used
- * here for the shared info page. */
-static void __init xen_hvm_init_shared_info(void)
-{
-       if (xen_major < 4) {
-               xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
-               xen_hvm_sip_phys = __pa(xen_hvm_shared_info);
-       } else {
-               xen_hvm_sip_phys = HVM_SHARED_INFO_ADDR;
-               set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_hvm_sip_phys);
-               xen_hvm_shared_info =
-               (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
        }
-       xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
-       xen_hvm_set_shared_info(xen_hvm_shared_info);
 }
 
+#ifdef CONFIG_XEN_PVHVM
 static void __init init_hvm_pv_info(void)
 {
-       uint32_t ecx, edx, pages, msr, base;
+       int major, minor;
+       uint32_t eax, ebx, ecx, edx, pages, msr, base;
        u64 pfn;
 
        base = xen_cpuid_base();
+       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+
+       major = eax >> 16;
+       minor = eax & 0xffff;
+       printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
+
        cpuid(base + 2, &pages, &msr, &ecx, &edx);
 
        pfn = __pa(hypercall_page);
@@ -1633,22 +1612,12 @@ static void __init xen_hvm_guest_init(void)
 
 static bool __init xen_hvm_platform(void)
 {
-       uint32_t eax, ebx, ecx, edx, base;
-
        if (xen_pv_domain())
                return false;
 
-       base = xen_cpuid_base();
-       if (!base)
+       if (!xen_cpuid_base())
                return false;
 
-       cpuid(base + 1, &eax, &ebx, &ecx, &edx);
-
-       xen_major = eax >> 16;
-       xen_minor = eax & 0xffff;
-
-       printk(KERN_INFO "Xen version %d.%d.\n", xen_major, xen_minor);
-
        return true;
 }
 
@@ -1668,6 +1637,7 @@ const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
        .name                   = "Xen HVM",
        .detect                 = xen_hvm_platform,
        .init_platform          = xen_hvm_guest_init,
+       .x2apic_available       = xen_x2apic_para_available,
 };
 EXPORT_SYMBOL(x86_hyper_xen_hvm);
 #endif
index 4f7d2599b484a67222cbfa68f7b929c35975732e..34bc4cee8887b2c2d974c99ca81b78577f719ff9 100644 (file)
@@ -432,13 +432,6 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
        play_dead_common();
        HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
        cpu_bringup();
-       /*
-        * Balance out the preempt calls - as we are running in cpu_idle
-        * loop which has been called at bootup from cpu_bringup_and_idle.
-        * The cpucpu_bringup_and_idle called cpu_bringup which made a
-        * preempt_disable() So this preempt_enable will balance it out.
-        */
-       preempt_enable();
 }
 
 #else /* !CONFIG_HOTPLUG_CPU */
index ae8a00c39de4b0d02cfad0722715d0fbd159a1cb..45329c8c226e4c4070f16a791b300265a0bf472b 100644 (file)
@@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
 #ifdef CONFIG_XEN_PVHVM
        int cpu;
-       xen_hvm_resume_shared_info();
+       xen_hvm_init_shared_info();
        xen_callback_vector();
        xen_unplug_emulated_devices();
        if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
index f9643fc50de571636347a1e0510d45f916728967..33ca6e42a4caabb412350563a1f8349fd77b7789 100644 (file)
@@ -89,11 +89,11 @@ ENTRY(xen_iret)
         */
 #ifdef CONFIG_SMP
        GET_THREAD_INFO(%eax)
-       movl TI_cpu(%eax), %eax
-       movl __per_cpu_offset(,%eax,4), %eax
-       mov xen_vcpu(%eax), %eax
+       movl %ss:TI_cpu(%eax), %eax
+       movl %ss:__per_cpu_offset(,%eax,4), %eax
+       mov %ss:xen_vcpu(%eax), %eax
 #else
-       movl xen_vcpu, %eax
+       movl %ss:xen_vcpu, %eax
 #endif
 
        /* check IF state we're restoring */
@@ -106,11 +106,11 @@ ENTRY(xen_iret)
         * resuming the code, so we don't have to be worried about
         * being preempted to another CPU.
         */
-       setz XEN_vcpu_info_mask(%eax)
+       setz %ss:XEN_vcpu_info_mask(%eax)
 xen_iret_start_crit:
 
        /* check for unmasked and pending */
-       cmpw $0x0001, XEN_vcpu_info_pending(%eax)
+       cmpw $0x0001, %ss:XEN_vcpu_info_pending(%eax)
 
        /*
         * If there's something pending, mask events again so we can
@@ -118,7 +118,7 @@ xen_iret_start_crit:
         * touch XEN_vcpu_info_mask.
         */
        jne 1f
-       movb $1, XEN_vcpu_info_mask(%eax)
+       movb $1, %ss:XEN_vcpu_info_mask(%eax)
 
 1:     popl %eax
 
index d2e73d19d366d54820e453f44ff886cecea8d174..a95b41744ad0bafdcde069cb965cabb67ab0f61b 100644 (file)
@@ -40,7 +40,7 @@ void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
 
 void xen_callback_vector(void);
-void xen_hvm_resume_shared_info(void);
+void xen_hvm_init_shared_info(void);
 void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
index 73d34e77c39c136b0066236b7b8a2f43d8b9aa0c..5aab1acabf1cb4440c0b5656ecff733bc1df7b07 100644 (file)
@@ -13,8 +13,6 @@ 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
        select CLONE_BACKWARDS
        select IRQ_DOMAIN
index 4acb5feba1fb7ae0bb830fed17b0391ae7a8483a..172a02a6ad146fea24ab966cf46a3612434a03da 100644 (file)
@@ -170,4 +170,19 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        consistent_sync(vaddr, size, direction);
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif /* _XTENSA_DMA_MAPPING_H */
index 04890d6e233536d1cdef5f17b5d4af530b682270..8554b2c8b17a0128bc873f2d67b194462f89c2bf 100644 (file)
@@ -12,7 +12,7 @@
 #define _XTENSA_MMU_H
 
 #ifndef CONFIG_MMU
-#include <asm/nommu.h>
+#include <asm-generic/mmu.h>
 #else
 
 /* Default "unsigned long" context */
diff --git a/arch/xtensa/include/asm/nommu.h b/arch/xtensa/include/asm/nommu.h
deleted file mode 100644 (file)
index dce2c43..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-typedef struct {
-       unsigned long end_brk;
-} mm_context_t;
index 58bf6fd3f913d4458162c4ddef8a4234a0a7cf6e..682b1deac1f281912c6462b556ff6307ac5c2fd3 100644 (file)
@@ -63,6 +63,8 @@ struct pt_regs {
 #  define profile_pc(regs) instruction_pointer(regs)
 # endif
 
+#define user_stack_pointer(regs) ((regs)->areg[1])
+
 #else  /* __ASSEMBLY__ */
 
 # include <asm/asm-offsets.h>
index e002dbcc88b6e621bf25c8a73ce2e60641912126..eb63ea87815c9e9eba1e1ad3af11c70297e3d7c5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _XTENSA_UNISTD_H
 #define _XTENSA_UNISTD_H
 
-#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
 
index b88ce96f2af9a71f410f86b9d61d276ca1ce2ab8..dacf716dd3e0e66e857ce27cd9fcabaed36c8b89 100644 (file)
@@ -97,12 +97,6 @@ typedef struct {
 
 #define SA_RESTORER    0x04000000
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index 74638ec234c807ccaaed0a77ce0eceb71e2997c7..c88202f973d944f7e9c847b13d48c8ce24c87230 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/sched/sysctl.h>
 
 #include "blk.h"
 
index 9a289d7c84bbedc6ca2e17cf74c201acc43fe7cd..3993ebf4135fb1adb8e25c9562dadd996d1c6be2 100644 (file)
@@ -35,6 +35,8 @@ static DEFINE_IDR(ext_devt_idr);
 
 static struct device_type disk_type;
 
+static void disk_check_events(struct disk_events *ev,
+                             unsigned int *clearing_ptr);
 static void disk_alloc_events(struct gendisk *disk);
 static void disk_add_events(struct gendisk *disk);
 static void disk_del_events(struct gendisk *disk);
@@ -1549,6 +1551,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
        const struct block_device_operations *bdops = disk->fops;
        struct disk_events *ev = disk->ev;
        unsigned int pending;
+       unsigned int clearing = mask;
 
        if (!ev) {
                /* for drivers still using the old ->media_changed method */
@@ -1558,34 +1561,53 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
                return 0;
        }
 
-       /* tell the workfn about the events being cleared */
+       disk_block_events(disk);
+
+       /*
+        * store the union of mask and ev->clearing on the stack so that the
+        * race with disk_flush_events does not cause ambiguity (ev->clearing
+        * can still be modified even if events are blocked).
+        */
        spin_lock_irq(&ev->lock);
-       ev->clearing |= mask;
+       clearing |= ev->clearing;
+       ev->clearing = 0;
        spin_unlock_irq(&ev->lock);
 
-       /* uncondtionally schedule event check and wait for it to finish */
-       disk_block_events(disk);
-       queue_delayed_work(system_freezable_wq, &ev->dwork, 0);
-       flush_delayed_work(&ev->dwork);
-       __disk_unblock_events(disk, false);
+       disk_check_events(ev, &clearing);
+       /*
+        * if ev->clearing is not 0, the disk_flush_events got called in the
+        * middle of this function, so we want to run the workfn without delay.
+        */
+       __disk_unblock_events(disk, ev->clearing ? true : false);
 
        /* then, fetch and clear pending events */
        spin_lock_irq(&ev->lock);
-       WARN_ON_ONCE(ev->clearing & mask);      /* cleared by workfn */
        pending = ev->pending & mask;
        ev->pending &= ~mask;
        spin_unlock_irq(&ev->lock);
+       WARN_ON_ONCE(clearing & mask);
 
        return pending;
 }
 
+/*
+ * Separate this part out so that a different pointer for clearing_ptr can be
+ * passed in for disk_clear_events.
+ */
 static void disk_events_workfn(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
        struct disk_events *ev = container_of(dwork, struct disk_events, dwork);
+
+       disk_check_events(ev, &ev->clearing);
+}
+
+static void disk_check_events(struct disk_events *ev,
+                             unsigned int *clearing_ptr)
+{
        struct gendisk *disk = ev->disk;
        char *envp[ARRAY_SIZE(disk_uevents) + 1] = { };
-       unsigned int clearing = ev->clearing;
+       unsigned int clearing = *clearing_ptr;
        unsigned int events;
        unsigned long intv;
        int nr_events = 0, i;
@@ -1598,7 +1620,7 @@ static void disk_events_workfn(struct work_struct *work)
 
        events &= ~ev->pending;
        ev->pending |= events;
-       ev->clearing &= ~clearing;
+       *clearing_ptr &= ~clearing;
 
        intv = disk_events_poll_jiffies(disk);
        if (!ev->block && intv)
index eb30e5ab4cab6810197aa12c36d6421962a6b3f6..b679bf8478f7a4bd3483127853cceb75185f97aa 100644 (file)
@@ -226,16 +226,6 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
        struct acpi_memory_info *info;
        int node;
 
-
-       /* Get the range from the _CRS */
-       result = acpi_memory_get_device_resources(mem_device);
-       if (result) {
-               dev_err(&mem_device->device->dev,
-                       "get_device_resources failed\n");
-               mem_device->state = MEMORY_INVALID_STATE;
-               return result;
-       }
-
        node = acpi_get_node(mem_device->device->handle);
        /*
         * Tell the VM there is more memory here...
@@ -342,14 +332,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
                        break;
                }
 
-               if (acpi_memory_check_device(mem_device))
-                       break;
-
-               if (acpi_memory_enable_device(mem_device)) {
-                       acpi_handle_err(handle,"Cannot enable memory device\n");
-                       break;
-               }
-
                ost_code = ACPI_OST_SC_SUCCESS;
                break;
 
index c8bc24bd1f720580b6e80ce4225277c781576b23..bc7a03ded064520fd88d64a4d335bf1d0a6813e8 100644 (file)
@@ -162,5 +162,5 @@ acpi-y +=           \
        utxferror.o     \
        utxfmutex.o
 
-acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o utclib.o
+acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o
 
diff --git a/drivers/acpi/acpica/utclib.c b/drivers/acpi/acpica/utclib.c
deleted file mode 100644 (file)
index 19ea475..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/******************************************************************************
- *
- * 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 00a783661d0b5548b65882f312faa4a116ff5762..46f80e2c92f7da893ff28f5993d89fa01efc323a 100644 (file)
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
        if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 &&
            *access_bit_width < 32)
                *access_bit_width = 32;
+       else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 &&
+           *access_bit_width < 64)
+               *access_bit_width = 64;
 
        if ((bit_width + bit_offset) > *access_bit_width) {
                pr_warning(FW_BUG APEI_PFX
index e6defd86b42454e98d2828abf2d99240d9e68b18..1e5d8a40101e274f5d6ce2bfe1a24a486a671af7 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/time.h>
 #include <linux/cper.h>
 #include <linux/acpi.h>
+#include <linux/pci.h>
 #include <linux/aer.h>
 
 /*
@@ -249,6 +250,10 @@ static const char *cper_pcie_port_type_strs[] = {
 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
                            const struct acpi_hest_generic_data *gdata)
 {
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+       struct pci_dev *dev;
+#endif
+
        if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
                printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
                       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
@@ -281,10 +286,18 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
        "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
        pfx, pcie->bridge.secondary_status, pcie->bridge.control);
 #ifdef CONFIG_ACPI_APEI_PCIEAER
-       if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
-               struct aer_capability_regs *aer_regs = (void *)pcie->aer_info;
-               cper_print_aer(pfx, gdata->error_severity, aer_regs);
+       dev = pci_get_domain_bus_and_slot(pcie->device_id.segment,
+                       pcie->device_id.bus, pcie->device_id.function);
+       if (!dev) {
+               pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n",
+                       pcie->device_id.segment, pcie->device_id.bus,
+                       pcie->device_id.slot, pcie->device_id.function);
+               return;
        }
+       if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO)
+               cper_print_aer(pfx, dev, gdata->error_severity,
+                               (struct aer_capability_regs *) pcie->aer_info);
+       pci_dev_put(dev);
 #endif
 }
 
index 903549df809bf1b02cc95df234dd7442cd3fb3ee..04ab5c9d3cedc16ac5250ee70b610829216d6117 100644 (file)
@@ -111,8 +111,17 @@ retry_next:
        if (rc)
                goto out;
        /* no more record */
-       if (id == APEI_ERST_INVALID_RECORD_ID)
+       if (id == APEI_ERST_INVALID_RECORD_ID) {
+               /*
+                * If the persistent store is empty initially, the function
+                * 'erst_read' below will return "-ENOENT" value. This causes
+                * 'retry_next' label is entered again. The returned value
+                * should be zero indicating the read operation is EOF.
+                */
+               len = 0;
+
                goto out;
+       }
 retry:
        rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len);
        /* The record may be cleared by others, try read next record */
index f09dc987cf17bce2ea762cdf902165cdbb7bd3d9..c6ff606c6d5bb35d51b2bff23588914f99a6ba83 100644 (file)
@@ -358,8 +358,7 @@ 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;
+       return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL;
 }
 
 /**
index 01551840d2365389ae8e0ea3c67054bc8655452f..35da18113216c367eae553371e9164a726a70f44 100644 (file)
 
 #define ACPI_GLUE_DEBUG        0
 #if ACPI_GLUE_DEBUG
-#define DBG(x...) printk(PREFIX x)
+#define DBG(fmt, ...)                                          \
+       printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__)
 #else
-#define DBG(x...) do { } while(0)
+#define DBG(fmt, ...)                                          \
+do {                                                           \
+       if (0)                                                  \
+               printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__);   \
+} while (0)
 #endif
 static LIST_HEAD(bus_type_list);
 static DECLARE_RWSEM(bus_type_sem);
@@ -292,7 +297,7 @@ static int acpi_platform_notify(struct device *dev)
        if (!ret) {
                struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-               acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
+               acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer);
                DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
                kfree(buffer.pointer);
        } else
index 3ff267861541f7570a5b110b7893e0cb012f5917..bd22f8667eed65e3889e61dcc357d85f5f3d1239 100644 (file)
@@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
                return acpi_rsdp;
 #endif
 
-       if (efi_enabled) {
+       if (efi_enabled(EFI_CONFIG_TABLES)) {
                if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
                        return efi.acpi20;
                else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
index 7db61b8fa11f0337de7c8dc82e80ae1fb3cb6df8..6e7b9d5238124586ca10a000726472ff29cbc191 100644 (file)
@@ -445,11 +445,8 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
                return -ENODEV;
 
        ret = acpi_bus_get_device(handle, &acpi_dev);
-       if (ret)
-               goto no_power_resource;
-
-       if (!acpi_dev->power.flags.power_resources)
-               goto no_power_resource;
+       if (ret || !acpi_dev->power.flags.power_resources)
+               return -ENODEV;
 
        powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL);
        if (!powered_device)
@@ -471,10 +468,6 @@ 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!\n");
-       return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
 
index f1a5da44591dcd1b415b57e638165318bc13e793..ed9a1cc690be5fa8cd3844394128216350904a7e 100644 (file)
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
                return -EINVAL;
        }
 
+       if (!dev)
+               return -EINVAL;
+
        dev->cpu = pr->id;
 
        if (max_cstate == 0)
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
                }
 
                /* Populate Updated C-state information */
+               acpi_processor_get_power_info(pr);
                acpi_processor_setup_cpuidle_states(pr);
 
                /* Enable all cpuidle devices */
index 836bfe0690422855c80ecfe41895a4fe667bfd14..53e7ac9403a7dc21502e90a698ef1b27ad668a37 100644 (file)
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
        if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
            || boot_cpu_data.x86 == 0x11) {
                rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
+               /*
+                * MSR C001_0064+:
+                * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
+                */
+               if (!(hi & BIT(31)))
+                       return;
+
                fid = lo & 0x3f;
                did = (lo >> 6) & 7;
                if (boot_cpu_data.x86 == 0x10)
index 53502d1bbf26f1bc9b5ac46d7db7ec11caa792a7..c88be6c37c309b79b147ea683b9e177b1b8cca33 100644 (file)
@@ -1346,7 +1346,7 @@ static void acpi_device_set_id(struct acpi_device *device)
                        acpi_add_id(device, ACPI_DOCK_HID);
                else if (!acpi_ibm_smbus_match(device))
                        acpi_add_id(device, ACPI_SMBUS_IBM_HID);
-               else if (!acpi_device_hid(device) &&
+               else if (list_empty(&device->pnp.ids) &&
                         ACPI_IS_ROOT_DEVICE(device->parent)) {
                        acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
                        strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
index a2fc56d2e6819d04a86474157e330ff0467d6b09..cdbad3a454a085a7aa17bf1ae29e4a22b73c5c37 100644 (file)
@@ -45,7 +45,6 @@ static int amba_match(struct device *dev, struct device_driver *drv)
        return amba_lookup(pcdrv->id_table, pcdev) != NULL;
 }
 
-#ifdef CONFIG_HOTPLUG
 static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct amba_device *pcdev = to_amba_device(dev);
@@ -58,9 +57,6 @@ static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
        retval = add_uevent_var(env, "MODALIAS=amba:d%08X", pcdev->periphid);
        return retval;
 }
-#else
-#define amba_uevent NULL
-#endif
 
 #define amba_attr_func(name,fmt,arg...)                                        \
 static ssize_t name##_show(struct device *_dev,                                \
index 0576a7dd32a53a19fa2d7283e396ecf8c901de27..536c166f4253eac9b8bcdf4b9c71c45c35b18b45 100644 (file)
@@ -243,7 +243,7 @@ static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb)
        gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4);
 }
 
-static int __devinit tegra_ahb_probe(struct platform_device *pdev)
+static int tegra_ahb_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct tegra_ahb *ahb;
@@ -267,7 +267,7 @@ static int __devinit tegra_ahb_probe(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id tegra_ahb_of_match[] __devinitconst = {
+static const struct of_device_id tegra_ahb_of_match[] = {
        { .compatible = "nvidia,tegra30-ahb", },
        { .compatible = "nvidia,tegra20-ahb", },
        {},
index 7862d17976b7532f48204cbf4210ffb6d4984f97..495aeed26779c96ad7555ad646f0d3ae03ca69dc 100644 (file)
@@ -53,6 +53,7 @@
 
 enum {
        AHCI_PCI_BAR_STA2X11    = 0,
+       AHCI_PCI_BAR_ENMOTUS    = 2,
        AHCI_PCI_BAR_STANDARD   = 5,
 };
 
@@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
        { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
+       /* Enmotus */
+       { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
+
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -1057,6 +1061,86 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
+int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
+{
+       int rc;
+       unsigned int maxvec;
+
+       if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) {
+               rc = pci_enable_msi_block_auto(pdev, &maxvec);
+               if (rc > 0) {
+                       if ((rc == maxvec) || (rc == 1))
+                               return rc;
+                       /*
+                        * Assume that advantage of multipe MSIs is negated,
+                        * so fallback to single MSI mode to save resources
+                        */
+                       pci_disable_msi(pdev);
+                       if (!pci_enable_msi(pdev))
+                               return 1;
+               }
+       }
+
+       pci_intx(pdev, 1);
+       return 0;
+}
+
+/**
+ *     ahci_host_activate - start AHCI host, request IRQs and register it
+ *     @host: target ATA host
+ *     @irq: base IRQ number to request
+ *     @n_msis: number of MSIs allocated for this host
+ *     @irq_handler: irq_handler used when requesting IRQs
+ *     @irq_flags: irq_flags used when requesting IRQs
+ *
+ *     Similar to ata_host_activate, but requests IRQs according to AHCI-1.1
+ *     when multiple MSIs were allocated. That is one MSI per port, starting
+ *     from @irq.
+ *
+ *     LOCKING:
+ *     Inherited from calling layer (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
+{
+       int i, rc;
+
+       /* Sharing Last Message among several ports is not supported */
+       if (n_msis < host->n_ports)
+               return -EINVAL;
+
+       rc = ata_host_start(host);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < host->n_ports; i++) {
+               rc = devm_request_threaded_irq(host->dev,
+                       irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
+                       dev_driver_string(host->dev), host->ports[i]);
+               if (rc)
+                       goto out_free_irqs;
+       }
+
+       for (i = 0; i < host->n_ports; i++)
+               ata_port_desc(host->ports[i], "irq %d", irq + i);
+
+       rc = ata_host_register(host, &ahci_sht);
+       if (rc)
+               goto out_free_all_irqs;
+
+       return 0;
+
+out_free_all_irqs:
+       i = host->n_ports;
+out_free_irqs:
+       for (i--; i >= 0; i--)
+               devm_free_irq(host->dev, irq + i, host->ports[i]);
+
+       return rc;
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned int board_id = ent->driver_data;
@@ -1065,7 +1149,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
        struct ata_host *host;
-       int n_ports, i, rc;
+       int n_ports, n_msis, i, rc;
        int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
 
        VPRINTK("ENTER\n");
@@ -1098,9 +1182,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_info(&pdev->dev,
                         "PDC42819 can only drive SATA devices with this driver\n");
 
-       /* The Connext uses non-standard BAR */
+       /* Both Connext and Enmotus devices use non-standard BARs */
        if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
                ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
+       else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
+               ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
 
        /* acquire resources */
        rc = pcim_enable_device(pdev);
@@ -1150,11 +1236,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ahci_sb600_enable_64bit(pdev))
                hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
 
-       if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
-               pci_intx(pdev, 1);
-
        hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
 
+       n_msis = ahci_init_interrupts(pdev, hpriv);
+       if (n_msis > 1)
+               hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
+
        /* save initial config */
        ahci_pci_save_initial_config(pdev, hpriv);
 
@@ -1250,6 +1337,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        ahci_pci_print_info(host);
 
        pci_set_master(pdev);
+
+       if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
+               return ahci_host_activate(host, pdev->irq, n_msis);
+
        return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
                                 &ahci_sht);
 }
index 9be471200a07657f1f655ea31d805e0d6223c24b..b830e6c9fe49f385b77405c188b100a7afcc0570 100644 (file)
@@ -231,6 +231,7 @@ enum {
        AHCI_HFLAG_DELAY_ENGINE         = (1 << 15), /* do not start engine on
                                                        port start (wait until
                                                        error-handling stage) */
+       AHCI_HFLAG_MULTI_MSI            = (1 << 16), /* multiple PCI MSIs */
 
        /* ap->flags bits */
 
@@ -297,6 +298,8 @@ struct ahci_port_priv {
        unsigned int            ncq_saw_d2h:1;
        unsigned int            ncq_saw_dmas:1;
        unsigned int            ncq_saw_sdb:1;
+       u32                     intr_status;    /* interrupts to handle */
+       spinlock_t              lock;           /* protects parent ata_port */
        u32                     intr_mask;      /* interrupts to enable */
        bool                    fbs_supported;  /* set iff FBS is supported */
        bool                    fbs_enabled;    /* set iff FBS is enabled */
@@ -359,7 +362,10 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv,
                          struct ata_port_info *pi);
 int ahci_reset_em(struct ata_host *host);
 irqreturn_t ahci_interrupt(int irq, void *dev_instance);
+irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance);
+irqreturn_t ahci_thread_fn(int irq, void *dev_instance);
 void ahci_print_info(struct ata_host *host, const char *scc_s);
+int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis);
 
 static inline void __iomem *__ahci_port_base(struct ata_host *host,
                                             unsigned int port_no)
index 1cc467bdb63d9e4b456743452c5168e606db79f2..7a8a2841fe64a93effec85f1ff5fc6dc4c610d06 100644 (file)
@@ -86,7 +86,7 @@ static struct scsi_host_template ahci_platform_sht = {
        AHCI_SHT("ahci_platform"),
 };
 
-static int __devinit ahci_probe(struct platform_device *pdev)
+static int ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
index acffcf0b3ad3345f00563fbe2a1fdb018e96deaf..174eca609b425e06bf788de9ba50f07c17ffbbdc 100644 (file)
@@ -1270,7 +1270,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
  *     they are found return an error code so we can turn off DMA
  */
 
-static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+static int piix_check_450nx_errata(struct pci_dev *ata_dev)
 {
        struct pci_dev *pdev = NULL;
        u16 cfg;
@@ -1296,8 +1296,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
        return no_piix_dma;
 }
 
-static void __devinit piix_init_pcs(struct ata_host *host,
-                                   const struct piix_map_db *map_db)
+static void piix_init_pcs(struct ata_host *host,
+                         const struct piix_map_db *map_db)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        u16 pcs, new_pcs;
@@ -1313,9 +1313,9 @@ static void __devinit piix_init_pcs(struct ata_host *host,
        }
 }
 
-static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
-                                              struct ata_port_info *pinfo,
-                                              const struct piix_map_db *map_db)
+static const int *piix_init_sata_map(struct pci_dev *pdev,
+                                    struct ata_port_info *pinfo,
+                                    const struct piix_map_db *map_db)
 {
        const int *map;
        int i, invalid_map = 0;
@@ -1392,7 +1392,7 @@ static bool piix_no_sidpr(struct ata_host *host)
        return false;
 }
 
-static int __devinit piix_init_sidpr(struct ata_host *host)
+static int piix_init_sidpr(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        struct piix_host_priv *hpriv = host->private_data;
@@ -1595,8 +1595,7 @@ static void piix_ignore_devices_quirk(struct ata_host *host)
  *     Zero on success, or -ERRNO value.
  */
 
-static int __devinit piix_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct device *dev = &pdev->dev;
        struct ata_port_info port_info[2];
index 320712a7b9eaac3174f3a96de8693b63dee5f1af..34c82167b9625f41666125685148b68774036fd9 100644 (file)
@@ -1655,19 +1655,16 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
                ata_port_abort(ap);
 }
 
-static void ahci_port_intr(struct ata_port *ap)
+static void ahci_handle_port_interrupt(struct ata_port *ap,
+                                      void __iomem *port_mmio, u32 status)
 {
-       void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_eh_info *ehi = &ap->link.eh_info;
        struct ahci_port_priv *pp = ap->private_data;
        struct ahci_host_priv *hpriv = ap->host->private_data;
        int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
-       u32 status, qc_active = 0;
+       u32 qc_active = 0;
        int rc;
 
-       status = readl(port_mmio + PORT_IRQ_STAT);
-       writel(status, port_mmio + PORT_IRQ_STAT);
-
        /* ignore BAD_PMP while resetting */
        if (unlikely(resetting))
                status &= ~PORT_IRQ_BAD_PMP;
@@ -1743,6 +1740,107 @@ static void ahci_port_intr(struct ata_port *ap)
        }
 }
 
+void ahci_port_intr(struct ata_port *ap)
+{
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 status;
+
+       status = readl(port_mmio + PORT_IRQ_STAT);
+       writel(status, port_mmio + PORT_IRQ_STAT);
+
+       ahci_handle_port_interrupt(ap, port_mmio, status);
+}
+
+irqreturn_t ahci_thread_fn(int irq, void *dev_instance)
+{
+       struct ata_port *ap = dev_instance;
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       unsigned long flags;
+       u32 status;
+
+       spin_lock_irqsave(&ap->host->lock, flags);
+       status = pp->intr_status;
+       if (status)
+               pp->intr_status = 0;
+       spin_unlock_irqrestore(&ap->host->lock, flags);
+
+       spin_lock_bh(ap->lock);
+       ahci_handle_port_interrupt(ap, port_mmio, status);
+       spin_unlock_bh(ap->lock);
+
+       return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(ahci_thread_fn);
+
+void ahci_hw_port_interrupt(struct ata_port *ap)
+{
+       void __iomem *port_mmio = ahci_port_base(ap);
+       struct ahci_port_priv *pp = ap->private_data;
+       u32 status;
+
+       status = readl(port_mmio + PORT_IRQ_STAT);
+       writel(status, port_mmio + PORT_IRQ_STAT);
+
+       pp->intr_status |= status;
+}
+
+irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance)
+{
+       struct ata_port *ap_this = dev_instance;
+       struct ahci_port_priv *pp = ap_this->private_data;
+       struct ata_host *host = ap_this->host;
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = hpriv->mmio;
+       unsigned int i;
+       u32 irq_stat, irq_masked;
+
+       VPRINTK("ENTER\n");
+
+       spin_lock(&host->lock);
+
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+
+       if (!irq_stat) {
+               u32 status = pp->intr_status;
+
+               spin_unlock(&host->lock);
+
+               VPRINTK("EXIT\n");
+
+               return status ? IRQ_WAKE_THREAD : IRQ_NONE;
+       }
+
+       irq_masked = irq_stat & hpriv->port_map;
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap;
+
+               if (!(irq_masked & (1 << i)))
+                       continue;
+
+               ap = host->ports[i];
+               if (ap) {
+                       ahci_hw_port_interrupt(ap);
+                       VPRINTK("port %u\n", i);
+               } else {
+                       VPRINTK("port %u (no irq)\n", i);
+                       if (ata_ratelimit())
+                               dev_warn(host->dev,
+                                        "interrupt on disabled port %u\n", i);
+               }
+       }
+
+       writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+       spin_unlock(&host->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_WAKE_THREAD;
+}
+EXPORT_SYMBOL_GPL(ahci_hw_interrupt);
+
 irqreturn_t ahci_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
@@ -1951,13 +2049,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
        /* Use the nominal value 10 ms if the read MDAT is zero,
         * the nominal value of DETO is 20 ms.
         */
-       if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
+       if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
            ATA_LOG_DEVSLP_VALID_MASK) {
-               mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
+               mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
                       ATA_LOG_DEVSLP_MDAT_MASK;
                if (!mdat)
                        mdat = 10;
-               deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
+               deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
                if (!deto)
                        deto = 20;
        } else {
@@ -2196,6 +2294,14 @@ static int ahci_port_start(struct ata_port *ap)
         */
        pp->intr_mask = DEF_PORT_IRQ;
 
+       /*
+        * Switch to per-port locking in case each port has its own MSI vector.
+        */
+       if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) {
+               spin_lock_init(&pp->lock);
+               ap->lock = &pp->lock;
+       }
+
        ap->private_data = pp;
 
        /* engage engines, captain */
index 9e8b99af400dc53539ba4e8d45d36696e4818b65..46cd3f4c6aaaf8122c82ea8f60f7e6bcbaf435c6 100644 (file)
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev)
                        }
                }
 
-               /* check and mark DevSlp capability */
-               if (ata_id_has_devslp(dev->id))
-                       dev->flags |= ATA_DFLAG_DEVSLP;
-
-               /* Obtain SATA Settings page from Identify Device Data Log,
-                * which contains DevSlp timing variables etc.
-                * Exclude old devices with ata_id_has_ncq()
+               /* Check and mark DevSlp capability. Get DevSlp timing variables
+                * from SATA Settings page of Identify Device Data Log.
                 */
-               if (ata_id_has_ncq(dev->id)) {
+               if (ata_id_has_devslp(dev->id)) {
+                       u8 sata_setting[ATA_SECT_SIZE];
+                       int i, j;
+
+                       dev->flags |= ATA_DFLAG_DEVSLP;
                        err_mask = ata_read_log_page(dev,
                                                     ATA_LOG_SATA_ID_DEV_DATA,
                                                     ATA_LOG_SATA_SETTINGS,
-                                                    dev->sata_settings,
+                                                    sata_setting,
                                                     1);
                        if (err_mask)
                                ata_dev_dbg(dev,
                                            "failed to get Identify Device Data, Emask 0x%x\n",
                                            err_mask);
+                       else
+                               for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) {
+                                       j = ATA_LOG_DEVSLP_OFFSET + i;
+                                       dev->devslp_timing[i] = sata_setting[j];
+                               }
                }
 
                dev->cdb_len = 16;
index bf039b0e97b79d7f9c9d2bae803ad84850b181b4..bcf4437214f50141e2d1bfe17a0ad02af6f4d81b 100644 (file)
@@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
  */
 static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
 {
-       if (qc->flags & AC_ERR_MEDIA)
+       if (qc->err_mask & AC_ERR_MEDIA)
                return 0;       /* don't retry media errors */
        if (qc->flags & ATA_QCFLAG_IO)
                return 1;       /* otherwise retry anything from fs stack */
index 9764e80f93202bb6d75811885f07bbf98f0f8929..405022d302c3479f9a142ecf93dda695e21878e4 100644 (file)
@@ -791,7 +791,7 @@ static struct ata_port_operations arasan_cf_ops = {
        .set_dmamode = arasan_cf_set_dmamode,
 };
 
-static int __devinit arasan_cf_probe(struct platform_device *pdev)
+static int arasan_cf_probe(struct platform_device *pdev)
 {
        struct arasan_cf_dev *acdev;
        struct arasan_cf_pdata *pdata = dev_get_platdata(&pdev->dev);
@@ -905,7 +905,7 @@ free_clk:
        return ret;
 }
 
-static int __devexit arasan_cf_remove(struct platform_device *pdev)
+static int arasan_cf_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
        struct arasan_cf_dev *acdev = host->ports[0]->private_data;
@@ -955,7 +955,7 @@ MODULE_DEVICE_TABLE(of, arasan_cf_id_table);
 
 static struct platform_driver arasan_cf_driver = {
        .probe          = arasan_cf_probe,
-       .remove         = __devexit_p(arasan_cf_remove),
+       .remove         = arasan_cf_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
index 2a96bb2c53ee520a3c8f6205dc3c3f7e30c01d52..033f3f4c20adc9def5cca1a683bdd7e08e5a1fa7 100644 (file)
@@ -313,7 +313,7 @@ static struct ata_port_operations pata_at91_port_ops = {
        .cable_detect   = ata_cable_40wire,
 };
 
-static int __devinit pata_at91_probe(struct platform_device *pdev)
+static int pata_at91_probe(struct platform_device *pdev)
 {
        struct at91_cf_data *board = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
@@ -420,7 +420,7 @@ err_put:
        return ret;
 }
 
-static int __devexit pata_at91_remove(struct platform_device *pdev)
+static int pata_at91_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
        struct at91_ide_info *info;
@@ -441,7 +441,7 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
 
 static struct platform_driver pata_at91_driver = {
        .probe          = pata_at91_probe,
-       .remove         = __devexit_p(pata_at91_remove),
+       .remove         = pata_at91_remove,
        .driver         = {
                .name           = DRV_NAME,
                .owner          = THIS_MODULE,
index 1e65842e2ca719a0916bc371c676e68f27c096e2..8d43510c6becbb14a2e66ae54b92200c568af96a 100644 (file)
@@ -1538,7 +1538,7 @@ static unsigned short atapi_io_port[] = {
  *             - IRQ      (IORESOURCE_IRQ)
  *
  */
-static int __devinit bfin_atapi_probe(struct platform_device *pdev)
+static int bfin_atapi_probe(struct platform_device *pdev)
 {
        int board_idx = 0;
        struct resource *res;
@@ -1608,7 +1608,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
  *     A bfin atapi device has been unplugged. Perform the needed
  *     cleanup. Also called on module unload for any active devices.
  */
-static int __devexit bfin_atapi_remove(struct platform_device *pdev)
+static int bfin_atapi_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ata_host *host = dev_get_drvdata(dev);
@@ -1654,7 +1654,7 @@ static int bfin_atapi_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_atapi_driver = {
        .probe                  = bfin_atapi_probe,
-       .remove                 = __devexit_p(bfin_atapi_remove),
+       .remove                 = bfin_atapi_remove,
        .suspend                = bfin_atapi_suspend,
        .resume                 = bfin_atapi_resume,
        .driver = {
index de74d804f0312f770dba0e9287c721b734f775ce..bfcf377e8f77a81df2b32b5c8525be844e585b21 100644 (file)
@@ -115,7 +115,7 @@ static struct ata_port_operations cs5520_port_ops = {
        .set_piomode            = cs5520_set_piomode,
 };
 
-static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        static const unsigned int cmd_port[] = { 0x1F0, 0x170 };
        static const unsigned int ctl_port[] = { 0x3F6, 0x376 };
index 3982cef91f3c2da4c7b505c321bb081c98bf9e93..556222f04731ea7326afdaaac3a0ccedf3cc5e10 100644 (file)
@@ -910,7 +910,7 @@ static struct ata_port_operations ep93xx_pata_port_ops = {
        .port_start             = ep93xx_pata_port_start,
 };
 
-static int __devinit ep93xx_pata_probe(struct platform_device *pdev)
+static int ep93xx_pata_probe(struct platform_device *pdev)
 {
        struct ep93xx_pata_data *drv_data;
        struct ata_host *host;
@@ -1011,7 +1011,7 @@ err_rel_gpio:
        return err;
 }
 
-static int __devexit ep93xx_pata_remove(struct platform_device *pdev)
+static int ep93xx_pata_remove(struct platform_device *pdev)
 {
        struct ata_host *host = platform_get_drvdata(pdev);
        struct ep93xx_pata_data *drv_data = host->private_data;
@@ -1029,7 +1029,7 @@ static struct platform_driver ep93xx_pata_platform_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ep93xx_pata_probe,
-       .remove = __devexit_p(ep93xx_pata_remove),
+       .remove = ep93xx_pata_remove,
 };
 
 module_platform_driver(ep93xx_pata_platform_driver);
index 52e7e7b8c74f6cf960245ace818adc8053cbfff4..d7c732042a4fe74775d24d8625d8b7c8e10249b2 100644 (file)
@@ -337,10 +337,9 @@ static struct ata_port_operations pata_icside_port_ops = {
        .port_start             = ATA_OP_NULL,  /* don't need PRD table */
 };
 
-static void __devinit
-pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
-                        struct pata_icside_info *info,
-                        const struct portinfo *port)
+static void pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
+                                    struct pata_icside_info *info,
+                                    const struct portinfo *port)
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
        void __iomem *cmd = base + port->dataoffset;
@@ -368,7 +367,7 @@ pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
                ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);
 }
 
-static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
+static int pata_icside_register_v5(struct pata_icside_info *info)
 {
        struct pata_icside_state *state = info->state;
        void __iomem *base;
@@ -391,7 +390,7 @@ static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
        return 0;
 }
 
-static int __devinit pata_icside_register_v6(struct pata_icside_info *info)
+static int pata_icside_register_v6(struct pata_icside_info *info)
 {
        struct pata_icside_state *state = info->state;
        struct expansion_card *ec = info->ec;
@@ -434,7 +433,7 @@ static int __devinit pata_icside_register_v6(struct pata_icside_info *info)
        return icside_dma_init(info);
 }
 
-static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+static int pata_icside_add_ports(struct pata_icside_info *info)
 {
        struct expansion_card *ec = info->ec;
        struct ata_host *host;
@@ -474,8 +473,8 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
                                 &pata_icside_sht);
 }
 
-static int __devinit
-pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int pata_icside_probe(struct expansion_card *ec,
+                            const struct ecard_id *id)
 {
        struct pata_icside_state *state;
        struct pata_icside_info info;
@@ -575,7 +574,7 @@ static void pata_icside_shutdown(struct expansion_card *ec)
        }
 }
 
-static void __devexit pata_icside_remove(struct expansion_card *ec)
+static void pata_icside_remove(struct expansion_card *ec)
 {
        struct ata_host *host = ecard_get_drvdata(ec);
        struct pata_icside_state *state = host->private_data;
@@ -602,7 +601,7 @@ static const struct ecard_id pata_icside_ids[] = {
 
 static struct ecard_driver pata_icside_driver = {
        .probe          = pata_icside_probe,
-       .remove         = __devexit_p(pata_icside_remove),
+       .remove         = pata_icside_remove,
        .shutdown       = pata_icside_shutdown,
        .id_table       = pata_icside_ids,
        .drv = {
index 7d40b526ef118761194e0ea9a428432e9a1668d3..40849445a9dca0bedad6d2f4ad8edfa747676e00 100644 (file)
@@ -91,7 +91,7 @@ static void pata_imx_setup_port(struct ata_ioports *ioaddr)
        ioaddr->command_addr    = ioaddr->cmd_addr + (ATA_REG_CMD     << 2);
 }
 
-static int __devinit pata_imx_probe(struct platform_device *pdev)
+static int pata_imx_probe(struct platform_device *pdev)
 {
        struct ata_host *host;
        struct ata_port *ap;
@@ -167,7 +167,7 @@ free_priv:
        return -ENOMEM;
 }
 
-static int __devexit pata_imx_remove(struct platform_device *pdev)
+static int pata_imx_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
        struct pata_imx_priv *priv = host->private_data;
@@ -225,7 +225,7 @@ static const struct dev_pm_ops pata_imx_pm_ops = {
 
 static struct platform_driver pata_imx_driver = {
        .probe          = pata_imx_probe,
-       .remove         = __devexit_p(pata_imx_remove),
+       .remove         = pata_imx_remove,
        .driver = {
                .name           = DRV_NAME,
                .owner          = THIS_MODULE,
index 0566e67b5e125b744d1a34ff897aef4564175186..dcc6b243e525572ba4ac92576c3cb5e7d28863b9 100644 (file)
@@ -137,7 +137,7 @@ static void ixp4xx_setup_port(struct ata_port *ap,
        ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", raw_cmd, raw_ctl);
 }
 
-static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
+static int ixp4xx_pata_probe(struct platform_device *pdev)
 {
        unsigned int irq;
        struct resource *cs0, *cs1;
index b057e3fa44bcac0b39193335ab559e7bec314891..e5725edcf5159eabae5e6751972aeb0e7d46ed1b 100644 (file)
@@ -935,7 +935,7 @@ static struct ata_port_operations pata_macio_ops = {
        .sff_irq_clear          = pata_macio_irq_clear,
 };
 
-static void __devinit pata_macio_invariants(struct pata_macio_priv *priv)
+static void pata_macio_invariants(struct pata_macio_priv *priv)
 {
        const int *bidp;
 
@@ -976,9 +976,8 @@ static void __devinit pata_macio_invariants(struct pata_macio_priv *priv)
                priv->aapl_bus_id = 1;
 }
 
-static void __devinit pata_macio_setup_ios(struct ata_ioports *ioaddr,
-                                          void __iomem * base,
-                                          void __iomem * dma)
+static void pata_macio_setup_ios(struct ata_ioports *ioaddr,
+                                void __iomem * base, void __iomem * dma)
 {
        /* cmd_addr is the base of regs for that port */
        ioaddr->cmd_addr        = base;
@@ -999,8 +998,8 @@ static void __devinit pata_macio_setup_ios(struct ata_ioports *ioaddr,
        ioaddr->bmdma_addr      = dma;
 }
 
-static void __devinit pmac_macio_calc_timing_masks(struct pata_macio_priv *priv,
-                                                  struct ata_port_info   *pinfo)
+static void pmac_macio_calc_timing_masks(struct pata_macio_priv *priv,
+                                        struct ata_port_info *pinfo)
 {
        int i = 0;
 
@@ -1027,11 +1026,11 @@ static void __devinit pmac_macio_calc_timing_masks(struct pata_macio_priv *priv,
                pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask);
 }
 
-static int __devinit pata_macio_common_init(struct pata_macio_priv     *priv,
-                                           resource_size_t             tfregs,
-                                           resource_size_t             dmaregs,
-                                           resource_size_t             fcregs,
-                                           unsigned long               irq)
+static int pata_macio_common_init(struct pata_macio_priv *priv,
+                                 resource_size_t tfregs,
+                                 resource_size_t dmaregs,
+                                 resource_size_t fcregs,
+                                 unsigned long irq)
 {
        struct ata_port_info            pinfo;
        const struct ata_port_info      *ppi[] = { &pinfo, NULL };
@@ -1113,8 +1112,8 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv        *priv,
                                 &pata_macio_sht);
 }
 
-static int __devinit pata_macio_attach(struct macio_dev *mdev,
-                                      const struct of_device_id *match)
+static int pata_macio_attach(struct macio_dev *mdev,
+                            const struct of_device_id *match)
 {
        struct pata_macio_priv  *priv;
        resource_size_t         tfregs, dmaregs = 0;
@@ -1190,7 +1189,7 @@ static int __devinit pata_macio_attach(struct macio_dev *mdev,
        return rc;
 }
 
-static int __devexit pata_macio_detach(struct macio_dev *mdev)
+static int pata_macio_detach(struct macio_dev *mdev)
 {
        struct ata_host *host = macio_get_drvdata(mdev);
        struct pata_macio_priv *priv = host->private_data;
@@ -1257,8 +1256,8 @@ static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state)
 #endif /* CONFIG_PMAC_MEDIABAY */
 
 
-static int __devinit pata_macio_pci_attach(struct pci_dev *pdev,
-                                          const struct pci_device_id *id)
+static int pata_macio_pci_attach(struct pci_dev *pdev,
+                                const struct pci_device_id *id)
 {
        struct pata_macio_priv  *priv;
        struct device_node      *np;
@@ -1310,7 +1309,7 @@ static int __devinit pata_macio_pci_attach(struct pci_dev *pdev,
        return 0;
 }
 
-static void __devexit pata_macio_pci_detach(struct pci_dev *pdev)
+static void pata_macio_pci_detach(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
 
index ec67f54dc56f5ae4360f27330fe0fa19b0972fe2..652f57e8348466e51b476ec68c4c39ba9b5a5864 100644 (file)
@@ -621,9 +621,10 @@ static struct ata_port_operations mpc52xx_ata_port_ops = {
        .qc_prep                = ata_noop_qc_prep,
 };
 
-static int __devinit
-mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
-                    unsigned long raw_ata_regs, int mwdma_mask, int udma_mask)
+static int mpc52xx_ata_init_one(struct device *dev,
+                               struct mpc52xx_ata_priv *priv,
+                               unsigned long raw_ata_regs,
+                               int mwdma_mask, int udma_mask)
 {
        struct ata_host *host;
        struct ata_port *ap;
@@ -667,8 +668,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
 /* OF Platform driver                                                       */
 /* ======================================================================== */
 
-static int __devinit
-mpc52xx_ata_probe(struct platform_device *op)
+static int mpc52xx_ata_probe(struct platform_device *op)
 {
        unsigned int ipb_freq;
        struct resource res_mem;
index 4e1194b4c27128a9c6cb0671552ffaba4f97c681..ff2e57f3b5972521377199814a2e4f0a0aaa0ae2 100644 (file)
@@ -840,7 +840,7 @@ static struct ata_port_operations octeon_cf_ops = {
        .dev_config             = octeon_cf_dev_config,
 };
 
-static int __devinit octeon_cf_probe(struct platform_device *pdev)
+static int octeon_cf_probe(struct platform_device *pdev)
 {
        struct resource *res_cs0, *res_cs1;
 
index e5b234c370fa8d3482cc748409ea863b6561a2f5..a7e95a54c7827582c5a47344cb3dcc313e53ce22 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/ata_platform.h>
 #include <linux/libata.h>
 
-static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
+static int pata_of_platform_probe(struct platform_device *ofdev)
 {
        int ret;
        struct device_node *dn = ofdev->dev.of_node;
index f9f79fc04a8fc67001f69ff27d43790ddc0ecb8d..df2bb7504fc8e073650c271dd147d4d75cbf26a5 100644 (file)
@@ -48,7 +48,7 @@ static struct ata_port_operations palmld_port_ops = {
        .cable_detect           = ata_cable_40wire,
 };
 
-static __devinit int palmld_pata_probe(struct platform_device *pdev)
+static int palmld_pata_probe(struct platform_device *pdev)
 {
        struct ata_host *host;
        struct ata_port *ap;
@@ -109,7 +109,7 @@ err1:
        return ret;
 }
 
-static __devexit int palmld_pata_remove(struct platform_device *dev)
+static int palmld_pata_remove(struct platform_device *dev)
 {
        ata_platform_remove_one(dev);
 
@@ -127,7 +127,7 @@ static struct platform_driver palmld_pata_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = palmld_pata_probe,
-       .remove         = __devexit_p(palmld_pata_remove),
+       .remove         = palmld_pata_remove,
 };
 
 module_platform_driver(palmld_pata_platform_driver);
index c9399c8688c5c62555137d2db5a6ba060e2240c4..3f94a886bb35cb90d833021d41237ccd08002e94 100644 (file)
@@ -700,7 +700,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
  * @pdev: instance of pci_dev found
  * @ent:  matching entry in the id_tbl[]
  */
-static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int pdc2027x_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 };
        static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 };
index f4372d0c7ce603c2db18374cf22cc82cec66a4a2..71e093767f4e400e66ea8defe5b7d0ff0c2d0ff7 100644 (file)
@@ -98,12 +98,9 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
  *
  *     If no IRQ resource is present, PIO polling mode is used instead.
  */
-int __devinit __pata_platform_probe(struct device *dev,
-                                   struct resource *io_res,
-                                   struct resource *ctl_res,
-                                   struct resource *irq_res,
-                                   unsigned int ioport_shift,
-                                   int __pio_mask)
+int __pata_platform_probe(struct device *dev, struct resource *io_res,
+                         struct resource *ctl_res, struct resource *irq_res,
+                         unsigned int ioport_shift, int __pio_mask)
 {
        struct ata_host *host;
        struct ata_port *ap;
@@ -178,7 +175,7 @@ int __devinit __pata_platform_probe(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__pata_platform_probe);
 
-static int __devinit pata_platform_probe(struct platform_device *pdev)
+static int pata_platform_probe(struct platform_device *pdev)
 {
        struct resource *io_res;
        struct resource *ctl_res;
index 4b8ba559fe24cff43808ac586a3d87f18a226f7b..b0ac9e0c5e01e647d205e6597f33614098d66a42 100644 (file)
@@ -229,7 +229,7 @@ static void pxa_ata_dma_irq(int dma, void *port)
                complete(&pd->dma_done);
 }
 
-static int __devinit pxa_ata_probe(struct platform_device *pdev)
+static int pxa_ata_probe(struct platform_device *pdev)
 {
        struct ata_host *host;
        struct ata_port *ap;
@@ -369,7 +369,7 @@ static int __devinit pxa_ata_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit pxa_ata_remove(struct platform_device *pdev)
+static int pxa_ata_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
        struct pata_pxa_data *data = host->ports[0]->private_data;
@@ -383,7 +383,7 @@ static int __devexit pxa_ata_remove(struct platform_device *pdev)
 
 static struct platform_driver pxa_ata_driver = {
        .probe          = pxa_ata_probe,
-       .remove         = __devexit_p(pxa_ata_remove),
+       .remove         = pxa_ata_remove,
        .driver         = {
                .name           = DRV_NAME,
                .owner          = THIS_MODULE,
index 9417101bd5ca4524eb4aefdd797e4f41fc6840ae..3c5eb8fa6bd1f6e3538979e8b588f72dfda4cd72 100644 (file)
@@ -102,7 +102,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah)
        ap->ioaddr.error_addr   = info->iobase + RB500_CF_REG_ERR;
 }
 
-static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
+static int rb532_pata_driver_probe(struct platform_device *pdev)
 {
        int irq;
        int gpio;
@@ -177,7 +177,7 @@ err_free_gpio:
        return ret;
 }
 
-static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
+static int rb532_pata_driver_remove(struct platform_device *pdev)
 {
        struct ata_host *ah = platform_get_drvdata(pdev);
        struct rb532_cf_info *info = ah->private_data;
@@ -190,7 +190,7 @@ static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
 
 static struct platform_driver rb532_pata_platform_driver = {
        .probe          = rb532_pata_driver_probe,
-       .remove         = __devexit_p(rb532_pata_driver_remove),
+       .remove         = rb532_pata_driver_remove,
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index e71f998dd90ddfe4c9101996a5e59011e0a8a1bc..6a8665574fee5ad0e20e2f2423c76e32d8fca6a9 100644 (file)
@@ -321,8 +321,7 @@ static struct scsi_host_template rdc_sht = {
  *     Zero on success, or -ERRNO value.
  */
 
-static int __devinit rdc_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int rdc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct device *dev = &pdev->dev;
        struct ata_port_info port_info[2];
index db0d18cf1c2a3f00191a94fda39b75205b378eef..d3830c45a369cd611ba99ff78bac235c5fc4e258 100644 (file)
@@ -169,8 +169,7 @@ static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  *     Zero on success, or -ERRNO value.
  */
 
-static int __devinit sch_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int sch_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
 
index 5cfdf94823d07494116b0c3e3f02289156768973..64c5f0d0f81279cad0fb8226b85da5dfdeafe08f 100644 (file)
@@ -323,8 +323,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
        return tmpbyte & 0x30;
 }
 
-static int __devinit sil680_init_one(struct pci_dev *pdev,
-                                    const struct pci_device_id *id)
+static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        static const struct ata_port_info info = {
                .flags = ATA_FLAG_SLAVE_POSS,
index dc7d78eecb19ce6dd3631e8fcc0393804da359eb..5dba77ccaa0b9e89badebcad04b2525c7d5e9add 100644 (file)
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
-static int __devinit ahci_highbank_probe(struct platform_device *pdev)
+static int ahci_highbank_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
index 68f4fb54d627f43ba24a758e5ed216668e65eb1e..35c6b6d09c277526d93461388b6971069c644341 100644 (file)
@@ -4148,7 +4148,7 @@ err:
  *      A platform bus SATA device has been unplugged. Perform the needed
  *      cleanup. Also called on module unload for any active devices.
  */
-static int __devexit mv_platform_remove(struct platform_device *pdev)
+static int mv_platform_remove(struct platform_device *pdev)
 {
        struct ata_host *host = platform_get_drvdata(pdev);
 #if defined(CONFIG_HAVE_CLK)
@@ -4215,7 +4215,7 @@ static int mv_platform_resume(struct platform_device *pdev)
 #endif
 
 #ifdef CONFIG_OF
-static struct of_device_id mv_sata_dt_ids[] __devinitdata = {
+static struct of_device_id mv_sata_dt_ids[] = {
        { .compatible = "marvell,orion-sata", },
        {},
 };
@@ -4224,7 +4224,7 @@ MODULE_DEVICE_TABLE(of, mv_sata_dt_ids);
 
 static struct platform_driver mv_platform_driver = {
        .probe          = mv_platform_probe,
-       .remove         = __devexit_p(mv_platform_remove),
+       .remove         = mv_platform_remove,
        .suspend        = mv_platform_suspend,
        .resume         = mv_platform_resume,
        .driver         = {
@@ -4429,7 +4429,7 @@ static int mv_pci_device_resume(struct pci_dev *pdev)
 #endif
 
 static int mv_platform_probe(struct platform_device *pdev);
-static int __devexit mv_platform_remove(struct platform_device *pdev);
+static int mv_platform_remove(struct platform_device *pdev);
 
 static int __init mv_init(void)
 {
index e8cf88ba145d40c96230e8ac77da01e0af9e0713..44f304b3de63c6ee45fa87f88793e900359ac1be 100644 (file)
@@ -312,8 +312,7 @@ static struct ata_port_operations vsc_sata_ops = {
        .scr_write              = vsc_sata_scr_write,
 };
 
-static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
-                                         void __iomem *base)
+static void vsc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
 {
        port->cmd_addr          = base + VSC_SATA_TF_CMD_OFFSET;
        port->data_addr         = base + VSC_SATA_TF_DATA_OFFSET;
@@ -335,8 +334,8 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
 }
 
 
-static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int vsc_sata_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        static const struct ata_port_info pi = {
                .flags          = ATA_FLAG_SATA,
index ff7bb8a42ed62b042bff5f786b94775f8bfb87bc..77a7480dc4d1bc23881c0b6d4a1e469833576424 100644 (file)
@@ -1507,9 +1507,9 @@ static void do_housekeeping (unsigned long arg) {
 
 /********** creation of communication queues **********/
 
-static int __devinit create_queues (amb_dev * dev, unsigned int cmds,
-                                unsigned int txs, unsigned int * rxs,
-                                unsigned int * rx_buffer_sizes) {
+static int create_queues(amb_dev *dev, unsigned int cmds, unsigned int txs,
+                        unsigned int *rxs, unsigned int *rx_buffer_sizes)
+{
   unsigned char pool;
   size_t total = 0;
   void * memory;
@@ -1737,8 +1737,9 @@ static  int decode_loader_result (loader_command cmd, u32 result)
        return res;
 }
 
-static int __devinit do_loader_command (volatile loader_block * lb,
-                                    const amb_dev * dev, loader_command cmd) {
+static int do_loader_command(volatile loader_block *lb, const amb_dev *dev,
+                            loader_command cmd)
+{
   
   unsigned long timeout;
   
@@ -1793,8 +1794,9 @@ static int __devinit do_loader_command (volatile loader_block * lb,
 
 /* loader: determine loader version */
 
-static int __devinit get_loader_version (loader_block * lb,
-                                     const amb_dev * dev, u32 * version) {
+static int get_loader_version(loader_block *lb, const amb_dev *dev,
+                             u32 *version)
+{
   int res;
   
   PRINTD (DBG_FLOW|DBG_LOAD, "get_loader_version");
@@ -1809,9 +1811,9 @@ static int __devinit get_loader_version (loader_block * lb,
 
 /* loader: write memory data blocks */
 
-static int __devinit loader_write (loader_block* lb,
-                                  const amb_dev *dev,
-                                  const struct ihex_binrec *rec) {
+static int loader_write(loader_block *lb, const amb_dev *dev,
+                       const struct ihex_binrec *rec)
+{
   transfer_block * tb = &lb->payload.transfer;
   
   PRINTD (DBG_FLOW|DBG_LOAD, "loader_write");
@@ -1824,9 +1826,9 @@ static int __devinit loader_write (loader_block* lb,
 
 /* loader: verify memory data blocks */
 
-static int __devinit loader_verify (loader_block * lb,
-                                   const amb_dev *dev,
-                                   const struct ihex_binrec *rec) {
+static int loader_verify(loader_block *lb, const amb_dev *dev,
+                        const struct ihex_binrec *rec)
+{
   transfer_block * tb = &lb->payload.transfer;
   int res;
   
@@ -1842,8 +1844,8 @@ static int __devinit loader_verify (loader_block * lb,
 
 /* loader: start microcode */
 
-static int __devinit loader_start (loader_block * lb,
-                               const amb_dev * dev, u32 address) {
+static int loader_start(loader_block *lb, const amb_dev *dev, u32 address)
+{
   PRINTD (DBG_FLOW|DBG_LOAD, "loader_start");
   
   lb->payload.start = cpu_to_be32 (address);
@@ -1918,7 +1920,8 @@ static int amb_reset (amb_dev * dev, int diags) {
 
 /********** transfer and start the microcode **********/
 
-static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
+static int ucode_init(loader_block *lb, amb_dev *dev)
+{
   const struct firmware *fw;
   unsigned long start_address;
   const struct ihex_binrec *rec;
@@ -1980,7 +1983,8 @@ static inline __be32 bus_addr(void * addr) {
     return cpu_to_be32 (virt_to_bus (addr));
 }
 
-static int __devinit amb_talk (amb_dev * dev) {
+static int amb_talk(amb_dev *dev)
+{
   adap_talk_block a;
   unsigned char pool;
   unsigned long timeout;
@@ -2027,7 +2031,8 @@ static int __devinit amb_talk (amb_dev * dev) {
 }
 
 // get microcode version
-static void __devinit amb_ucode_version (amb_dev * dev) {
+static void amb_ucode_version(amb_dev *dev)
+{
   u32 major;
   u32 minor;
   command cmd;
@@ -2042,7 +2047,8 @@ static void __devinit amb_ucode_version (amb_dev * dev) {
 }
   
 // get end station address
-static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
+static void amb_esi(amb_dev *dev, u8 *esi)
+{
   u32 lower4;
   u16 upper2;
   command cmd;
@@ -2088,7 +2094,7 @@ static void fixup_plx_window (amb_dev *dev, loader_block *lb)
        return;
 }
 
-static int __devinit amb_init (amb_dev * dev)
+static int amb_init(amb_dev *dev)
 {
   loader_block lb;
   
@@ -2184,7 +2190,8 @@ static void setup_pci_dev(struct pci_dev *pci_dev)
        }
 }
 
-static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+static int amb_probe(struct pci_dev *pci_dev,
+                    const struct pci_device_id *pci_ent)
 {
        amb_dev * dev;
        int err;
@@ -2285,7 +2292,7 @@ out_disable:
 }
 
 
-static void __devexit amb_remove_one(struct pci_dev *pci_dev)
+static void amb_remove_one(struct pci_dev *pci_dev)
 {
        struct amb_dev *dev;
 
@@ -2379,7 +2386,7 @@ MODULE_DEVICE_TABLE(pci, amb_pci_tbl);
 static struct pci_driver amb_driver = {
        .name =         "amb",
        .probe =        amb_probe,
-       .remove =       __devexit_p(amb_remove_one),
+       .remove =       amb_remove_one,
        .id_table =     amb_pci_tbl,
 };
 
index 81e44f7b0ab6669b4e88bc28cac5402f2856452f..c1eb6fa8ac35b0e05125b0f5955d30a6f39d9ef7 100644 (file)
@@ -1567,7 +1567,7 @@ tx_complete++;
 /*--------------------------------- entries ---------------------------------*/
 
 
-static char * const media_name[] __devinitconst = {
+static char * const media_name[] = {
     "MMF", "SMF", "MMF", "03?", /*  0- 3 */
     "UTP", "05?", "06?", "07?", /*  4- 7 */
     "TAXI","09?", "10?", "11?", /*  8-11 */
@@ -1591,7 +1591,7 @@ static char * const media_name[] __devinitconst = {
   } })
 
 
-static int __devinit get_esi_asic(struct atm_dev *dev)
+static int get_esi_asic(struct atm_dev *dev)
 {
        struct eni_dev *eni_dev;
        unsigned char tonga;
@@ -1683,7 +1683,7 @@ static int __devinit get_esi_asic(struct atm_dev *dev)
 #undef GET_SEPROM
 
 
-static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
+static int get_esi_fpga(struct atm_dev *dev, void __iomem *base)
 {
        void __iomem *mac_base;
        int i;
@@ -1694,7 +1694,7 @@ static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
 }
 
 
-static int __devinit eni_do_init(struct atm_dev *dev)
+static int eni_do_init(struct atm_dev *dev)
 {
        struct midway_eprom __iomem *eprom;
        struct eni_dev *eni_dev;
@@ -1797,7 +1797,7 @@ static void eni_do_release(struct atm_dev *dev)
        iounmap(ed->ioaddr);
 }
 
-static int __devinit eni_start(struct atm_dev *dev)
+static int eni_start(struct atm_dev *dev)
 {
        struct eni_dev *eni_dev;
        
@@ -2226,8 +2226,8 @@ static const struct atmdev_ops ops = {
 };
 
 
-static int __devinit eni_init_one(struct pci_dev *pci_dev,
-                                 const struct pci_device_id *ent)
+static int eni_init_one(struct pci_dev *pci_dev,
+                       const struct pci_device_id *ent)
 {
        struct atm_dev *dev;
        struct eni_dev *eni_dev;
@@ -2292,7 +2292,7 @@ static struct pci_device_id eni_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
 
 
-static void __devexit eni_remove_one(struct pci_dev *pdev)
+static void eni_remove_one(struct pci_dev *pdev)
 {
        struct atm_dev *dev = pci_get_drvdata(pdev);
        struct eni_dev *ed = ENI_DEV(dev);
@@ -2310,7 +2310,7 @@ static struct pci_driver eni_driver = {
        .name           = DEV_LABEL,
        .id_table       = eni_pci_tbl,
        .probe          = eni_init_one,
-       .remove         = __devexit_p(eni_remove_one),
+       .remove         = eni_remove_one,
 };
 
 
index 86fed1b916957623130923714ce877c69543af37..b41c9481b67b94bf8331c9401b18123eb47ffaef 100644 (file)
@@ -252,7 +252,7 @@ struct reginit_item {
 };
 
 
-static struct reginit_item PHY_NTC_INIT[] __devinitdata = {
+static struct reginit_item PHY_NTC_INIT[] = {
        { PHY_CLEARALL, 0x40 }, 
        { 0x12,  0x0001 },
        { 0x13,  0x7605 },
@@ -1295,7 +1295,7 @@ static const struct atmdev_ops ops = {
 };
 
 
-static void __devinit undocumented_pci_fix (struct pci_dev *pdev)
+static void undocumented_pci_fix(struct pci_dev *pdev)
 {
        u32 tint;
 
@@ -1319,13 +1319,13 @@ static void __devinit undocumented_pci_fix (struct pci_dev *pdev)
  *                              PHY routines                              *
  **************************************************************************/
 
-static void __devinit write_phy (struct fs_dev *dev, int regnum, int val)
+static void write_phy(struct fs_dev *dev, int regnum, int val)
 {
        submit_command (dev,  &dev->hp_txq, QE_CMD_PRP_WR | QE_CMD_IMM_INQ,
                        regnum, val, 0);
 }
 
-static int __devinit init_phy (struct fs_dev *dev, struct reginit_item *reginit)
+static int init_phy(struct fs_dev *dev, struct reginit_item *reginit)
 {
        int i;
 
@@ -1381,7 +1381,7 @@ static void reset_chip (struct fs_dev *dev)
        }
 }
 
-static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment)
+static void *aligned_kmalloc(int size, gfp_t flags, int alignment)
 {
        void  *t;
 
@@ -1398,8 +1398,8 @@ static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment)
        return NULL;
 }
 
-static int __devinit init_q (struct fs_dev *dev, 
-                         struct queue *txq, int queue, int nentries, int is_rq)
+static int init_q(struct fs_dev *dev, struct queue *txq, int queue,
+                 int nentries, int is_rq)
 {
        int sz = nentries * sizeof (struct FS_QENTRY);
        struct FS_QENTRY *p;
@@ -1434,8 +1434,8 @@ static int __devinit init_q (struct fs_dev *dev,
 }
 
 
-static int __devinit init_fp (struct fs_dev *dev, 
-                          struct freepool *fp, int queue, int bufsize, int nr_buffers)
+static int init_fp(struct fs_dev *dev, struct freepool *fp, int queue,
+                  int bufsize, int nr_buffers)
 {
        func_enter ();
 
@@ -1528,7 +1528,7 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
        fs_dprintk (FS_DEBUG_QUEUE, "Added %d entries. \n", n);
 }
 
-static void __devexit free_queue (struct fs_dev *dev, struct queue *txq)
+static void free_queue(struct fs_dev *dev, struct queue *txq)
 {
        func_enter ();
 
@@ -1544,7 +1544,7 @@ static void __devexit free_queue (struct fs_dev *dev, struct queue *txq)
        func_exit ();
 }
 
-static void __devexit free_freepool (struct fs_dev *dev, struct freepool *fp)
+static void free_freepool(struct fs_dev *dev, struct freepool *fp)
 {
        func_enter ();
 
@@ -1662,7 +1662,7 @@ static void fs_poll (unsigned long data)
 }
 #endif
 
-static int __devinit fs_init (struct fs_dev *dev)
+static int fs_init(struct fs_dev *dev)
 {
        struct pci_dev  *pci_dev;
        int isr, to;
@@ -1897,8 +1897,8 @@ unmap:
        return 1;
 }
 
-static int __devinit firestream_init_one (struct pci_dev *pci_dev,
-                                      const struct pci_device_id *ent) 
+static int firestream_init_one(struct pci_dev *pci_dev,
+                              const struct pci_device_id *ent)
 {
        struct atm_dev *atm_dev;
        struct fs_dev *fs_dev;
@@ -1934,7 +1934,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev,
        return -ENODEV;
 }
 
-static void __devexit firestream_remove_one (struct pci_dev *pdev)
+static void firestream_remove_one(struct pci_dev *pdev)
 {
        int i;
        struct fs_dev *dev, *nxtdev;
@@ -2038,7 +2038,7 @@ static struct pci_driver firestream_driver = {
        .name           = "firestream",
        .id_table       = firestream_pci_tbl,
        .probe          = firestream_init_one,
-       .remove         = __devexit_p(firestream_remove_one),
+       .remove         = firestream_remove_one,
 };
 
 static int __init firestream_init_module (void)
index 361f5aee3be12fec5afd8796eaa784b6d3291b89..204814e88e464480248a6ddef6fe292d095514ad 100644 (file)
@@ -527,8 +527,7 @@ fore200e_pca_reset(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_pca_map(struct fore200e* fore200e)
+static int fore200e_pca_map(struct fore200e* fore200e)
 {
     DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
 
@@ -561,8 +560,7 @@ fore200e_pca_unmap(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_pca_configure(struct fore200e* fore200e)
+static int fore200e_pca_configure(struct fore200e *fore200e)
 {
     struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
     u8              master_ctrl, latency;
@@ -2028,8 +2026,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
 }
     
 
-static int __devinit
-fore200e_irq_request(struct fore200e* fore200e)
+static int fore200e_irq_request(struct fore200e *fore200e)
 {
     if (request_irq(fore200e->irq, fore200e_interrupt, IRQF_SHARED, fore200e->name, fore200e->atm_dev) < 0) {
 
@@ -2051,8 +2048,7 @@ fore200e_irq_request(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_get_esi(struct fore200e* fore200e)
+static int fore200e_get_esi(struct fore200e *fore200e)
 {
     struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
     int ok, i;
@@ -2081,8 +2077,7 @@ fore200e_get_esi(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_alloc_rx_buf(struct fore200e* fore200e)
+static int fore200e_alloc_rx_buf(struct fore200e *fore200e)
 {
     int scheme, magn, nbr, size, i;
 
@@ -2146,8 +2141,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_init_bs_queue(struct fore200e* fore200e)
+static int fore200e_init_bs_queue(struct fore200e *fore200e)
 {
     int scheme, magn, i;
 
@@ -2209,8 +2203,7 @@ fore200e_init_bs_queue(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_init_rx_queue(struct fore200e* fore200e)
+static int fore200e_init_rx_queue(struct fore200e *fore200e)
 {
     struct host_rxq*     rxq =  &fore200e->host_rxq;
     struct cp_rxq_entry __iomem * cp_entry;
@@ -2269,8 +2262,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_init_tx_queue(struct fore200e* fore200e)
+static int fore200e_init_tx_queue(struct fore200e *fore200e)
 {
     struct host_txq*     txq =  &fore200e->host_txq;
     struct cp_txq_entry __iomem * cp_entry;
@@ -2332,8 +2324,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e)
 }
 
 
-static int __devinit
-fore200e_init_cmd_queue(struct fore200e* fore200e)
+static int fore200e_init_cmd_queue(struct fore200e *fore200e)
 {
     struct host_cmdq*     cmdq =  &fore200e->host_cmdq;
     struct cp_cmdq_entry __iomem * cp_entry;
@@ -2374,10 +2365,10 @@ fore200e_init_cmd_queue(struct fore200e* fore200e)
 }
 
 
-static void __devinit
-fore200e_param_bs_queue(struct fore200e* fore200e,
-                       enum buffer_scheme scheme, enum buffer_magn magn,
-                       int queue_length, int pool_size, int supply_blksize)
+static void fore200e_param_bs_queue(struct fore200e *fore200e,
+                                   enum buffer_scheme scheme,
+                                   enum buffer_magn magn, int queue_length,
+                                   int pool_size, int supply_blksize)
 {
     struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ];
 
@@ -2388,8 +2379,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e,
 }
 
 
-static int __devinit
-fore200e_initialize(struct fore200e* fore200e)
+static int fore200e_initialize(struct fore200e *fore200e)
 {
     struct cp_queues __iomem * cpq;
     int               ok, scheme, magn;
@@ -2440,8 +2430,7 @@ fore200e_initialize(struct fore200e* fore200e)
 }
 
 
-static void __devinit
-fore200e_monitor_putc(struct fore200e* fore200e, char c)
+static void fore200e_monitor_putc(struct fore200e *fore200e, char c)
 {
     struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
 
@@ -2452,8 +2441,7 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c)
 }
 
 
-static int __devinit
-fore200e_monitor_getc(struct fore200e* fore200e)
+static int fore200e_monitor_getc(struct fore200e *fore200e)
 {
     struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
     unsigned long      timeout = jiffies + msecs_to_jiffies(50);
@@ -2477,8 +2465,7 @@ fore200e_monitor_getc(struct fore200e* fore200e)
 }
 
 
-static void __devinit
-fore200e_monitor_puts(struct fore200e* fore200e, char* str)
+static void fore200e_monitor_puts(struct fore200e *fore200e, char *str)
 {
     while (*str) {
 
@@ -2497,8 +2484,7 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str)
 #define FW_EXT "_ecd.bin2"
 #endif
 
-static int __devinit
-fore200e_load_and_start_fw(struct fore200e* fore200e)
+static int fore200e_load_and_start_fw(struct fore200e *fore200e)
 {
     const struct firmware *firmware;
     struct device *device;
@@ -2566,8 +2552,7 @@ release:
 }
 
 
-static int __devinit
-fore200e_register(struct fore200e* fore200e, struct device *parent)
+static int fore200e_register(struct fore200e *fore200e, struct device *parent)
 {
     struct atm_dev* atm_dev;
 
@@ -2593,8 +2578,7 @@ fore200e_register(struct fore200e* fore200e, struct device *parent)
 }
 
 
-static int __devinit
-fore200e_init(struct fore200e* fore200e, struct device *parent)
+static int fore200e_init(struct fore200e *fore200e, struct device *parent)
 {
     if (fore200e_register(fore200e, parent) < 0)
        return -ENODEV;
@@ -2644,7 +2628,7 @@ fore200e_init(struct fore200e* fore200e, struct device *parent)
 
 #ifdef CONFIG_SBUS
 static const struct of_device_id fore200e_sba_match[];
-static int __devinit fore200e_sba_probe(struct platform_device *op)
+static int fore200e_sba_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
        const struct fore200e_bus *bus;
@@ -2681,7 +2665,7 @@ static int __devinit fore200e_sba_probe(struct platform_device *op)
        return 0;
 }
 
-static int __devexit fore200e_sba_remove(struct platform_device *op)
+static int fore200e_sba_remove(struct platform_device *op)
 {
        struct fore200e *fore200e = dev_get_drvdata(&op->dev);
 
@@ -2707,13 +2691,13 @@ static struct platform_driver fore200e_sba_driver = {
                .of_match_table = fore200e_sba_match,
        },
        .probe          = fore200e_sba_probe,
-       .remove         = __devexit_p(fore200e_sba_remove),
+       .remove         = fore200e_sba_remove,
 };
 #endif
 
 #ifdef CONFIG_PCI
-static int __devinit
-fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+static int fore200e_pca_detect(struct pci_dev *pci_dev,
+                              const struct pci_device_id *pci_ent)
 {
     const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data;
     struct fore200e* fore200e;
@@ -2766,7 +2750,7 @@ out_disable:
 }
 
 
-static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
+static void fore200e_pca_remove_one(struct pci_dev *pci_dev)
 {
     struct fore200e *fore200e;
 
@@ -2789,7 +2773,7 @@ MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
 static struct pci_driver fore200e_pca_driver = {
     .name =     "fore_200e",
     .probe =    fore200e_pca_detect,
-    .remove =   __devexit_p(fore200e_pca_remove_one),
+    .remove =   fore200e_pca_remove_one,
     .id_table = fore200e_pca_tbl,
 };
 #endif
index b182c2f7d777c077806d79a261a600454a701438..72b6960fa95f6ea6ef33a17e24b0e53c3b752c4b 100644 (file)
@@ -349,8 +349,8 @@ __find_vcc(struct he_dev *he_dev, unsigned cid)
        return NULL;
 }
 
-static int __devinit
-he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+static int he_init_one(struct pci_dev *pci_dev,
+                      const struct pci_device_id *pci_ent)
 {
        struct atm_dev *atm_dev = NULL;
        struct he_dev *he_dev = NULL;
@@ -406,8 +406,7 @@ init_one_failure:
        return err;
 }
 
-static void __devexit
-he_remove_one (struct pci_dev *pci_dev)
+static void he_remove_one(struct pci_dev *pci_dev)
 {
        struct atm_dev *atm_dev;
        struct he_dev *he_dev;
@@ -445,8 +444,7 @@ rate_to_atmf(unsigned rate)         /* cps to atm forum format */
        return (NONZERO | (exp << 9) | (rate & 0x1ff));
 }
 
-static void __devinit
-he_init_rx_lbfp0(struct he_dev *he_dev)
+static void he_init_rx_lbfp0(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
@@ -476,8 +474,7 @@ he_init_rx_lbfp0(struct he_dev *he_dev)
        he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
 }
 
-static void __devinit
-he_init_rx_lbfp1(struct he_dev *he_dev)
+static void he_init_rx_lbfp1(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
@@ -507,8 +504,7 @@ he_init_rx_lbfp1(struct he_dev *he_dev)
        he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
 }
 
-static void __devinit
-he_init_tx_lbfp(struct he_dev *he_dev)
+static void he_init_tx_lbfp(struct he_dev *he_dev)
 {
        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
@@ -537,8 +533,7 @@ he_init_tx_lbfp(struct he_dev *he_dev)
        he_writel(he_dev, lbufd_index - 1, TLBF_T);
 }
 
-static int __devinit
-he_init_tpdrq(struct he_dev *he_dev)
+static int he_init_tpdrq(struct he_dev *he_dev)
 {
        he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
                CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
@@ -559,8 +554,7 @@ he_init_tpdrq(struct he_dev *he_dev)
        return 0;
 }
 
-static void __devinit
-he_init_cs_block(struct he_dev *he_dev)
+static void he_init_cs_block(struct he_dev *he_dev)
 {
        unsigned clock, rate, delta;
        int reg;
@@ -655,8 +649,7 @@ he_init_cs_block(struct he_dev *he_dev)
 
 }
 
-static int __devinit
-he_init_cs_block_rcm(struct he_dev *he_dev)
+static int he_init_cs_block_rcm(struct he_dev *he_dev)
 {
        unsigned (*rategrid)[16][16];
        unsigned rate, delta;
@@ -776,8 +769,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)
        return 0;
 }
 
-static int __devinit
-he_init_group(struct he_dev *he_dev, int group)
+static int he_init_group(struct he_dev *he_dev, int group)
 {
        struct he_buff *heb, *next;
        dma_addr_t mapping;
@@ -915,8 +907,7 @@ out_free_rbpl_table:
        return -ENOMEM;
 }
 
-static int __devinit
-he_init_irq(struct he_dev *he_dev)
+static int he_init_irq(struct he_dev *he_dev)
 {
        int i;
 
@@ -978,8 +969,7 @@ he_init_irq(struct he_dev *he_dev)
        return 0;
 }
 
-static int __devinit
-he_start(struct atm_dev *dev)
+static int he_start(struct atm_dev *dev)
 {
        struct he_dev *he_dev;
        struct pci_dev *pci_dev;
@@ -2879,7 +2869,7 @@ MODULE_DEVICE_TABLE(pci, he_pci_tbl);
 static struct pci_driver he_driver = {
        .name =         "he",
        .probe =        he_init_one,
-       .remove =       __devexit_p(he_remove_one),
+       .remove =       he_remove_one,
        .id_table =     he_pci_tbl,
 };
 
index 7d01c2a7525657f1da1654b4cf40ea04aec00b46..1dc0519333f291ab859b58739e762b2aa5ae5834 100644 (file)
@@ -1789,7 +1789,7 @@ static void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
        WRITE_IT_WAIT(dev, ctrl | SEEPROM_SK);
 }
 
-static u16 __devinit read_bia (const hrz_dev * dev, u16 addr)
+static u16 read_bia(const hrz_dev *dev, u16 addr)
 {
   u32 ctrl = rd_regl (dev, CONTROL_0_REG);
   
@@ -1845,7 +1845,8 @@ static u16 __devinit read_bia (const hrz_dev * dev, u16 addr)
 
 /********** initialise a card **********/
 
-static int __devinit hrz_init (hrz_dev * dev) {
+static int hrz_init(hrz_dev *dev)
+{
   int onefivefive;
   
   u16 chan;
@@ -2681,7 +2682,8 @@ static const struct atmdev_ops hrz_ops = {
   .owner       = THIS_MODULE,
 };
 
-static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+static int hrz_probe(struct pci_dev *pci_dev,
+                    const struct pci_device_id *pci_ent)
 {
        hrz_dev * dev;
        int err = 0;
@@ -2836,7 +2838,7 @@ out_disable:
        goto out;
 }
 
-static void __devexit hrz_remove_one(struct pci_dev *pci_dev)
+static void hrz_remove_one(struct pci_dev *pci_dev)
 {
        hrz_dev *dev;
 
@@ -2901,7 +2903,7 @@ MODULE_DEVICE_TABLE(pci, hrz_pci_tbl);
 static struct pci_driver hrz_driver = {
        .name =         "horizon",
        .probe =        hrz_probe,
-       .remove =       __devexit_p(hrz_remove_one),
+       .remove =       hrz_remove_one,
        .id_table =     hrz_pci_tbl,
 };
 
index 8974bd2b961e605b3b03c9c52e8dbedc897fb485..272f00927761b1e34e5676ad018e0f72ef623b8c 100644 (file)
@@ -3109,8 +3109,7 @@ deinit_card(struct idt77252_dev *card)
 }
 
 
-static void __devinit
-init_sram(struct idt77252_dev *card)
+static void init_sram(struct idt77252_dev *card)
 {
        int i;
 
@@ -3257,8 +3256,7 @@ init_sram(struct idt77252_dev *card)
        IPRINTK("%s: SRAM initialization complete.\n", card->name);
 }
 
-static int __devinit
-init_card(struct atm_dev *dev)
+static int init_card(struct atm_dev *dev)
 {
        struct idt77252_dev *card = dev->dev_data;
        struct pci_dev *pcidev = card->pcidev;
@@ -3537,8 +3535,7 @@ init_card(struct atm_dev *dev)
 /*****************************************************************************/
 
 
-static int __devinit
-idt77252_preset(struct idt77252_dev *card)
+static int idt77252_preset(struct idt77252_dev *card)
 {
        u16 pci_command;
 
@@ -3579,8 +3576,7 @@ idt77252_preset(struct idt77252_dev *card)
 }
 
 
-static unsigned long __devinit
-probe_sram(struct idt77252_dev *card)
+static unsigned long probe_sram(struct idt77252_dev *card)
 {
        u32 data, addr;
 
@@ -3601,8 +3597,8 @@ probe_sram(struct idt77252_dev *card)
        return addr * sizeof(u32);
 }
 
-static int __devinit
-idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
+static int idt77252_init_one(struct pci_dev *pcidev,
+                            const struct pci_device_id *id)
 {
        static struct idt77252_dev **last = &idt77252_chain;
        static int index = 0;
index 96cce6d5319592b20fbc8536c350d3cffdd841e8..4217f29a85e0473b9686e428cf11c75599b13b41 100644 (file)
@@ -2299,7 +2299,7 @@ static int reset_sar(struct atm_dev *dev)
 }  
          
          
-static int __devinit ia_init(struct atm_dev *dev)
+static int ia_init(struct atm_dev *dev)
 {  
        IADEV *iadev;  
        unsigned long real_base;
@@ -2492,7 +2492,7 @@ static void ia_free_rx(IADEV *iadev)
                          iadev->rx_dle_dma);  
 }
 
-static int __devinit ia_start(struct atm_dev *dev)
+static int ia_start(struct atm_dev *dev)
 {  
        IADEV *iadev;  
        int error;  
@@ -3168,8 +3168,7 @@ static const struct atmdev_ops ops = {
        .owner          = THIS_MODULE,
 };  
          
-static int __devinit ia_init_one(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int ia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {  
        struct atm_dev *dev;  
        IADEV *iadev;  
@@ -3229,7 +3228,7 @@ err_out:
        return ret;
 }
 
-static void __devexit ia_remove_one(struct pci_dev *pdev)
+static void ia_remove_one(struct pci_dev *pdev)
 {
        struct atm_dev *dev = pci_get_drvdata(pdev);
        IADEV *iadev = INPH_IA_DEV(dev);
@@ -3270,7 +3269,7 @@ static struct pci_driver ia_driver = {
        .name =         DEV_LABEL,
        .id_table =     ia_pci_tbl,
        .probe =        ia_init_one,
-       .remove =       __devexit_p(ia_remove_one),
+       .remove =       ia_remove_one,
 };
 
 static int __init ia_module_init(void)
index 6a0955e6d4fc92231e59d36e0849dd46c9e0e60b..53ecac5a2161d729fc957b8b4379a526ca89e0d3 100644 (file)
@@ -636,82 +636,82 @@ struct rx_buf_desc {
 #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE  
 #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE  
 
-typedef volatile u_int  freg_t;
+typedef volatile u_int ffreg_t;
 typedef u_int   rreg_t;
 
 typedef struct _ffredn_t {
-        freg_t  idlehead_high;  /* Idle cell header (high)              */
-        freg_t  idlehead_low;   /* Idle cell header (low)               */
-        freg_t  maxrate;        /* Maximum rate                         */
-        freg_t  stparms;        /* Traffic Management Parameters        */
-        freg_t  abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */
-        freg_t  rm_type;        /*                                      */
-        u_int   filler5[0x17 - 0x06];
-        freg_t  cmd_reg;        /* Command register                     */
-        u_int   filler18[0x20 - 0x18];
-        freg_t  cbr_base;       /* CBR Pointer Base                     */
-        freg_t  vbr_base;       /* VBR Pointer Base                     */
-        freg_t  abr_base;       /* ABR Pointer Base                     */
-        freg_t  ubr_base;       /* UBR Pointer Base                     */
-        u_int   filler24;
-        freg_t  vbrwq_base;     /* VBR Wait Queue Base                  */
-        freg_t  abrwq_base;     /* ABR Wait Queue Base                  */
-        freg_t  ubrwq_base;     /* UBR Wait Queue Base                  */
-        freg_t  vct_base;       /* Main VC Table Base                   */
-        freg_t  vcte_base;      /* Extended Main VC Table Base          */
-        u_int   filler2a[0x2C - 0x2A];
-        freg_t  cbr_tab_beg;    /* CBR Table Begin                      */
-        freg_t  cbr_tab_end;    /* CBR Table End                        */
-        freg_t  cbr_pointer;    /* CBR Pointer                          */
-        u_int   filler2f[0x30 - 0x2F];
-        freg_t  prq_st_adr;     /* Packet Ready Queue Start Address     */
-        freg_t  prq_ed_adr;     /* Packet Ready Queue End Address       */
-        freg_t  prq_rd_ptr;     /* Packet Ready Queue read pointer      */
-        freg_t  prq_wr_ptr;     /* Packet Ready Queue write pointer     */
-        freg_t  tcq_st_adr;     /* Transmit Complete Queue Start Address*/
-        freg_t  tcq_ed_adr;     /* Transmit Complete Queue End Address  */
-        freg_t  tcq_rd_ptr;     /* Transmit Complete Queue read pointer */
-        freg_t  tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/
-        u_int   filler38[0x40 - 0x38];
-        freg_t  queue_base;     /* Base address for PRQ and TCQ         */
-        freg_t  desc_base;      /* Base address of descriptor table     */
-        u_int   filler42[0x45 - 0x42];
-        freg_t  mode_reg_0;     /* Mode register 0                      */
-        freg_t  mode_reg_1;     /* Mode register 1                      */
-        freg_t  intr_status_reg;/* Interrupt Status register            */
-        freg_t  mask_reg;       /* Mask Register                        */
-        freg_t  cell_ctr_high1; /* Total cell transfer count (high)     */
-        freg_t  cell_ctr_lo1;   /* Total cell transfer count (low)      */
-        freg_t  state_reg;      /* Status register                      */
-        u_int   filler4c[0x58 - 0x4c];
-        freg_t  curr_desc_num;  /* Contains the current descriptor num  */
-        freg_t  next_desc;      /* Next descriptor                      */
-        freg_t  next_vc;        /* Next VC                              */
-        u_int   filler5b[0x5d - 0x5b];
-        freg_t  present_slot_cnt;/* Present slot count                  */
-        u_int   filler5e[0x6a - 0x5e];
-        freg_t  new_desc_num;   /* New descriptor number                */
-        freg_t  new_vc;         /* New VC                               */
-        freg_t  sched_tbl_ptr;  /* Schedule table pointer               */
-        freg_t  vbrwq_wptr;     /* VBR wait queue write pointer         */
-        freg_t  vbrwq_rptr;     /* VBR wait queue read pointer          */
-        freg_t  abrwq_wptr;     /* ABR wait queue write pointer         */
-        freg_t  abrwq_rptr;     /* ABR wait queue read pointer          */
-        freg_t  ubrwq_wptr;     /* UBR wait queue write pointer         */
-        freg_t  ubrwq_rptr;     /* UBR wait queue read pointer          */
-        freg_t  cbr_vc;         /* CBR VC                               */
-        freg_t  vbr_sb_vc;      /* VBR SB VC                            */
-        freg_t  abr_sb_vc;      /* ABR SB VC                            */
-        freg_t  ubr_sb_vc;      /* UBR SB VC                            */
-        freg_t  vbr_next_link;  /* VBR next link                        */
-        freg_t  abr_next_link;  /* ABR next link                        */
-        freg_t  ubr_next_link;  /* UBR next link                        */
-        u_int   filler7a[0x7c-0x7a];
-        freg_t  out_rate_head;  /* Out of rate head                     */
-        u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */
-        freg_t  cell_ctr_high1_nc;/* Total cell transfer count (high)   */
-        freg_t  cell_ctr_lo1_nc;/* Total cell transfer count (low)      */
-        u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */
+       ffreg_t idlehead_high;  /* Idle cell header (high)              */
+       ffreg_t idlehead_low;   /* Idle cell header (low)               */
+       ffreg_t maxrate;        /* Maximum rate                         */
+       ffreg_t stparms;        /* Traffic Management Parameters        */
+       ffreg_t abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */
+       ffreg_t rm_type;        /*                                      */
+       u_int   filler5[0x17 - 0x06];
+       ffreg_t cmd_reg;        /* Command register                     */
+       u_int   filler18[0x20 - 0x18];
+       ffreg_t cbr_base;       /* CBR Pointer Base                     */
+       ffreg_t vbr_base;       /* VBR Pointer Base                     */
+       ffreg_t abr_base;       /* ABR Pointer Base                     */
+       ffreg_t ubr_base;       /* UBR Pointer Base                     */
+       u_int   filler24;
+       ffreg_t vbrwq_base;     /* VBR Wait Queue Base                  */
+       ffreg_t abrwq_base;     /* ABR Wait Queue Base                  */
+       ffreg_t ubrwq_base;     /* UBR Wait Queue Base                  */
+       ffreg_t vct_base;       /* Main VC Table Base                   */
+       ffreg_t vcte_base;      /* Extended Main VC Table Base          */
+       u_int   filler2a[0x2C - 0x2A];
+       ffreg_t cbr_tab_beg;    /* CBR Table Begin                      */
+       ffreg_t cbr_tab_end;    /* CBR Table End                        */
+       ffreg_t cbr_pointer;    /* CBR Pointer                          */
+       u_int   filler2f[0x30 - 0x2F];
+       ffreg_t prq_st_adr;     /* Packet Ready Queue Start Address     */
+       ffreg_t prq_ed_adr;     /* Packet Ready Queue End Address       */
+       ffreg_t prq_rd_ptr;     /* Packet Ready Queue read pointer      */
+       ffreg_t prq_wr_ptr;     /* Packet Ready Queue write pointer     */
+       ffreg_t tcq_st_adr;     /* Transmit Complete Queue Start Address*/
+       ffreg_t tcq_ed_adr;     /* Transmit Complete Queue End Address  */
+       ffreg_t tcq_rd_ptr;     /* Transmit Complete Queue read pointer */
+       ffreg_t tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/
+       u_int   filler38[0x40 - 0x38];
+       ffreg_t queue_base;     /* Base address for PRQ and TCQ         */
+       ffreg_t desc_base;      /* Base address of descriptor table     */
+       u_int   filler42[0x45 - 0x42];
+       ffreg_t mode_reg_0;     /* Mode register 0                      */
+       ffreg_t mode_reg_1;     /* Mode register 1                      */
+       ffreg_t intr_status_reg;/* Interrupt Status register            */
+       ffreg_t mask_reg;       /* Mask Register                        */
+       ffreg_t cell_ctr_high1; /* Total cell transfer count (high)     */
+       ffreg_t cell_ctr_lo1;   /* Total cell transfer count (low)      */
+       ffreg_t state_reg;      /* Status register                      */
+       u_int   filler4c[0x58 - 0x4c];
+       ffreg_t curr_desc_num;  /* Contains the current descriptor num  */
+       ffreg_t next_desc;      /* Next descriptor                      */
+       ffreg_t next_vc;        /* Next VC                              */
+       u_int   filler5b[0x5d - 0x5b];
+       ffreg_t present_slot_cnt;/* Present slot count                  */
+       u_int   filler5e[0x6a - 0x5e];
+       ffreg_t new_desc_num;   /* New descriptor number                */
+       ffreg_t new_vc;         /* New VC                               */
+       ffreg_t sched_tbl_ptr;  /* Schedule table pointer               */
+       ffreg_t vbrwq_wptr;     /* VBR wait queue write pointer         */
+       ffreg_t vbrwq_rptr;     /* VBR wait queue read pointer          */
+       ffreg_t abrwq_wptr;     /* ABR wait queue write pointer         */
+       ffreg_t abrwq_rptr;     /* ABR wait queue read pointer          */
+       ffreg_t ubrwq_wptr;     /* UBR wait queue write pointer         */
+       ffreg_t ubrwq_rptr;     /* UBR wait queue read pointer          */
+       ffreg_t cbr_vc;         /* CBR VC                               */
+       ffreg_t vbr_sb_vc;      /* VBR SB VC                            */
+       ffreg_t abr_sb_vc;      /* ABR SB VC                            */
+       ffreg_t ubr_sb_vc;      /* UBR SB VC                            */
+       ffreg_t vbr_next_link;  /* VBR next link                        */
+       ffreg_t abr_next_link;  /* ABR next link                        */
+       ffreg_t ubr_next_link;  /* UBR next link                        */
+       u_int   filler7a[0x7c-0x7a];
+       ffreg_t out_rate_head;  /* Out of rate head                     */
+       u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */
+       ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high)   */
+       ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low)      */
+       u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */
 } ffredn_t;
 
 typedef struct _rfredn_t {
index 68c75887181203eb7a7cee93ca19964cd13c9c36..fa7d701933bab7cbfd0fa60c2e113de8c255a597 100644 (file)
@@ -551,8 +551,8 @@ static inline void sram_write(const struct lanai_dev *lanai,
        writel(val, sram_addr(lanai, offset));
 }
 
-static int __devinit sram_test_word(const struct lanai_dev *lanai,
-                                   int offset, u32 pattern)
+static int sram_test_word(const struct lanai_dev *lanai, int offset,
+                         u32 pattern)
 {
        u32 readback;
        sram_write(lanai, pattern, offset);
@@ -566,7 +566,7 @@ static int __devinit sram_test_word(const struct lanai_dev *lanai,
        return -EIO;
 }
 
-static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
+static int sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
 {
        int offset, result = 0;
        for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4)
@@ -574,7 +574,7 @@ static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
        return result;
 }
 
-static int __devinit sram_test_and_clear(const struct lanai_dev *lanai)
+static int sram_test_and_clear(const struct lanai_dev *lanai)
 {
 #ifdef FULL_MEMORY_TEST
        int result;
@@ -860,7 +860,7 @@ static inline void aal0_buffer_free(struct lanai_dev *lanai)
 #ifndef READ_EEPROM
 
 /* Stub functions to use if EEPROM reading is disabled */
-static int __devinit eeprom_read(struct lanai_dev *lanai)
+static int eeprom_read(struct lanai_dev *lanai)
 {
        printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n",
            lanai->number);
@@ -868,7 +868,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai)
        return 0;
 }
 
-static int __devinit eeprom_validate(struct lanai_dev *lanai)
+static int eeprom_validate(struct lanai_dev *lanai)
 {
        lanai->serialno = 0;
        lanai->magicno = EEPROM_MAGIC_VALUE;
@@ -877,7 +877,7 @@ static int __devinit eeprom_validate(struct lanai_dev *lanai)
 
 #else /* READ_EEPROM */
 
-static int __devinit eeprom_read(struct lanai_dev *lanai)
+static int eeprom_read(struct lanai_dev *lanai)
 {
        int i, address;
        u8 data;
@@ -953,7 +953,7 @@ static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address)
 }
 
 /* Checksum/validate EEPROM contents */
-static int __devinit eeprom_validate(struct lanai_dev *lanai)
+static int eeprom_validate(struct lanai_dev *lanai)
 {
        int i, s;
        u32 v;
@@ -1448,7 +1448,7 @@ static void vcc_rx_aal0(struct lanai_dev *lanai)
 #include <linux/vmalloc.h>
 #endif
 
-static int __devinit vcc_table_allocate(struct lanai_dev *lanai)
+static int vcc_table_allocate(struct lanai_dev *lanai)
 {
 #ifdef VCCTABLE_GETFREEPAGE
        APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE,
@@ -1588,7 +1588,7 @@ static void lanai_reset(struct lanai_dev *lanai)
 /*
  * Allocate service buffer and tell card about it
  */
-static int __devinit service_buffer_allocate(struct lanai_dev *lanai)
+static int service_buffer_allocate(struct lanai_dev *lanai)
 {
        lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8,
            lanai->pci);
@@ -1942,7 +1942,7 @@ static int check_board_id_and_rev(const char *name, u32 val, int *revp)
 
 /* -------------------- PCI INITIALIZATION/SHUTDOWN: */
 
-static int __devinit lanai_pci_start(struct lanai_dev *lanai)
+static int lanai_pci_start(struct lanai_dev *lanai)
 {
        struct pci_dev *pci = lanai->pci;
        int result;
@@ -2123,7 +2123,7 @@ static inline void lanai_cbr_shutdown(struct lanai_dev *lanai)
 /* -------------------- OPERATIONS: */
 
 /* setup a newly detected device */
-static int __devinit lanai_dev_open(struct atm_dev *atmdev)
+static int lanai_dev_open(struct atm_dev *atmdev)
 {
        struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
        unsigned long raw_base;
@@ -2566,8 +2566,8 @@ static const struct atmdev_ops ops = {
 };
 
 /* initialize one probed card */
-static int __devinit lanai_init_one(struct pci_dev *pci,
-                                   const struct pci_device_id *ident)
+static int lanai_init_one(struct pci_dev *pci,
+                         const struct pci_device_id *ident)
 {
        struct lanai_dev *lanai;
        struct atm_dev *atmdev;
index 1c70c45fa044837d1b3e872c7bafe9220d074aef..ed1d2b7f923b33334f4b07d288a63015071a3226 100644 (file)
 static u32 ns_read_sram(ns_dev * card, u32 sram_address);
 static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value,
                          int count);
-static int __devinit ns_init_card(int i, struct pci_dev *pcidev);
-static void __devinit ns_init_card_error(ns_dev * card, int error);
+static int ns_init_card(int i, struct pci_dev *pcidev);
+static void ns_init_card_error(ns_dev * card, int error);
 static scq_info *get_scq(ns_dev *card, int size, u32 scd);
 static void free_scq(ns_dev *card, scq_info * scq, struct atm_vcc *vcc);
 static void push_rxbufs(ns_dev *, struct sk_buff *);
@@ -180,8 +180,8 @@ MODULE_LICENSE("GPL");
 
 /* Functions */
 
-static int __devinit nicstar_init_one(struct pci_dev *pcidev,
-                                     const struct pci_device_id *ent)
+static int nicstar_init_one(struct pci_dev *pcidev,
+                           const struct pci_device_id *ent)
 {
        static int index = -1;
        unsigned int error;
@@ -200,7 +200,7 @@ err_out:
        return -ENODEV;
 }
 
-static void __devexit nicstar_remove_one(struct pci_dev *pcidev)
+static void nicstar_remove_one(struct pci_dev *pcidev)
 {
        int i, j;
        ns_dev *card = pci_get_drvdata(pcidev);
@@ -262,7 +262,7 @@ static void __devexit nicstar_remove_one(struct pci_dev *pcidev)
        kfree(card);
 }
 
-static struct pci_device_id nicstar_pci_tbl[] __devinitdata = {
+static struct pci_device_id nicstar_pci_tbl[] = {
        { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77201), 0 },
        {0,}                    /* terminate list */
 };
@@ -273,7 +273,7 @@ static struct pci_driver nicstar_driver = {
        .name = "nicstar",
        .id_table = nicstar_pci_tbl,
        .probe = nicstar_init_one,
-       .remove = __devexit_p(nicstar_remove_one),
+       .remove = nicstar_remove_one,
 };
 
 static int __init nicstar_init(void)
@@ -351,7 +351,7 @@ static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value,
        spin_unlock_irqrestore(&card->res_lock, flags);
 }
 
-static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
+static int ns_init_card(int i, struct pci_dev *pcidev)
 {
        int j;
        struct ns_dev *card = NULL;
@@ -821,7 +821,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
        return error;
 }
 
-static void __devinit ns_init_card_error(ns_dev * card, int error)
+static void ns_init_card_error(ns_dev *card, int error)
 {
        if (error >= 17) {
                writel(0x00000000, card->membase + CFG);
index d70abe77f737591c236e8b711aef14a4ca37826a..0474a89170b9cc0d969f4917dd889ae7a0a679bb 100644 (file)
@@ -538,7 +538,7 @@ static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr
        } else {
                count = -EINVAL;
        }
-       spin_lock_irq(&card->param_queue_lock);
+       spin_unlock_irq(&card->param_queue_lock);
        return count;
 }
 
@@ -1462,7 +1462,7 @@ static void fpga_remove(struct pci_dev *dev)
        kfree(card);
 }
 
-static struct pci_device_id fpga_pci_tbl[] __devinitdata = {
+static struct pci_device_id fpga_pci_tbl[] = {
        { 0x10ee, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { 0, }
 };
index abe4e20b07660bcec8fd9b1cac15878ae78c5f0e..969c3c29000c3622094068d940b854d251393673 100644 (file)
@@ -1094,8 +1094,8 @@ static irqreturn_t zatm_int(int irq,void *dev_id)
 /*----------------------------- (E)EPROM access -----------------------------*/
 
 
-static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
-    unsigned short cmd)
+static void eprom_set(struct zatm_dev *zatm_dev, unsigned long value,
+                     unsigned short cmd)
 {
        int error;
 
@@ -1105,8 +1105,7 @@ static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
 }
 
 
-static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev,
-    unsigned short cmd)
+static unsigned long eprom_get(struct zatm_dev *zatm_dev, unsigned short cmd)
 {
        unsigned int value;
        int error;
@@ -1118,8 +1117,8 @@ static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev,
 }
 
 
-static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev,
-    unsigned long data,int bits,unsigned short cmd)
+static void eprom_put_bits(struct zatm_dev *zatm_dev, unsigned long data,
+                          int bits, unsigned short cmd)
 {
        unsigned long value;
        int i;
@@ -1133,8 +1132,8 @@ static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev,
 }
 
 
-static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev,
-    unsigned char *byte,unsigned short cmd)
+static void eprom_get_byte(struct zatm_dev *zatm_dev, unsigned char *byte,
+                          unsigned short cmd)
 {
        int i;
 
@@ -1149,8 +1148,8 @@ static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev,
 }
 
 
-static unsigned char __devinit eprom_try_esi(struct atm_dev *dev,
-    unsigned short cmd,int offset,int swap)
+static unsigned char eprom_try_esi(struct atm_dev *dev, unsigned short cmd,
+                                  int offset, int swap)
 {
        unsigned char buf[ZEPROM_SIZE];
        struct zatm_dev *zatm_dev;
@@ -1170,7 +1169,7 @@ static unsigned char __devinit eprom_try_esi(struct atm_dev *dev,
 }
 
 
-static void __devinit eprom_get_esi(struct atm_dev *dev)
+static void eprom_get_esi(struct atm_dev *dev)
 {
        if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return;
        (void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0);
@@ -1180,7 +1179,7 @@ static void __devinit eprom_get_esi(struct atm_dev *dev)
 /*--------------------------------- entries ---------------------------------*/
 
 
-static int __devinit zatm_init(struct atm_dev *dev)
+static int zatm_init(struct atm_dev *dev)
 {
        struct zatm_dev *zatm_dev;
        struct pci_dev *pci_dev;
@@ -1257,7 +1256,7 @@ static int __devinit zatm_init(struct atm_dev *dev)
 }
 
 
-static int __devinit zatm_start(struct atm_dev *dev)
+static int zatm_start(struct atm_dev *dev)
 {
        struct zatm_dev *zatm_dev = ZATM_DEV(dev);
        struct pci_dev *pdev = zatm_dev->pci_dev;
@@ -1584,8 +1583,8 @@ static const struct atmdev_ops ops = {
        .change_qos     = zatm_change_qos,
 };
 
-static int __devinit zatm_init_one(struct pci_dev *pci_dev,
-                                  const struct pci_device_id *ent)
+static int zatm_init_one(struct pci_dev *pci_dev,
+                        const struct pci_device_id *ent)
 {
        struct atm_dev *dev;
        struct zatm_dev *zatm_dev;
@@ -1636,7 +1635,7 @@ out_free:
 
 MODULE_LICENSE("GPL");
 
-static struct pci_device_id zatm_pci_tbl[] __devinitdata = {
+static struct pci_device_id zatm_pci_tbl[] = {
        { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1221), ZATM_COPPER },
        { PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1225), 0 },
        { 0, }
index 5ad3bad2b0a53ecf0aa57d656f7aaf5a01752152..d585735430dd6c7eb763a8a3fe53dba6b0e858c3 100644 (file)
@@ -37,7 +37,7 @@
 
 #define CFAG12864BFB_NAME "cfag12864bfb"
 
-static struct fb_fix_screeninfo cfag12864bfb_fix __devinitdata = {
+static struct fb_fix_screeninfo cfag12864bfb_fix = {
        .id = "cfag12864b",
        .type = FB_TYPE_PACKED_PIXELS,
        .visual = FB_VISUAL_MONO10,
@@ -48,7 +48,7 @@ static struct fb_fix_screeninfo cfag12864bfb_fix __devinitdata = {
        .accel = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo cfag12864bfb_var __devinitdata = {
+static struct fb_var_screeninfo cfag12864bfb_var = {
        .xres = CFAG12864B_WIDTH,
        .yres = CFAG12864B_HEIGHT,
        .xres_virtual = CFAG12864B_WIDTH,
@@ -80,7 +80,7 @@ static struct fb_ops cfag12864bfb_ops = {
        .fb_mmap = cfag12864bfb_mmap,
 };
 
-static int __devinit cfag12864bfb_probe(struct platform_device *device)
+static int cfag12864bfb_probe(struct platform_device *device)
 {
        int ret = -EINVAL;
        struct fb_info *info = framebuffer_alloc(0, &device->dev);
@@ -114,7 +114,7 @@ none:
        return ret;
 }
 
-static int __devexit cfag12864bfb_remove(struct platform_device *device)
+static int cfag12864bfb_remove(struct platform_device *device)
 {
        struct fb_info *info = platform_get_drvdata(device);
 
@@ -128,7 +128,7 @@ static int __devexit cfag12864bfb_remove(struct platform_device *device)
 
 static struct platform_driver cfag12864bfb_driver = {
        .probe  = cfag12864bfb_probe,
-       .remove = __devexit_p(cfag12864bfb_remove),
+       .remove = cfag12864bfb_remove,
        .driver = {
                .name   = CFAG12864BFB_NAME,
        },
index 63452943abd1e2a509661f934d51be5431259b86..fb10728f63721565d282e2298f2bf14641fb8f1e 100644 (file)
@@ -224,7 +224,7 @@ static void cpu_device_release(struct device *dev)
         * by the cpu device.
         *
         * Never copy this way of doing things, or you too will be made fun of
-        * on the linux-kerenl list, you have been warned.
+        * on the linux-kernel list, you have been warned.
         */
 }
 
index 147d1a4dd2694eb05a5366cf0a47317eec729479..17cf7cad601e56840adefbd1b16a8d0cd5c8a5d8 100644 (file)
@@ -148,7 +148,7 @@ static int dev_mkdir(const char *name, umode_t mode)
        struct path path;
        int err;
 
-       dentry = kern_path_create(AT_FDCWD, name, &path, 1);
+       dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
index d81460309182fde4177865a922f740c278c7d40c..b392b353be39016818abd096da01fb4a18839450 100644 (file)
@@ -305,7 +305,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf
        char *buf;
 
        size = fw_file_size(file);
-       if (size < 0)
+       if (size <= 0)
                return false;
        buf = vmalloc(size);
        if (!buf)
index a3c1404c79338c3b7e82b7b71835971dc42ec358..2b7f77d3fcb0d518d2a1f4e041f29b61d6e4521b 100644 (file)
@@ -513,6 +513,8 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 
  Out:
        TRACE_RESUME(error);
+
+       pm_runtime_enable(dev);
        return error;
 }
 
@@ -589,8 +591,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        if (!dev->power.is_suspended)
                goto Unlock;
 
-       pm_runtime_enable(dev);
-
        if (dev->pm_domain) {
                info = "power domain ";
                callback = pm_op(&dev->pm_domain->ops, state);
@@ -930,6 +930,8 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
        pm_callback_t callback = NULL;
        char *info = NULL;
 
+       __pm_runtime_disable(dev, false);
+
        if (dev->power.syscore)
                return 0;
 
@@ -1133,11 +1135,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 
  Complete:
        complete_all(&dev->power.completion);
-
        if (error)
                async_error = error;
-       else if (dev->power.is_suspended)
-               __pm_runtime_disable(dev, false);
 
        return error;
 }
index ff46387f5308394d913d5789c16265253b56b5f0..d21349544ce5b8131b0ca217ec5618af7beca346 100644 (file)
@@ -542,19 +542,19 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
                                    struct dev_pm_qos_request *req, s32 value)
 {
        struct device *ancestor = dev->parent;
-       int error = -ENODEV;
+       int ret = -ENODEV;
 
        while (ancestor && !ancestor->power.ignore_children)
                ancestor = ancestor->parent;
 
        if (ancestor)
-               error = dev_pm_qos_add_request(ancestor, req,
-                                              DEV_PM_QOS_LATENCY, value);
+               ret = dev_pm_qos_add_request(ancestor, req,
+                                            DEV_PM_QOS_LATENCY, value);
 
-       if (error < 0)
+       if (ret < 0)
                req->dev = NULL;
 
-       return error;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 
index 07aad786f817e88300af9c4d6d685391f41b3471..d9a6c94ce42338b27c98c87f8e82910fdaa20579 100644 (file)
@@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = {
        .llseek = default_llseek,
 };
 
+static void regmap_debugfs_free_dump_cache(struct regmap *map)
+{
+       struct regmap_debugfs_off_cache *c;
+
+       while (!list_empty(&map->debugfs_off_cache)) {
+               c = list_first_entry(&map->debugfs_off_cache,
+                                    struct regmap_debugfs_off_cache,
+                                    list);
+               list_del(&c->list);
+               kfree(c);
+       }
+}
+
 /*
  * Work out where the start offset maps into register numbers, bearing
  * in mind that we suppress hidden registers.
@@ -91,8 +104,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
                        /* No cache entry?  Start a new one */
                        if (!c) {
                                c = kzalloc(sizeof(*c), GFP_KERNEL);
-                               if (!c)
-                                       break;
+                               if (!c) {
+                                       regmap_debugfs_free_dump_cache(map);
+                                       return base;
+                               }
                                c->min = p;
                                c->base_reg = i;
                        }
@@ -101,14 +116,32 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
                }
        }
 
+       /* Close the last entry off if we didn't scan beyond it */
+       if (c) {
+               c->max = p - 1;
+               list_add_tail(&c->list,
+                             &map->debugfs_off_cache);
+       }
+
+       /*
+        * This should never happen; we return above if we fail to
+        * allocate and we should never be in this code if there are
+        * no registers at all.
+        */
+       if (list_empty(&map->debugfs_off_cache)) {
+               WARN_ON(list_empty(&map->debugfs_off_cache));
+               return base;
+       }
+
        /* Find the relevant block */
        list_for_each_entry(c, &map->debugfs_off_cache, list) {
-               if (*pos >= c->min && *pos <= c->max) {
+               if (from >= c->min && from <= c->max) {
                        *pos = c->min;
                        return c->base_reg;
                }
 
-               ret = c->max;
+               *pos = c->min;
+               ret = c->base_reg;
        }
 
        return ret;
@@ -387,16 +420,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 
 void regmap_debugfs_exit(struct regmap *map)
 {
-       struct regmap_debugfs_off_cache *c;
-
        debugfs_remove_recursive(map->debugfs);
-       while (!list_empty(&map->debugfs_off_cache)) {
-               c = list_first_entry(&map->debugfs_off_cache,
-                                    struct regmap_debugfs_off_cache,
-                                    list);
-               list_del(&c->list);
-               kfree(c);
-       }
+       regmap_debugfs_free_dump_cache(map);
        kfree(map->debugfs_name);
 }
 
index 42d5cb0f503fb825104d7a0f02f79b63ab6f63da..f00b059c057ad01e4c8b9f05e95676c3c53c0e79 100644 (file)
@@ -1106,7 +1106,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write);
  * @val_count: Number of registers to write
  *
  * This function is intended to be used for writing a large block of
- * data to be device either in single transfer or multiple transfer.
+ * data to the device either in single transfer or multiple transfer.
  *
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
index d7b56a88c9f4d7211317484f441864263e4b0a20..8b4221cfd118bdb390fea9fa5e6bbfdfe37060f7 100644 (file)
@@ -67,8 +67,7 @@ config BCMA_DRIVER_GMAC_CMN
 
 config BCMA_DRIVER_GPIO
        bool "BCMA GPIO driver"
-       depends on BCMA
-       select GPIOLIB
+       depends on BCMA && GPIOLIB
        help
          Driver to provide access to the GPIO pins of the bcma bus.
 
index 4a2d72ec6d4325f49dd93baa09c99b8baff6d48c..cb0c4548857282c3bc6b38cfa836ad9474370604 100644 (file)
@@ -22,7 +22,7 @@
 struct bcma_bus;
 
 /* main.c */
-int __devinit bcma_bus_register(struct bcma_bus *bus);
+int bcma_bus_register(struct bcma_bus *bus);
 void bcma_bus_unregister(struct bcma_bus *bus);
 int __init bcma_bus_early_register(struct bcma_bus *bus,
                                   struct bcma_device *core_cc,
@@ -87,18 +87,23 @@ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
 extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc);
 
 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
-bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
-void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
 
 #ifdef CONFIG_BCMA_DRIVER_GPIO
 /* driver_gpio.c */
 int bcma_gpio_init(struct bcma_drv_cc *cc);
+int bcma_gpio_unregister(struct bcma_drv_cc *cc);
 #else
 static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
 {
        return -ENOTSUPP;
 }
+static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return 0;
+}
 #endif /* CONFIG_BCMA_DRIVER_GPIO */
 
 #endif
index dbda91e4dff5189ccabbb710b7a2a11f0e099651..1f0b83e18f6827f5003669b4015c2a89b2d369c5 100644 (file)
@@ -21,7 +21,7 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
        struct bcma_bus *bus = cc->core->bus;
 
        if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
-           cc->core->id.rev != 0x38) {
+           cc->core->id.rev != 38) {
                bcma_err(bus, "NAND flash on unsupported board!\n");
                return -ENOTSUPP;
        }
index 63e688393825539b5f2c64537cbefb1659c579c3..1e694db4532dd7aa41f95fc207b5bb0adea1556b 100644 (file)
@@ -35,7 +35,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
        { "M25P40", 0x12, 0x10000, 8, },
 
        { "M25P16", 0x14, 0x10000, 32, },
-       { "M25P32", 0x14, 0x10000, 64, },
+       { "M25P32", 0x15, 0x10000, 64, },
        { "M25P64", 0x16, 0x10000, 128, },
        { "M25FL128", 0x17, 0x10000, 256, },
        { 0 },
index 834225f65e8fca0804a644d1eaf55e48362efede..dcb137926d31e423dd51872c15cb7780cff8885f 100644 (file)
@@ -8,7 +8,7 @@
 #include "bcma_private.h"
 #include <linux/bcma/bcma.h>
 
-void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc)
+void bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc)
 {
        mutex_init(&gc->phy_mutex);
 }
index 9a6f585da2d9f21d232ac4b58cc3a36b442d9b36..71f755c06fc6637497665f31d15f6432d49c3075 100644 (file)
@@ -96,3 +96,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
 
        return gpiochip_add(chip);
 }
+
+int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return gpiochip_remove(&cc->gpio);
+}
index c39ee6d458506d6bb9c44eae651742e692255207..cf7a476a519f1809ec5313765c4e236e074a5230 100644 (file)
@@ -207,14 +207,14 @@ static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
  * Init.
  **************************************************/
 
-static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 {
        bcma_core_pci_fixcfg(pc);
        bcma_pcicore_serdes_workaround(pc);
        bcma_core_pci_config_fixup(pc);
 }
 
-void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
 {
        if (pc->setup_done)
                return;
index e6b5c89469dcea0fd7dec00809934b54eccafcbe..af0c9fabee54f212833809ecbfab0007bc9105fb 100644 (file)
@@ -24,7 +24,7 @@
 #define BCMA_PCI_SLOT_MAX      16
 #define        PCI_CONFIG_SPACE_SIZE   256
 
-bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
+bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
 {
        struct bcma_bus *bus = pc->core->bus;
        u16 chipid_top;
@@ -264,10 +264,9 @@ static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus,
 }
 
 /* return cap_offset if requested capability exists in the PCI config space */
-static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
-                                            unsigned int dev,
-                                            unsigned int func, u8 req_cap_id,
-                                            unsigned char *buf, u32 *buflen)
+static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
+                                  unsigned int func, u8 req_cap_id,
+                                  unsigned char *buf, u32 *buflen)
 {
        u8 cap_id;
        u8 cap_ptr = 0;
@@ -334,7 +333,7 @@ static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
  * Retry Status (CRS) Completion Status to software then
  * enable the feature.
  */
-static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
+static void bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
 {
        struct bcma_bus *bus = pc->core->bus;
        u8 cap_ptr, root_ctrl, root_cap, dev;
@@ -381,7 +380,7 @@ static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
        }
 }
 
-void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 {
        struct bcma_bus *bus = pc->core->bus;
        struct bcma_drv_pci_host *pc_host;
index 98fdc3e014e7f5ada5dd70cb26a511632d4d6acb..fbf2759e7e4e4d5f0777a058e37c5ab21976a2ce 100644 (file)
@@ -155,8 +155,8 @@ static const struct bcma_host_ops bcma_host_pci_ops = {
        .awrite32       = bcma_host_pci_awrite32,
 };
 
-static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
-                                        const struct pci_device_id *id)
+static int bcma_host_pci_probe(struct pci_dev *dev,
+                              const struct pci_device_id *id)
 {
        struct bcma_bus *bus;
        int err = -ENOMEM;
@@ -226,7 +226,7 @@ err_kfree_bus:
        return err;
 }
 
-static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
+static void bcma_host_pci_remove(struct pci_dev *dev)
 {
        struct bcma_bus *bus = pci_get_drvdata(dev);
 
@@ -284,7 +284,7 @@ static struct pci_driver bcma_pci_bridge_driver = {
        .name = "bcma-pci-bridge",
        .id_table = bcma_pci_bridge_tbl,
        .probe = bcma_host_pci_probe,
-       .remove = __devexit_p(bcma_host_pci_remove),
+       .remove = bcma_host_pci_remove,
        .driver.pm = BCMA_PM_OPS,
 };
 
index 53ba20ca17e0d00b1fc9087b540b41645c0f64bb..324f9debda88007ac096320dae35340db99e3fe5 100644 (file)
@@ -192,7 +192,7 @@ static void bcma_unregister_cores(struct bcma_bus *bus)
                platform_device_unregister(bus->drv_cc.watchdog);
 }
 
-int __devinit bcma_bus_register(struct bcma_bus *bus)
+int bcma_bus_register(struct bcma_bus *bus)
 {
        int err;
        struct bcma_device *core;
@@ -268,6 +268,13 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
        struct bcma_device *cores[3];
+       int err;
+
+       err = bcma_gpio_unregister(&bus->drv_cc);
+       if (err == -EBUSY)
+               bcma_err(bus, "Some GPIOs are still in use.\n");
+       else if (err)
+               bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
 
        cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
index 6526157edafc151e2761adf740a6404a6c046f26..ade58bc8f3c4dee67f69edde4ce20b1ef18d7cc8 100644 (file)
@@ -181,8 +181,8 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol,
                        sector_t total_size,
                        unsigned int block_size, InquiryData_struct *inq_buff,
                                   drive_info_struct *drv);
-static void __devinit cciss_interrupt_mode(ctlr_info_t *);
-static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
+static void cciss_interrupt_mode(ctlr_info_t *);
+static int cciss_enter_simple_mode(struct ctlr_info *h);
 static void start_io(ctlr_info_t *h);
 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
                        __u8 page_code, unsigned char scsi3addr[],
@@ -199,14 +199,13 @@ static void cciss_device_release(struct device *dev);
 static void cciss_free_gendisk(ctlr_info_t *h, int drv_index);
 static void cciss_free_drive_info(ctlr_info_t *h, int drv_index);
 static inline u32 next_command(ctlr_info_t *h);
-static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev,
-       void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
-       u64 *cfg_offset);
-static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
-       unsigned long *memory_bar);
+static int cciss_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+                               u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+                               u64 *cfg_offset);
+static int cciss_pci_find_memory_BAR(struct pci_dev *pdev,
+                                    unsigned long *memory_bar);
 static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag);
-static __devinit int write_driver_ver_to_cfgtable(
-       CfgTable_struct __iomem *cfgtable);
+static int write_driver_ver_to_cfgtable(CfgTable_struct __iomem *cfgtable);
 
 /* performant mode helper functions */
 static void  calc_bucket_map(int *bucket, int num_buckets, int nsgs,
@@ -550,7 +549,7 @@ static const struct file_operations cciss_proc_fops = {
        .write   = cciss_proc_write,
 };
 
-static void __devinit cciss_procinit(ctlr_info_t *h)
+static void cciss_procinit(ctlr_info_t *h)
 {
        struct proc_dir_entry *pde;
 
@@ -2663,8 +2662,8 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
        return status;
 }
 
-static int __devinit cciss_send_reset(ctlr_info_t *h, unsigned char *scsi3addr,
-       u8 reset_type)
+static int cciss_send_reset(ctlr_info_t *h, unsigned char *scsi3addr,
+                           u8 reset_type)
 {
        CommandList_struct *c;
        int return_status;
@@ -3919,7 +3918,7 @@ static void  calc_bucket_map(int bucket[], int num_buckets,
        }
 }
 
-static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
+static void cciss_wait_for_mode_change_ack(ctlr_info_t *h)
 {
        int i;
 
@@ -3933,8 +3932,7 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h)
        }
 }
 
-static __devinit void cciss_enter_performant_mode(ctlr_info_t *h,
-       u32 use_short_tags)
+static void cciss_enter_performant_mode(ctlr_info_t *h, u32 use_short_tags)
 {
        /* This is a bit complicated.  There are 8 registers on
         * the controller which we write to to tell it 8 different
@@ -4000,7 +3998,7 @@ static __devinit void cciss_enter_performant_mode(ctlr_info_t *h,
                                        " performant mode\n");
 }
 
-static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
+static void cciss_put_controller_into_performant_mode(ctlr_info_t *h)
 {
        __u32 trans_support;
 
@@ -4062,7 +4060,7 @@ clean_up:
  * controllers that are capable. If not, we use IO-APIC mode.
  */
 
-static void __devinit cciss_interrupt_mode(ctlr_info_t *h)
+static void cciss_interrupt_mode(ctlr_info_t *h)
 {
 #ifdef CONFIG_PCI_MSI
        int err;
@@ -4108,7 +4106,7 @@ default_int_mode:
        return;
 }
 
-static int __devinit cciss_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
+static int cciss_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
 {
        int i;
        u32 subsystem_vendor_id, subsystem_device_id;
@@ -4134,8 +4132,8 @@ static inline bool cciss_board_disabled(ctlr_info_t *h)
        return ((command & PCI_COMMAND_MEMORY) == 0);
 }
 
-static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
-       unsigned long *memory_bar)
+static int cciss_pci_find_memory_BAR(struct pci_dev *pdev,
+                                    unsigned long *memory_bar)
 {
        int i;
 
@@ -4151,8 +4149,8 @@ static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev,
-       void __iomem *vaddr, int wait_for_ready)
+static int cciss_wait_for_board_state(struct pci_dev *pdev,
+                                     void __iomem *vaddr, int wait_for_ready)
 #define BOARD_READY 1
 #define BOARD_NOT_READY 0
 {
@@ -4179,9 +4177,9 @@ static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev,
-       void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
-       u64 *cfg_offset)
+static int cciss_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+                               u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+                               u64 *cfg_offset)
 {
        *cfg_base_addr = readl(vaddr + SA5_CTCFG_OFFSET);
        *cfg_offset = readl(vaddr + SA5_CTMEM_OFFSET);
@@ -4195,7 +4193,7 @@ static int __devinit cciss_find_cfg_addrs(struct pci_dev *pdev,
        return 0;
 }
 
-static int __devinit cciss_find_cfgtables(ctlr_info_t *h)
+static int cciss_find_cfgtables(ctlr_info_t *h)
 {
        u64 cfg_offset;
        u32 cfg_base_addr;
@@ -4224,7 +4222,7 @@ static int __devinit cciss_find_cfgtables(ctlr_info_t *h)
        return 0;
 }
 
-static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h)
+static void cciss_get_max_perf_mode_cmds(struct ctlr_info *h)
 {
        h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
 
@@ -4245,7 +4243,7 @@ static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h)
  * max commands, max SG elements without chaining, and with chaining,
  * SG chain block size, etc.
  */
-static void __devinit cciss_find_board_params(ctlr_info_t *h)
+static void cciss_find_board_params(ctlr_info_t *h)
 {
        cciss_get_max_perf_mode_cmds(h);
        h->nr_cmds = h->max_commands - 4 - cciss_tape_cmds;
@@ -4304,7 +4302,7 @@ static inline void cciss_p600_dma_prefetch_quirk(ctlr_info_t *h)
        pci_write_config_dword(h->pdev, PCI_COMMAND_PARITY, dma_refetch);
 }
 
-static int __devinit cciss_pci_init(ctlr_info_t *h)
+static int cciss_pci_init(ctlr_info_t *h)
 {
        int prod_index, err;
 
@@ -4424,7 +4422,8 @@ static void free_hba(ctlr_info_t *h)
 }
 
 /* Send a message CDB to the firmware. */
-static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, unsigned char type)
+static int cciss_message(struct pci_dev *pdev, unsigned char opcode,
+                        unsigned char type)
 {
        typedef struct {
                CommandListHeader_struct CommandHeader;
@@ -4571,14 +4570,13 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev,
        return 0;
 }
 
-static __devinit void init_driver_version(char *driver_version, int len)
+static void init_driver_version(char *driver_version, int len)
 {
        memset(driver_version, 0, len);
        strncpy(driver_version, "cciss " DRIVER_NAME, len - 1);
 }
 
-static __devinit int write_driver_ver_to_cfgtable(
-       CfgTable_struct __iomem *cfgtable)
+static int write_driver_ver_to_cfgtable(CfgTable_struct __iomem *cfgtable)
 {
        char *driver_version;
        int i, size = sizeof(cfgtable->driver_version);
@@ -4594,8 +4592,8 @@ static __devinit int write_driver_ver_to_cfgtable(
        return 0;
 }
 
-static __devinit void read_driver_ver_from_cfgtable(
-       CfgTable_struct __iomem *cfgtable, unsigned char *driver_ver)
+static void read_driver_ver_from_cfgtable(CfgTable_struct __iomem *cfgtable,
+                                         unsigned char *driver_ver)
 {
        int i;
 
@@ -4603,8 +4601,7 @@ static __devinit void read_driver_ver_from_cfgtable(
                driver_ver[i] = readb(&cfgtable->driver_version[i]);
 }
 
-static __devinit int controller_reset_failed(
-       CfgTable_struct __iomem *cfgtable)
+static int controller_reset_failed(CfgTable_struct __iomem *cfgtable)
 {
 
        char *driver_ver, *old_driver_ver;
@@ -4627,7 +4624,7 @@ static __devinit int controller_reset_failed(
 
 /* This does a hard reset of the controller using PCI power management
  * states or using the doorbell register. */
-static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
+static int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
 {
        u64 cfg_offset;
        u32 cfg_base_addr;
@@ -4772,7 +4769,7 @@ unmap_vaddr:
        return rc;
 }
 
-static __devinit int cciss_init_reset_devices(struct pci_dev *pdev)
+static int cciss_init_reset_devices(struct pci_dev *pdev)
 {
        int rc, i;
 
@@ -4806,7 +4803,7 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev)
        return 0;
 }
 
-static __devinit int cciss_allocate_cmd_pool(ctlr_info_t *h)
+static int cciss_allocate_cmd_pool(ctlr_info_t *h)
 {
        h->cmd_pool_bits = kmalloc(BITS_TO_LONGS(h->nr_cmds) *
                sizeof(unsigned long), GFP_KERNEL);
@@ -4825,7 +4822,7 @@ static __devinit int cciss_allocate_cmd_pool(ctlr_info_t *h)
        return 0;
 }
 
-static __devinit int cciss_allocate_scatterlists(ctlr_info_t *h)
+static int cciss_allocate_scatterlists(ctlr_info_t *h)
 {
        int i;
 
@@ -4893,7 +4890,7 @@ static int cciss_request_irq(ctlr_info_t *h,
        return -1;
 }
 
-static int __devinit cciss_kdump_soft_reset(ctlr_info_t *h)
+static int cciss_kdump_soft_reset(ctlr_info_t *h)
 {
        if (cciss_send_reset(h, CTLR_LUNID, CCISS_RESET_TYPE_CONTROLLER)) {
                dev_warn(&h->pdev->dev, "Resetting array controller failed.\n");
@@ -4952,8 +4949,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
  *  stealing all these major device numbers.
  *  returns the number of block devices registered.
  */
-static int __devinit cciss_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int cciss_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int i;
        int j = 0;
@@ -5207,7 +5203,7 @@ static void cciss_shutdown(struct pci_dev *pdev)
        free_irq(h->intr[h->intr_mode], h);
 }
 
-static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
+static int cciss_enter_simple_mode(struct ctlr_info *h)
 {
        u32 trans_support;
 
@@ -5229,7 +5225,7 @@ static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
 }
 
 
-static void __devexit cciss_remove_one(struct pci_dev *pdev)
+static void cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *h;
        int i, j;
@@ -5308,7 +5304,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
 static struct pci_driver cciss_pci_driver = {
        .name = "cciss",
        .probe = cciss_init_one,
-       .remove = __devexit_p(cciss_remove_one),
+       .remove = cciss_remove_one,
        .id_table = cciss_pci_device_id,        /* id_table */
        .shutdown = cciss_shutdown,
 };
index 9125bbeacd4dcc6fa49043b7fe795b1c1c78b013..3f087133a25a0d2da7a0de32f26f83e7392ae4bd 100644 (file)
@@ -320,7 +320,7 @@ static void release_io_mem(ctlr_info_t *c)
        c->io_mem_length = 0;
 }
 
-static void __devexit cpqarray_remove_one(int i)
+static void cpqarray_remove_one(int i)
 {
        int j;
        char buff[4];
@@ -352,7 +352,7 @@ static void __devexit cpqarray_remove_one(int i)
        free_hba(i);
 }
 
-static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
+static void cpqarray_remove_one_pci(struct pci_dev *pdev)
 {
        int i;
        ctlr_info_t *tmp_ptr;
@@ -377,7 +377,7 @@ static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
 /* removing an instance that was not removed automatically..
  * must be an eisa card.
  */
-static void __devexit cpqarray_remove_one_eisa (int i)
+static void cpqarray_remove_one_eisa(int i)
 {
        if (hba[i] == NULL) {
                printk(KERN_ERR "cpqarray: controller %d appears to have"
@@ -388,7 +388,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
 }
 
 /* pdev is NULL for eisa */
-static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int cpqarray_register_ctlr(int i, struct pci_dev *pdev)
 {
        struct request_queue *q;
        int j;
@@ -505,8 +505,8 @@ Enomem4:
        return -1;
 }
 
-static int __devinit cpqarray_init_one( struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int cpqarray_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        int i;
 
@@ -536,7 +536,7 @@ static int __devinit cpqarray_init_one( struct pci_dev *pdev,
 static struct pci_driver cpqarray_pci_driver = {
        .name = "cpqarray",
        .probe = cpqarray_init_one,
-       .remove = __devexit_p(cpqarray_remove_one_pci),
+       .remove = cpqarray_remove_one_pci,
        .id_table = cpqarray_pci_device_id,
 };
 
@@ -742,7 +742,7 @@ __setup("smart2=", cpqarray_setup);
 /*
  * Find an EISA controller's signature.  Set up an hba if we find it.
  */
-static int __devinit cpqarray_eisa_detect(void)
+static int cpqarray_eisa_detect(void)
 {
        int i=0, j;
        __u32 board_id;
index f58a4a4b4dfb3d1042113bbcbf34ee7c8280b7e8..2b8303ad63c97966a3913854825cee60bec5320c 100644 (file)
@@ -168,7 +168,7 @@ static void wake_all_senders(struct drbd_tconn *tconn) {
 }
 
 /* must hold resource->req_lock */
-static void start_new_tl_epoch(struct drbd_tconn *tconn)
+void start_new_tl_epoch(struct drbd_tconn *tconn)
 {
        /* no point closing an epoch, if it is empty, anyways. */
        if (tconn->current_tle_writes == 0)
index 016de6b8bb57c2a646b348eb903fc870536a4512..c08d22964d06784024481cd0005784306341b891 100644 (file)
@@ -267,6 +267,7 @@ struct bio_and_error {
        int error;
 };
 
+extern void start_new_tl_epoch(struct drbd_tconn *tconn);
 extern void drbd_req_destroy(struct kref *kref);
 extern void _req_may_be_done(struct drbd_request *req,
                struct bio_and_error *m);
index 53bf6182bac4077afaa26bdeb94bb52e2414c76b..0fe220cfb9e9d31ce1dffac5e3365311076f66da 100644 (file)
@@ -931,6 +931,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
        enum drbd_state_rv rv = SS_SUCCESS;
        enum sanitize_state_warnings ssw;
        struct after_state_chg_work *ascw;
+       bool did_remote, should_do_remote;
 
        os = drbd_read_state(mdev);
 
@@ -981,11 +982,17 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
            (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
                atomic_inc(&mdev->local_cnt);
 
+       did_remote = drbd_should_do_remote(mdev->state);
        mdev->state.i = ns.i;
+       should_do_remote = drbd_should_do_remote(mdev->state);
        mdev->tconn->susp = ns.susp;
        mdev->tconn->susp_nod = ns.susp_nod;
        mdev->tconn->susp_fen = ns.susp_fen;
 
+       /* put replicated vs not-replicated requests in seperate epochs */
+       if (did_remote != should_do_remote)
+               start_new_tl_epoch(mdev->tconn);
+
        if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
                drbd_print_uuids(mdev, "attached to UUIDs");
 
index 9694dd99bbbc7253af1c3626823899f985b1afc2..3fd100990453b76f2297301e662e808819019ff2 100644 (file)
@@ -626,12 +626,13 @@ static void mtip_timeout_function(unsigned long int data)
                }
        }
 
-       if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+       if (cmdto_cnt) {
                print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
-
-               mtip_restart_port(port);
+               if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+                       mtip_restart_port(port);
+                       wake_up_interruptible(&port->svc_wait);
+               }
                clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
-               wake_up_interruptible(&port->svc_wait);
        }
 
        if (port->ic_pause_timer) {
@@ -3887,7 +3888,12 @@ static int mtip_block_remove(struct driver_data *dd)
         * Delete our gendisk structure. This also removes the device
         * from /dev
         */
-       del_gendisk(dd->disk);
+       if (dd->disk) {
+               if (dd->disk->queue)
+                       del_gendisk(dd->disk);
+               else
+                       put_disk(dd->disk);
+       }
 
        spin_lock(&rssd_index_lock);
        ida_remove(&rssd_index_ida, dd->index);
@@ -3921,7 +3927,13 @@ static int mtip_block_shutdown(struct driver_data *dd)
                "Shutting down %s ...\n", dd->disk->disk_name);
 
        /* Delete our gendisk structure, and cleanup the blk queue. */
-       del_gendisk(dd->disk);
+       if (dd->disk) {
+               if (dd->disk->queue)
+                       del_gendisk(dd->disk);
+               else
+                       put_disk(dd->disk);
+       }
+
 
        spin_lock(&rssd_index_lock);
        ida_remove(&rssd_index_ida, dd->index);
index 931769e133e5995b0cbe1e73e9dd7f5488f86f89..07fb2dfaae13f02588128ea0d73372a8859b63ba 100644 (file)
@@ -975,8 +975,8 @@ static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq,
                                IRQF_DISABLED | IRQF_SHARED, name, nvmeq);
 }
 
-static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
-                                       int qid, int cq_size, int vector)
+static struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, int qid,
+                                           int cq_size, int vector)
 {
        int result;
        struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector);
@@ -1011,7 +1011,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
        return ERR_PTR(result);
 }
 
-static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
+static int nvme_configure_admin_queue(struct nvme_dev *dev)
 {
        int result = 0;
        u32 aqa;
@@ -1408,7 +1408,7 @@ static int set_queue_count(struct nvme_dev *dev, int count)
        return min(result & 0xffff, result >> 16) + 1;
 }
 
-static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
+static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
        int result, cpu, i, nr_io_queues, db_bar_size, q_depth;
 
@@ -1481,7 +1481,7 @@ static void nvme_free_queues(struct nvme_dev *dev)
                nvme_free_queue(dev, i);
 }
 
-static int __devinit nvme_dev_add(struct nvme_dev *dev)
+static int nvme_dev_add(struct nvme_dev *dev)
 {
        int res, nn, i;
        struct nvme_ns *ns, *next;
@@ -1619,8 +1619,7 @@ static void nvme_release_instance(struct nvme_dev *dev)
        spin_unlock(&dev_list_lock);
 }
 
-static int __devinit nvme_probe(struct pci_dev *pdev,
-                                               const struct pci_device_id *id)
+static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int bars, result = -ENOMEM;
        struct nvme_dev *dev;
@@ -1702,7 +1701,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev,
        return result;
 }
 
-static void __devexit nvme_remove(struct pci_dev *pdev)
+static void nvme_remove(struct pci_dev *pdev)
 {
        struct nvme_dev *dev = pci_get_drvdata(pdev);
        nvme_dev_remove(dev);
@@ -1747,7 +1746,7 @@ static struct pci_driver nvme_driver = {
        .name           = "nvme",
        .id_table       = nvme_id_table,
        .probe          = nvme_probe,
-       .remove         = __devexit_p(nvme_remove),
+       .remove         = nvme_remove,
        .suspend        = nvme_suspend,
        .resume         = nvme_resume,
        .err_handler    = &nvme_err_handler,
index da0abc1838c196680bd093f0664924140ae4834f..d754a88d75858ef46f8553ac54b0163ff7b60d8a 100644 (file)
@@ -401,7 +401,7 @@ static unsigned long ps3disk_mask;
 
 static DEFINE_MUTEX(ps3disk_mask_mutex);
 
-static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
+static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 {
        struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
        struct ps3disk_private *priv;
index f58cdcfb305f2c497f408ac427e80fd1c536e648..75e112d660069411f5cb7d60c15733bac7b248d4 100644 (file)
@@ -536,7 +536,7 @@ static const struct file_operations ps3vram_proc_fops = {
        .release        = single_release,
 };
 
-static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
+static void ps3vram_proc_init(struct ps3_system_bus_device *dev)
 {
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
        struct proc_dir_entry *pde;
@@ -618,7 +618,7 @@ static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
        } while (bio);
 }
 
-static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
+static int ps3vram_probe(struct ps3_system_bus_device *dev)
 {
        struct ps3vram_priv *priv;
        int error, status;
index bb3d9be3b1b4eecb82ba82f8bc1045e825ff7a75..89576a0b3f2ed5b099ecf7ce675104d282b0dd48 100644 (file)
 
 #define RBD_MINORS_PER_MAJOR   256             /* max minors per blkdev */
 
-#define RBD_MAX_SNAP_NAME_LEN  32
+#define RBD_SNAP_DEV_NAME_PREFIX       "snap_"
+#define RBD_MAX_SNAP_NAME_LEN  \
+                       (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
+
 #define RBD_MAX_SNAP_COUNT     510     /* allows max snapc to fit in 4KB */
 #define RBD_MAX_OPT_LEN                1024
 
 #define RBD_SNAP_HEAD_NAME     "-"
 
+/* This allows a single page to hold an image name sent by OSD */
+#define RBD_IMAGE_NAME_LEN_MAX (PAGE_SIZE - sizeof (__le32) - 1)
 #define RBD_IMAGE_ID_LEN_MAX   64
+
 #define RBD_OBJ_PREFIX_LEN_MAX 64
 
+/* Feature bits */
+
+#define RBD_FEATURE_LAYERING      1
+
+/* Features supported by this (client software) implementation. */
+
+#define RBD_FEATURES_ALL          (0)
+
 /*
  * An RBD device name will be "rbd#", where the "rbd" comes from
  * RBD_DRV_NAME above, and # is a unique integer identifier.
@@ -101,6 +115,27 @@ struct rbd_image_header {
        u64 obj_version;
 };
 
+/*
+ * An rbd image specification.
+ *
+ * The tuple (pool_id, image_id, snap_id) is sufficient to uniquely
+ * identify an image.
+ */
+struct rbd_spec {
+       u64             pool_id;
+       char            *pool_name;
+
+       char            *image_id;
+       size_t          image_id_len;
+       char            *image_name;
+       size_t          image_name_len;
+
+       u64             snap_id;
+       char            *snap_name;
+
+       struct kref     kref;
+};
+
 struct rbd_options {
        bool    read_only;
 };
@@ -155,11 +190,8 @@ struct rbd_snap {
 };
 
 struct rbd_mapping {
-       char                    *snap_name;
-       u64                     snap_id;
        u64                     size;
        u64                     features;
-       bool                    snap_exists;
        bool                    read_only;
 };
 
@@ -173,7 +205,6 @@ struct rbd_device {
        struct gendisk          *disk;          /* blkdev's gendisk and rq */
 
        u32                     image_format;   /* Either 1 or 2 */
-       struct rbd_options      rbd_opts;
        struct rbd_client       *rbd_client;
 
        char                    name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
@@ -181,17 +212,17 @@ struct rbd_device {
        spinlock_t              lock;           /* queue lock */
 
        struct rbd_image_header header;
-       char                    *image_id;
-       size_t                  image_id_len;
-       char                    *image_name;
-       size_t                  image_name_len;
+       bool                    exists;
+       struct rbd_spec         *spec;
+
        char                    *header_name;
-       char                    *pool_name;
-       int                     pool_id;
 
        struct ceph_osd_event   *watch_event;
        struct ceph_osd_request *watch_request;
 
+       struct rbd_spec         *parent_spec;
+       u64                     parent_overlap;
+
        /* protects updating the header */
        struct rw_semaphore     header_rwsem;
 
@@ -204,6 +235,7 @@ struct rbd_device {
 
        /* sysfs related */
        struct device           dev;
+       unsigned long           open_count;
 };
 
 static DEFINE_MUTEX(ctl_mutex);          /* Serialize open/close/setup/teardown */
@@ -218,7 +250,7 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev);
 static int rbd_dev_snaps_register(struct rbd_device *rbd_dev);
 
 static void rbd_dev_release(struct device *dev);
-static void __rbd_remove_snap_dev(struct rbd_snap *snap);
+static void rbd_remove_snap_dev(struct rbd_snap *snap);
 
 static ssize_t rbd_add(struct bus_type *bus, const char *buf,
                       size_t count);
@@ -258,17 +290,8 @@ static struct device rbd_root_dev = {
 #  define rbd_assert(expr)     ((void) 0)
 #endif /* !RBD_DEBUG */
 
-static struct device *rbd_get_dev(struct rbd_device *rbd_dev)
-{
-       return get_device(&rbd_dev->dev);
-}
-
-static void rbd_put_dev(struct rbd_device *rbd_dev)
-{
-       put_device(&rbd_dev->dev);
-}
-
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver);
 
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
@@ -277,8 +300,11 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
        if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only)
                return -EROFS;
 
-       rbd_get_dev(rbd_dev);
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       (void) get_device(&rbd_dev->dev);
        set_device_ro(bdev, rbd_dev->mapping.read_only);
+       rbd_dev->open_count++;
+       mutex_unlock(&ctl_mutex);
 
        return 0;
 }
@@ -287,7 +313,11 @@ static int rbd_release(struct gendisk *disk, fmode_t mode)
 {
        struct rbd_device *rbd_dev = disk->private_data;
 
-       rbd_put_dev(rbd_dev);
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       rbd_assert(rbd_dev->open_count > 0);
+       rbd_dev->open_count--;
+       put_device(&rbd_dev->dev);
+       mutex_unlock(&ctl_mutex);
 
        return 0;
 }
@@ -388,7 +418,7 @@ enum {
 static match_table_t rbd_opts_tokens = {
        /* int args above */
        /* string args above */
-       {Opt_read_only, "mapping.read_only"},
+       {Opt_read_only, "read_only"},
        {Opt_read_only, "ro"},          /* Alternate spelling */
        {Opt_read_write, "read_write"},
        {Opt_read_write, "rw"},         /* Alternate spelling */
@@ -441,33 +471,17 @@ static int parse_rbd_opts_token(char *c, void *private)
  * Get a ceph client with specific addr and configuration, if one does
  * not exist create it.
  */
-static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
-                               size_t mon_addr_len, char *options)
+static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
 {
-       struct rbd_options *rbd_opts = &rbd_dev->rbd_opts;
-       struct ceph_options *ceph_opts;
        struct rbd_client *rbdc;
 
-       rbd_opts->read_only = RBD_READ_ONLY_DEFAULT;
-
-       ceph_opts = ceph_parse_options(options, mon_addr,
-                                       mon_addr + mon_addr_len,
-                                       parse_rbd_opts_token, rbd_opts);
-       if (IS_ERR(ceph_opts))
-               return PTR_ERR(ceph_opts);
-
        rbdc = rbd_client_find(ceph_opts);
-       if (rbdc) {
-               /* using an existing client */
+       if (rbdc)       /* using an existing client */
                ceph_destroy_options(ceph_opts);
-       } else {
+       else
                rbdc = rbd_client_create(ceph_opts);
-               if (IS_ERR(rbdc))
-                       return PTR_ERR(rbdc);
-       }
-       rbd_dev->rbd_client = rbdc;
 
-       return 0;
+       return rbdc;
 }
 
 /*
@@ -492,10 +506,10 @@ static void rbd_client_release(struct kref *kref)
  * Drop reference to ceph client node. If it's not referenced anymore, release
  * it.
  */
-static void rbd_put_client(struct rbd_device *rbd_dev)
+static void rbd_put_client(struct rbd_client *rbdc)
 {
-       kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
-       rbd_dev->rbd_client = NULL;
+       if (rbdc)
+               kref_put(&rbdc->kref, rbd_client_release);
 }
 
 /*
@@ -524,6 +538,16 @@ static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk)
        if (memcmp(&ondisk->text, RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT)))
                return false;
 
+       /* The bio layer requires at least sector-sized I/O */
+
+       if (ondisk->options.order < SECTOR_SHIFT)
+               return false;
+
+       /* If we use u64 in a few spots we may be able to loosen this */
+
+       if (ondisk->options.order > 8 * sizeof (int) - 1)
+               return false;
+
        /*
         * The size of a snapshot header has to fit in a size_t, and
         * that limits the number of snapshots.
@@ -635,6 +659,20 @@ out_err:
        return -ENOMEM;
 }
 
+static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id)
+{
+       struct rbd_snap *snap;
+
+       if (snap_id == CEPH_NOSNAP)
+               return RBD_SNAP_HEAD_NAME;
+
+       list_for_each_entry(snap, &rbd_dev->snaps, node)
+               if (snap_id == snap->id)
+                       return snap->name;
+
+       return NULL;
+}
+
 static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name)
 {
 
@@ -642,7 +680,7 @@ static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name)
 
        list_for_each_entry(snap, &rbd_dev->snaps, node) {
                if (!strcmp(snap_name, snap->name)) {
-                       rbd_dev->mapping.snap_id = snap->id;
+                       rbd_dev->spec->snap_id = snap->id;
                        rbd_dev->mapping.size = snap->size;
                        rbd_dev->mapping.features = snap->features;
 
@@ -653,26 +691,23 @@ static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name)
        return -ENOENT;
 }
 
-static int rbd_dev_set_mapping(struct rbd_device *rbd_dev, char *snap_name)
+static int rbd_dev_set_mapping(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       if (!memcmp(snap_name, RBD_SNAP_HEAD_NAME,
+       if (!memcmp(rbd_dev->spec->snap_name, RBD_SNAP_HEAD_NAME,
                    sizeof (RBD_SNAP_HEAD_NAME))) {
-               rbd_dev->mapping.snap_id = CEPH_NOSNAP;
+               rbd_dev->spec->snap_id = CEPH_NOSNAP;
                rbd_dev->mapping.size = rbd_dev->header.image_size;
                rbd_dev->mapping.features = rbd_dev->header.features;
-               rbd_dev->mapping.snap_exists = false;
-               rbd_dev->mapping.read_only = rbd_dev->rbd_opts.read_only;
                ret = 0;
        } else {
-               ret = snap_by_name(rbd_dev, snap_name);
+               ret = snap_by_name(rbd_dev, rbd_dev->spec->snap_name);
                if (ret < 0)
                        goto done;
-               rbd_dev->mapping.snap_exists = true;
                rbd_dev->mapping.read_only = true;
        }
-       rbd_dev->mapping.snap_name = snap_name;
+       rbd_dev->exists = true;
 done:
        return ret;
 }
@@ -695,13 +730,13 @@ static char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
        u64 segment;
        int ret;
 
-       name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+       name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO);
        if (!name)
                return NULL;
        segment = offset >> rbd_dev->header.obj_order;
-       ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx",
+       ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx",
                        rbd_dev->header.object_prefix, segment);
-       if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) {
+       if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) {
                pr_err("error formatting segment name for #%llu (%d)\n",
                        segment, ret);
                kfree(name);
@@ -800,77 +835,144 @@ static void zero_bio_chain(struct bio *chain, int start_ofs)
 }
 
 /*
- * bio_chain_clone - clone a chain of bios up to a certain length.
- * might return a bio_pair that will need to be released.
+ * Clone a portion of a bio, starting at the given byte offset
+ * and continuing for the number of bytes indicated.
  */
-static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
-                                  struct bio_pair **bp,
-                                  int len, gfp_t gfpmask)
-{
-       struct bio *old_chain = *old;
-       struct bio *new_chain = NULL;
-       struct bio *tail;
-       int total = 0;
-
-       if (*bp) {
-               bio_pair_release(*bp);
-               *bp = NULL;
-       }
+static struct bio *bio_clone_range(struct bio *bio_src,
+                                       unsigned int offset,
+                                       unsigned int len,
+                                       gfp_t gfpmask)
+{
+       struct bio_vec *bv;
+       unsigned int resid;
+       unsigned short idx;
+       unsigned int voff;
+       unsigned short end_idx;
+       unsigned short vcnt;
+       struct bio *bio;
 
-       while (old_chain && (total < len)) {
-               struct bio *tmp;
+       /* Handle the easy case for the caller */
 
-               tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
-               if (!tmp)
-                       goto err_out;
-               gfpmask &= ~__GFP_WAIT; /* can't wait after the first */
+       if (!offset && len == bio_src->bi_size)
+               return bio_clone(bio_src, gfpmask);
 
-               if (total + old_chain->bi_size > len) {
-                       struct bio_pair *bp;
+       if (WARN_ON_ONCE(!len))
+               return NULL;
+       if (WARN_ON_ONCE(len > bio_src->bi_size))
+               return NULL;
+       if (WARN_ON_ONCE(offset > bio_src->bi_size - len))
+               return NULL;
 
-                       /*
-                        * this split can only happen with a single paged bio,
-                        * split_bio will BUG_ON if this is not the case
-                        */
-                       dout("bio_chain_clone split! total=%d remaining=%d"
-                            "bi_size=%u\n",
-                            total, len - total, old_chain->bi_size);
+       /* Find first affected segment... */
 
-                       /* split the bio. We'll release it either in the next
-                          call, or it will have to be released outside */
-                       bp = bio_split(old_chain, (len - total) / SECTOR_SIZE);
-                       if (!bp)
-                               goto err_out;
+       resid = offset;
+       __bio_for_each_segment(bv, bio_src, idx, 0) {
+               if (resid < bv->bv_len)
+                       break;
+               resid -= bv->bv_len;
+       }
+       voff = resid;
 
-                       __bio_clone(tmp, &bp->bio1);
+       /* ...and the last affected segment */
 
-                       *next = &bp->bio2;
-               } else {
-                       __bio_clone(tmp, old_chain);
-                       *next = old_chain->bi_next;
-               }
+       resid += len;
+       __bio_for_each_segment(bv, bio_src, end_idx, idx) {
+               if (resid <= bv->bv_len)
+                       break;
+               resid -= bv->bv_len;
+       }
+       vcnt = end_idx - idx + 1;
+
+       /* Build the clone */
 
-               tmp->bi_bdev = NULL;
-               tmp->bi_next = NULL;
-               if (new_chain)
-                       tail->bi_next = tmp;
-               else
-                       new_chain = tmp;
-               tail = tmp;
-               old_chain = old_chain->bi_next;
+       bio = bio_alloc(gfpmask, (unsigned int) vcnt);
+       if (!bio)
+               return NULL;    /* ENOMEM */
 
-               total += tmp->bi_size;
+       bio->bi_bdev = bio_src->bi_bdev;
+       bio->bi_sector = bio_src->bi_sector + (offset >> SECTOR_SHIFT);
+       bio->bi_rw = bio_src->bi_rw;
+       bio->bi_flags |= 1 << BIO_CLONED;
+
+       /*
+        * Copy over our part of the bio_vec, then update the first
+        * and last (or only) entries.
+        */
+       memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[idx],
+                       vcnt * sizeof (struct bio_vec));
+       bio->bi_io_vec[0].bv_offset += voff;
+       if (vcnt > 1) {
+               bio->bi_io_vec[0].bv_len -= voff;
+               bio->bi_io_vec[vcnt - 1].bv_len = resid;
+       } else {
+               bio->bi_io_vec[0].bv_len = len;
        }
 
-       rbd_assert(total == len);
+       bio->bi_vcnt = vcnt;
+       bio->bi_size = len;
+       bio->bi_idx = 0;
+
+       return bio;
+}
+
+/*
+ * Clone a portion of a bio chain, starting at the given byte offset
+ * into the first bio in the source chain and continuing for the
+ * number of bytes indicated.  The result is another bio chain of
+ * exactly the given length, or a null pointer on error.
+ *
+ * The bio_src and offset parameters are both in-out.  On entry they
+ * refer to the first source bio and the offset into that bio where
+ * the start of data to be cloned is located.
+ *
+ * On return, bio_src is updated to refer to the bio in the source
+ * chain that contains first un-cloned byte, and *offset will
+ * contain the offset of that byte within that bio.
+ */
+static struct bio *bio_chain_clone_range(struct bio **bio_src,
+                                       unsigned int *offset,
+                                       unsigned int len,
+                                       gfp_t gfpmask)
+{
+       struct bio *bi = *bio_src;
+       unsigned int off = *offset;
+       struct bio *chain = NULL;
+       struct bio **end;
+
+       /* Build up a chain of clone bios up to the limit */
+
+       if (!bi || off >= bi->bi_size || !len)
+               return NULL;            /* Nothing to clone */
 
-       *old = old_chain;
+       end = &chain;
+       while (len) {
+               unsigned int bi_size;
+               struct bio *bio;
+
+               if (!bi)
+                       goto out_err;   /* EINVAL; ran out of bio's */
+               bi_size = min_t(unsigned int, bi->bi_size - off, len);
+               bio = bio_clone_range(bi, off, bi_size, gfpmask);
+               if (!bio)
+                       goto out_err;   /* ENOMEM */
+
+               *end = bio;
+               end = &bio->bi_next;
+
+               off += bi_size;
+               if (off == bi->bi_size) {
+                       bi = bi->bi_next;
+                       off = 0;
+               }
+               len -= bi_size;
+       }
+       *bio_src = bi;
+       *offset = off;
 
-       return new_chain;
+       return chain;
+out_err:
+       bio_chain_put(chain);
 
-err_out:
-       dout("bio_chain_clone with err\n");
-       bio_chain_put(new_chain);
        return NULL;
 }
 
@@ -988,8 +1090,9 @@ static int rbd_do_request(struct request *rq,
                req_data->coll_index = coll_index;
        }
 
-       dout("rbd_do_request object_name=%s ofs=%llu len=%llu\n", object_name,
-               (unsigned long long) ofs, (unsigned long long) len);
+       dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n",
+               object_name, (unsigned long long) ofs,
+               (unsigned long long) len, coll, coll_index);
 
        osdc = &rbd_dev->rbd_client->client->osdc;
        req = ceph_osdc_alloc_request(osdc, flags, snapc, ops,
@@ -1019,7 +1122,7 @@ static int rbd_do_request(struct request *rq,
        layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
        layout->fl_stripe_count = cpu_to_le32(1);
        layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
-       layout->fl_pg_pool = cpu_to_le32(rbd_dev->pool_id);
+       layout->fl_pg_pool = cpu_to_le32((int) rbd_dev->spec->pool_id);
        ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno,
                                   req, ops);
        rbd_assert(ret == 0);
@@ -1154,8 +1257,6 @@ done:
 static int rbd_do_op(struct request *rq,
                     struct rbd_device *rbd_dev,
                     struct ceph_snap_context *snapc,
-                    u64 snapid,
-                    int opcode, int flags,
                     u64 ofs, u64 len,
                     struct bio *bio,
                     struct rbd_req_coll *coll,
@@ -1167,6 +1268,9 @@ static int rbd_do_op(struct request *rq,
        int ret;
        struct ceph_osd_req_op *ops;
        u32 payload_len;
+       int opcode;
+       int flags;
+       u64 snapid;
 
        seg_name = rbd_segment_name(rbd_dev, ofs);
        if (!seg_name)
@@ -1174,7 +1278,18 @@ static int rbd_do_op(struct request *rq,
        seg_len = rbd_segment_length(rbd_dev, ofs, len);
        seg_ofs = rbd_segment_offset(rbd_dev, ofs);
 
-       payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0);
+       if (rq_data_dir(rq) == WRITE) {
+               opcode = CEPH_OSD_OP_WRITE;
+               flags = CEPH_OSD_FLAG_WRITE|CEPH_OSD_FLAG_ONDISK;
+               snapid = CEPH_NOSNAP;
+               payload_len = seg_len;
+       } else {
+               opcode = CEPH_OSD_OP_READ;
+               flags = CEPH_OSD_FLAG_READ;
+               snapc = NULL;
+               snapid = rbd_dev->spec->snap_id;
+               payload_len = 0;
+       }
 
        ret = -ENOMEM;
        ops = rbd_create_rw_ops(1, opcode, payload_len);
@@ -1201,41 +1316,6 @@ done:
        return ret;
 }
 
-/*
- * Request async osd write
- */
-static int rbd_req_write(struct request *rq,
-                        struct rbd_device *rbd_dev,
-                        struct ceph_snap_context *snapc,
-                        u64 ofs, u64 len,
-                        struct bio *bio,
-                        struct rbd_req_coll *coll,
-                        int coll_index)
-{
-       return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
-                        CEPH_OSD_OP_WRITE,
-                        CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
-                        ofs, len, bio, coll, coll_index);
-}
-
-/*
- * Request async osd read
- */
-static int rbd_req_read(struct request *rq,
-                        struct rbd_device *rbd_dev,
-                        u64 snapid,
-                        u64 ofs, u64 len,
-                        struct bio *bio,
-                        struct rbd_req_coll *coll,
-                        int coll_index)
-{
-       return rbd_do_op(rq, rbd_dev, NULL,
-                        snapid,
-                        CEPH_OSD_OP_READ,
-                        CEPH_OSD_FLAG_READ,
-                        ofs, len, bio, coll, coll_index);
-}
-
 /*
  * Request sync osd read
  */
@@ -1304,7 +1384,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
        dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n",
                rbd_dev->header_name, (unsigned long long) notify_id,
                (unsigned int) opcode);
-       rc = rbd_refresh_header(rbd_dev, &hver);
+       rc = rbd_dev_refresh(rbd_dev, &hver);
        if (rc)
                pr_warning(RBD_DRV_NAME "%d got notification but failed to "
                           " update snaps: %d\n", rbd_dev->major, rc);
@@ -1460,18 +1540,16 @@ static void rbd_rq_fn(struct request_queue *q)
 {
        struct rbd_device *rbd_dev = q->queuedata;
        struct request *rq;
-       struct bio_pair *bp = NULL;
 
        while ((rq = blk_fetch_request(q))) {
                struct bio *bio;
-               struct bio *rq_bio, *next_bio = NULL;
                bool do_write;
                unsigned int size;
-               u64 op_size = 0;
                u64 ofs;
                int num_segs, cur_seg = 0;
                struct rbd_req_coll *coll;
                struct ceph_snap_context *snapc;
+               unsigned int bio_offset;
 
                dout("fetched request\n");
 
@@ -1483,10 +1561,6 @@ static void rbd_rq_fn(struct request_queue *q)
 
                /* deduce our operation (read, write) */
                do_write = (rq_data_dir(rq) == WRITE);
-
-               size = blk_rq_bytes(rq);
-               ofs = blk_rq_pos(rq) * SECTOR_SIZE;
-               rq_bio = rq->bio;
                if (do_write && rbd_dev->mapping.read_only) {
                        __blk_end_request_all(rq, -EROFS);
                        continue;
@@ -1496,8 +1570,8 @@ static void rbd_rq_fn(struct request_queue *q)
 
                down_read(&rbd_dev->header_rwsem);
 
-               if (rbd_dev->mapping.snap_id != CEPH_NOSNAP &&
-                               !rbd_dev->mapping.snap_exists) {
+               if (!rbd_dev->exists) {
+                       rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
                        up_read(&rbd_dev->header_rwsem);
                        dout("request for non-existent snapshot");
                        spin_lock_irq(q->queue_lock);
@@ -1509,6 +1583,10 @@ static void rbd_rq_fn(struct request_queue *q)
 
                up_read(&rbd_dev->header_rwsem);
 
+               size = blk_rq_bytes(rq);
+               ofs = blk_rq_pos(rq) * SECTOR_SIZE;
+               bio = rq->bio;
+
                dout("%s 0x%x bytes at 0x%llx\n",
                     do_write ? "write" : "read",
                     size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE);
@@ -1528,45 +1606,37 @@ static void rbd_rq_fn(struct request_queue *q)
                        continue;
                }
 
+               bio_offset = 0;
                do {
-                       /* a bio clone to be passed down to OSD req */
+                       u64 limit = rbd_segment_length(rbd_dev, ofs, size);
+                       unsigned int chain_size;
+                       struct bio *bio_chain;
+
+                       BUG_ON(limit > (u64) UINT_MAX);
+                       chain_size = (unsigned int) limit;
                        dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt);
-                       op_size = rbd_segment_length(rbd_dev, ofs, size);
+
                        kref_get(&coll->kref);
-                       bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
-                                             op_size, GFP_ATOMIC);
-                       if (!bio) {
-                               rbd_coll_end_req_index(rq, coll, cur_seg,
-                                                      -ENOMEM, op_size);
-                               goto next_seg;
-                       }
 
+                       /* Pass a cloned bio chain via an osd request */
 
-                       /* init OSD command: write or read */
-                       if (do_write)
-                               rbd_req_write(rq, rbd_dev,
-                                             snapc,
-                                             ofs,
-                                             op_size, bio,
-                                             coll, cur_seg);
+                       bio_chain = bio_chain_clone_range(&bio,
+                                               &bio_offset, chain_size,
+                                               GFP_ATOMIC);
+                       if (bio_chain)
+                               (void) rbd_do_op(rq, rbd_dev, snapc,
+                                               ofs, chain_size,
+                                               bio_chain, coll, cur_seg);
                        else
-                               rbd_req_read(rq, rbd_dev,
-                                            rbd_dev->mapping.snap_id,
-                                            ofs,
-                                            op_size, bio,
-                                            coll, cur_seg);
-
-next_seg:
-                       size -= op_size;
-                       ofs += op_size;
+                               rbd_coll_end_req_index(rq, coll, cur_seg,
+                                                      -ENOMEM, chain_size);
+                       size -= chain_size;
+                       ofs += chain_size;
 
                        cur_seg++;
-                       rq_bio = next_bio;
                } while (size > 0);
                kref_put(&coll->kref, rbd_coll_release);
 
-               if (bp)
-                       bio_pair_release(bp);
                spin_lock_irq(q->queue_lock);
 
                ceph_put_snap_context(snapc);
@@ -1576,28 +1646,47 @@ next_seg:
 /*
  * a queue callback. Makes sure that we don't create a bio that spans across
  * multiple osd objects. One exception would be with a single page bios,
- * which we handle later at bio_chain_clone
+ * which we handle later at bio_chain_clone_range()
  */
 static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
                          struct bio_vec *bvec)
 {
        struct rbd_device *rbd_dev = q->queuedata;
-       unsigned int chunk_sectors;
-       sector_t sector;
-       unsigned int bio_sectors;
-       int max;
+       sector_t sector_offset;
+       sector_t sectors_per_obj;
+       sector_t obj_sector_offset;
+       int ret;
 
-       chunk_sectors = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
-       sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev);
-       bio_sectors = bmd->bi_size >> SECTOR_SHIFT;
+       /*
+        * Find how far into its rbd object the partition-relative
+        * bio start sector is to offset relative to the enclosing
+        * device.
+        */
+       sector_offset = get_start_sect(bmd->bi_bdev) + bmd->bi_sector;
+       sectors_per_obj = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
+       obj_sector_offset = sector_offset & (sectors_per_obj - 1);
+
+       /*
+        * Compute the number of bytes from that offset to the end
+        * of the object.  Account for what's already used by the bio.
+        */
+       ret = (int) (sectors_per_obj - obj_sector_offset) << SECTOR_SHIFT;
+       if (ret > bmd->bi_size)
+               ret -= bmd->bi_size;
+       else
+               ret = 0;
 
-       max =  (chunk_sectors - ((sector & (chunk_sectors - 1))
-                                + bio_sectors)) << SECTOR_SHIFT;
-       if (max < 0)
-               max = 0; /* bio_add cannot handle a negative return */
-       if (max <= bvec->bv_len && bio_sectors == 0)
-               return bvec->bv_len;
-       return max;
+       /*
+        * Don't send back more than was asked for.  And if the bio
+        * was empty, let the whole thing through because:  "Note
+        * that a block device *must* allow a single page to be
+        * added to an empty bio."
+        */
+       rbd_assert(bvec->bv_len <= PAGE_SIZE);
+       if (ret > (int) bvec->bv_len || !bmd->bi_size)
+               ret = (int) bvec->bv_len;
+
+       return ret;
 }
 
 static void rbd_free_disk(struct rbd_device *rbd_dev)
@@ -1663,13 +1752,13 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev, u64 *version)
                        ret = -ENXIO;
                        pr_warning("short header read for image %s"
                                        " (want %zd got %d)\n",
-                               rbd_dev->image_name, size, ret);
+                               rbd_dev->spec->image_name, size, ret);
                        goto out_err;
                }
                if (!rbd_dev_ondisk_valid(ondisk)) {
                        ret = -ENXIO;
                        pr_warning("invalid header for image %s\n",
-                               rbd_dev->image_name);
+                               rbd_dev->spec->image_name);
                        goto out_err;
                }
 
@@ -1707,19 +1796,32 @@ static int rbd_read_header(struct rbd_device *rbd_dev,
        return ret;
 }
 
-static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev)
+static void rbd_remove_all_snaps(struct rbd_device *rbd_dev)
 {
        struct rbd_snap *snap;
        struct rbd_snap *next;
 
        list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node)
-               __rbd_remove_snap_dev(snap);
+               rbd_remove_snap_dev(snap);
+}
+
+static void rbd_update_mapping_size(struct rbd_device *rbd_dev)
+{
+       sector_t size;
+
+       if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
+               return;
+
+       size = (sector_t) rbd_dev->header.image_size / SECTOR_SIZE;
+       dout("setting size to %llu sectors", (unsigned long long) size);
+       rbd_dev->mapping.size = (u64) size;
+       set_capacity(rbd_dev->disk, size);
 }
 
 /*
  * only read the first part of the ondisk header, without the snaps info
  */
-static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
        int ret;
        struct rbd_image_header h;
@@ -1730,17 +1832,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
 
        down_write(&rbd_dev->header_rwsem);
 
-       /* resized? */
-       if (rbd_dev->mapping.snap_id == CEPH_NOSNAP) {
-               sector_t size = (sector_t) h.image_size / SECTOR_SIZE;
-
-               if (size != (sector_t) rbd_dev->mapping.size) {
-                       dout("setting size to %llu sectors",
-                               (unsigned long long) size);
-                       rbd_dev->mapping.size = (u64) size;
-                       set_capacity(rbd_dev->disk, size);
-               }
-       }
+       /* Update image size, and check for resize of mapped image */
+       rbd_dev->header.image_size = h.image_size;
+       rbd_update_mapping_size(rbd_dev);
 
        /* rbd_dev->header.object_prefix shouldn't change */
        kfree(rbd_dev->header.snap_sizes);
@@ -1768,12 +1862,16 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
        return ret;
 }
 
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
        int ret;
 
+       rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-       ret = __rbd_refresh_header(rbd_dev, hver);
+       if (rbd_dev->image_format == 1)
+               ret = rbd_dev_v1_refresh(rbd_dev, hver);
+       else
+               ret = rbd_dev_v2_refresh(rbd_dev, hver);
        mutex_unlock(&ctl_mutex);
 
        return ret;
@@ -1885,7 +1983,7 @@ static ssize_t rbd_pool_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       return sprintf(buf, "%s\n", rbd_dev->pool_name);
+       return sprintf(buf, "%s\n", rbd_dev->spec->pool_name);
 }
 
 static ssize_t rbd_pool_id_show(struct device *dev,
@@ -1893,7 +1991,8 @@ static ssize_t rbd_pool_id_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       return sprintf(buf, "%d\n", rbd_dev->pool_id);
+       return sprintf(buf, "%llu\n",
+               (unsigned long long) rbd_dev->spec->pool_id);
 }
 
 static ssize_t rbd_name_show(struct device *dev,
@@ -1901,7 +2000,10 @@ static ssize_t rbd_name_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       return sprintf(buf, "%s\n", rbd_dev->image_name);
+       if (rbd_dev->spec->image_name)
+               return sprintf(buf, "%s\n", rbd_dev->spec->image_name);
+
+       return sprintf(buf, "(unknown)\n");
 }
 
 static ssize_t rbd_image_id_show(struct device *dev,
@@ -1909,7 +2011,7 @@ static ssize_t rbd_image_id_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       return sprintf(buf, "%s\n", rbd_dev->image_id);
+       return sprintf(buf, "%s\n", rbd_dev->spec->image_id);
 }
 
 /*
@@ -1922,7 +2024,50 @@ static ssize_t rbd_snap_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       return sprintf(buf, "%s\n", rbd_dev->mapping.snap_name);
+       return sprintf(buf, "%s\n", rbd_dev->spec->snap_name);
+}
+
+/*
+ * For an rbd v2 image, shows the pool id, image id, and snapshot id
+ * for the parent image.  If there is no parent, simply shows
+ * "(no parent image)".
+ */
+static ssize_t rbd_parent_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+       struct rbd_spec *spec = rbd_dev->parent_spec;
+       int count;
+       char *bufp = buf;
+
+       if (!spec)
+               return sprintf(buf, "(no parent image)\n");
+
+       count = sprintf(bufp, "pool_id %llu\npool_name %s\n",
+                       (unsigned long long) spec->pool_id, spec->pool_name);
+       if (count < 0)
+               return count;
+       bufp += count;
+
+       count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id,
+                       spec->image_name ? spec->image_name : "(unknown)");
+       if (count < 0)
+               return count;
+       bufp += count;
+
+       count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n",
+                       (unsigned long long) spec->snap_id, spec->snap_name);
+       if (count < 0)
+               return count;
+       bufp += count;
+
+       count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap);
+       if (count < 0)
+               return count;
+       bufp += count;
+
+       return (ssize_t) (bufp - buf);
 }
 
 static ssize_t rbd_image_refresh(struct device *dev,
@@ -1933,7 +2078,7 @@ static ssize_t rbd_image_refresh(struct device *dev,
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
        int ret;
 
-       ret = rbd_refresh_header(rbd_dev, NULL);
+       ret = rbd_dev_refresh(rbd_dev, NULL);
 
        return ret < 0 ? ret : size;
 }
@@ -1948,6 +2093,7 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL);
 static DEVICE_ATTR(image_id, S_IRUGO, rbd_image_id_show, NULL);
 static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh);
 static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL);
+static DEVICE_ATTR(parent, S_IRUGO, rbd_parent_show, NULL);
 
 static struct attribute *rbd_attrs[] = {
        &dev_attr_size.attr,
@@ -1959,6 +2105,7 @@ static struct attribute *rbd_attrs[] = {
        &dev_attr_name.attr,
        &dev_attr_image_id.attr,
        &dev_attr_current_snap.attr,
+       &dev_attr_parent.attr,
        &dev_attr_refresh.attr,
        NULL
 };
@@ -2047,6 +2194,74 @@ static struct device_type rbd_snap_device_type = {
        .release        = rbd_snap_dev_release,
 };
 
+static struct rbd_spec *rbd_spec_get(struct rbd_spec *spec)
+{
+       kref_get(&spec->kref);
+
+       return spec;
+}
+
+static void rbd_spec_free(struct kref *kref);
+static void rbd_spec_put(struct rbd_spec *spec)
+{
+       if (spec)
+               kref_put(&spec->kref, rbd_spec_free);
+}
+
+static struct rbd_spec *rbd_spec_alloc(void)
+{
+       struct rbd_spec *spec;
+
+       spec = kzalloc(sizeof (*spec), GFP_KERNEL);
+       if (!spec)
+               return NULL;
+       kref_init(&spec->kref);
+
+       rbd_spec_put(rbd_spec_get(spec));       /* TEMPORARY */
+
+       return spec;
+}
+
+static void rbd_spec_free(struct kref *kref)
+{
+       struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref);
+
+       kfree(spec->pool_name);
+       kfree(spec->image_id);
+       kfree(spec->image_name);
+       kfree(spec->snap_name);
+       kfree(spec);
+}
+
+struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
+                               struct rbd_spec *spec)
+{
+       struct rbd_device *rbd_dev;
+
+       rbd_dev = kzalloc(sizeof (*rbd_dev), GFP_KERNEL);
+       if (!rbd_dev)
+               return NULL;
+
+       spin_lock_init(&rbd_dev->lock);
+       INIT_LIST_HEAD(&rbd_dev->node);
+       INIT_LIST_HEAD(&rbd_dev->snaps);
+       init_rwsem(&rbd_dev->header_rwsem);
+
+       rbd_dev->spec = spec;
+       rbd_dev->rbd_client = rbdc;
+
+       return rbd_dev;
+}
+
+static void rbd_dev_destroy(struct rbd_device *rbd_dev)
+{
+       rbd_spec_put(rbd_dev->parent_spec);
+       kfree(rbd_dev->header_name);
+       rbd_put_client(rbd_dev->rbd_client);
+       rbd_spec_put(rbd_dev->spec);
+       kfree(rbd_dev);
+}
+
 static bool rbd_snap_registered(struct rbd_snap *snap)
 {
        bool ret = snap->dev.type == &rbd_snap_device_type;
@@ -2057,7 +2272,7 @@ static bool rbd_snap_registered(struct rbd_snap *snap)
        return ret;
 }
 
-static void __rbd_remove_snap_dev(struct rbd_snap *snap)
+static void rbd_remove_snap_dev(struct rbd_snap *snap)
 {
        list_del(&snap->node);
        if (device_is_registered(&snap->dev))
@@ -2073,7 +2288,7 @@ static int rbd_register_snap_dev(struct rbd_snap *snap,
        dev->type = &rbd_snap_device_type;
        dev->parent = parent;
        dev->release = rbd_snap_dev_release;
-       dev_set_name(dev, "snap_%s", snap->name);
+       dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name);
        dout("%s: registering device for snapshot %s\n", __func__, snap->name);
 
        ret = device_register(dev);
@@ -2189,6 +2404,7 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
        dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
        if (ret < 0)
                goto out;
+       ret = 0;    /* rbd_req_sync_exec() can return positive */
 
        p = reply_buf;
        rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
@@ -2216,6 +2432,7 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
                __le64 features;
                __le64 incompat;
        } features_buf = { 0 };
+       u64 incompat;
        int ret;
 
        ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
@@ -2226,6 +2443,11 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
        dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
        if (ret < 0)
                return ret;
+
+       incompat = le64_to_cpu(features_buf.incompat);
+       if (incompat & ~RBD_FEATURES_ALL)
+               return -ENXIO;
+
        *snap_features = le64_to_cpu(features_buf.features);
 
        dout("  snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n",
@@ -2242,6 +2464,183 @@ static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
                                                &rbd_dev->header.features);
 }
 
+static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
+{
+       struct rbd_spec *parent_spec;
+       size_t size;
+       void *reply_buf = NULL;
+       __le64 snapid;
+       void *p;
+       void *end;
+       char *image_id;
+       u64 overlap;
+       size_t len = 0;
+       int ret;
+
+       parent_spec = rbd_spec_alloc();
+       if (!parent_spec)
+               return -ENOMEM;
+
+       size = sizeof (__le64) +                                /* pool_id */
+               sizeof (__le32) + RBD_IMAGE_ID_LEN_MAX +        /* image_id */
+               sizeof (__le64) +                               /* snap_id */
+               sizeof (__le64);                                /* overlap */
+       reply_buf = kmalloc(size, GFP_KERNEL);
+       if (!reply_buf) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       snapid = cpu_to_le64(CEPH_NOSNAP);
+       ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
+                               "rbd", "get_parent",
+                               (char *) &snapid, sizeof (snapid),
+                               (char *) reply_buf, size,
+                               CEPH_OSD_FLAG_READ, NULL);
+       dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
+       if (ret < 0)
+               goto out_err;
+
+       ret = -ERANGE;
+       p = reply_buf;
+       end = (char *) reply_buf + size;
+       ceph_decode_64_safe(&p, end, parent_spec->pool_id, out_err);
+       if (parent_spec->pool_id == CEPH_NOPOOL)
+               goto out;       /* No parent?  No problem. */
+
+       image_id = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL);
+       if (IS_ERR(image_id)) {
+               ret = PTR_ERR(image_id);
+               goto out_err;
+       }
+       parent_spec->image_id = image_id;
+       parent_spec->image_id_len = len;
+       ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err);
+       ceph_decode_64_safe(&p, end, overlap, out_err);
+
+       rbd_dev->parent_overlap = overlap;
+       rbd_dev->parent_spec = parent_spec;
+       parent_spec = NULL;     /* rbd_dev now owns this */
+out:
+       ret = 0;
+out_err:
+       kfree(reply_buf);
+       rbd_spec_put(parent_spec);
+
+       return ret;
+}
+
+static char *rbd_dev_image_name(struct rbd_device *rbd_dev)
+{
+       size_t image_id_size;
+       char *image_id;
+       void *p;
+       void *end;
+       size_t size;
+       void *reply_buf = NULL;
+       size_t len = 0;
+       char *image_name = NULL;
+       int ret;
+
+       rbd_assert(!rbd_dev->spec->image_name);
+
+       image_id_size = sizeof (__le32) + rbd_dev->spec->image_id_len;
+       image_id = kmalloc(image_id_size, GFP_KERNEL);
+       if (!image_id)
+               return NULL;
+
+       p = image_id;
+       end = (char *) image_id + image_id_size;
+       ceph_encode_string(&p, end, rbd_dev->spec->image_id,
+                               (u32) rbd_dev->spec->image_id_len);
+
+       size = sizeof (__le32) + RBD_IMAGE_NAME_LEN_MAX;
+       reply_buf = kmalloc(size, GFP_KERNEL);
+       if (!reply_buf)
+               goto out;
+
+       ret = rbd_req_sync_exec(rbd_dev, RBD_DIRECTORY,
+                               "rbd", "dir_get_name",
+                               image_id, image_id_size,
+                               (char *) reply_buf, size,
+                               CEPH_OSD_FLAG_READ, NULL);
+       if (ret < 0)
+               goto out;
+       p = reply_buf;
+       end = (char *) reply_buf + size;
+       image_name = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL);
+       if (IS_ERR(image_name))
+               image_name = NULL;
+       else
+               dout("%s: name is %s len is %zd\n", __func__, image_name, len);
+out:
+       kfree(reply_buf);
+       kfree(image_id);
+
+       return image_name;
+}
+
+/*
+ * When a parent image gets probed, we only have the pool, image,
+ * and snapshot ids but not the names of any of them.  This call
+ * is made later to fill in those names.  It has to be done after
+ * rbd_dev_snaps_update() has completed because some of the
+ * information (in particular, snapshot name) is not available
+ * until then.
+ */
+static int rbd_dev_probe_update_spec(struct rbd_device *rbd_dev)
+{
+       struct ceph_osd_client *osdc;
+       const char *name;
+       void *reply_buf = NULL;
+       int ret;
+
+       if (rbd_dev->spec->pool_name)
+               return 0;       /* Already have the names */
+
+       /* Look up the pool name */
+
+       osdc = &rbd_dev->rbd_client->client->osdc;
+       name = ceph_pg_pool_name_by_id(osdc->osdmap, rbd_dev->spec->pool_id);
+       if (!name)
+               return -EIO;    /* pool id too large (>= 2^31) */
+
+       rbd_dev->spec->pool_name = kstrdup(name, GFP_KERNEL);
+       if (!rbd_dev->spec->pool_name)
+               return -ENOMEM;
+
+       /* Fetch the image name; tolerate failure here */
+
+       name = rbd_dev_image_name(rbd_dev);
+       if (name) {
+               rbd_dev->spec->image_name_len = strlen(name);
+               rbd_dev->spec->image_name = (char *) name;
+       } else {
+               pr_warning(RBD_DRV_NAME "%d "
+                       "unable to get image name for image id %s\n",
+                       rbd_dev->major, rbd_dev->spec->image_id);
+       }
+
+       /* Look up the snapshot name. */
+
+       name = rbd_snap_name(rbd_dev, rbd_dev->spec->snap_id);
+       if (!name) {
+               ret = -EIO;
+               goto out_err;
+       }
+       rbd_dev->spec->snap_name = kstrdup(name, GFP_KERNEL);
+       if(!rbd_dev->spec->snap_name)
+               goto out_err;
+
+       return 0;
+out_err:
+       kfree(reply_buf);
+       kfree(rbd_dev->spec->pool_name);
+       rbd_dev->spec->pool_name = NULL;
+
+       return ret;
+}
+
 static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
 {
        size_t size;
@@ -2328,7 +2727,6 @@ static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which)
        int ret;
        void *p;
        void *end;
-       size_t snap_name_len;
        char *snap_name;
 
        size = sizeof (__le32) + RBD_MAX_SNAP_NAME_LEN;
@@ -2348,9 +2746,7 @@ static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which)
 
        p = reply_buf;
        end = (char *) reply_buf + size;
-       snap_name_len = 0;
-       snap_name = ceph_extract_encoded_string(&p, end, &snap_name_len,
-                               GFP_KERNEL);
+       snap_name = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL);
        if (IS_ERR(snap_name)) {
                ret = PTR_ERR(snap_name);
                goto out;
@@ -2397,6 +2793,41 @@ static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which,
        return ERR_PTR(-EINVAL);
 }
 
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver)
+{
+       int ret;
+       __u8 obj_order;
+
+       down_write(&rbd_dev->header_rwsem);
+
+       /* Grab old order first, to see if it changes */
+
+       obj_order = rbd_dev->header.obj_order,
+       ret = rbd_dev_v2_image_size(rbd_dev);
+       if (ret)
+               goto out;
+       if (rbd_dev->header.obj_order != obj_order) {
+               ret = -EIO;
+               goto out;
+       }
+       rbd_update_mapping_size(rbd_dev);
+
+       ret = rbd_dev_v2_snap_context(rbd_dev, hver);
+       dout("rbd_dev_v2_snap_context returned %d\n", ret);
+       if (ret)
+               goto out;
+       ret = rbd_dev_snaps_update(rbd_dev);
+       dout("rbd_dev_snaps_update returned %d\n", ret);
+       if (ret)
+               goto out;
+       ret = rbd_dev_snaps_register(rbd_dev);
+       dout("rbd_dev_snaps_register returned %d\n", ret);
+out:
+       up_write(&rbd_dev->header_rwsem);
+
+       return ret;
+}
+
 /*
  * Scan the rbd device's current snapshot list and compare it to the
  * newly-received snapshot context.  Remove any existing snapshots
@@ -2436,12 +2867,12 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev)
 
                        /* Existing snapshot not in the new snap context */
 
-                       if (rbd_dev->mapping.snap_id == snap->id)
-                               rbd_dev->mapping.snap_exists = false;
-                       __rbd_remove_snap_dev(snap);
+                       if (rbd_dev->spec->snap_id == snap->id)
+                               rbd_dev->exists = false;
+                       rbd_remove_snap_dev(snap);
                        dout("%ssnap id %llu has been removed\n",
-                               rbd_dev->mapping.snap_id == snap->id ?
-                                                               "mapped " : "",
+                               rbd_dev->spec->snap_id == snap->id ?
+                                                       "mapped " : "",
                                (unsigned long long) snap->id);
 
                        /* Done with this list entry; advance */
@@ -2559,7 +2990,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
        do {
                ret = rbd_req_sync_watch(rbd_dev);
                if (ret == -ERANGE) {
-                       rc = rbd_refresh_header(rbd_dev, NULL);
+                       rc = rbd_dev_refresh(rbd_dev, NULL);
                        if (rc < 0)
                                return rc;
                }
@@ -2621,8 +3052,8 @@ static void rbd_dev_id_put(struct rbd_device *rbd_dev)
                struct rbd_device *rbd_dev;
 
                rbd_dev = list_entry(tmp, struct rbd_device, node);
-               if (rbd_id > max_id)
-                       max_id = rbd_id;
+               if (rbd_dev->dev_id > max_id)
+                       max_id = rbd_dev->dev_id;
        }
        spin_unlock(&rbd_dev_list_lock);
 
@@ -2722,73 +3153,140 @@ static inline char *dup_token(const char **buf, size_t *lenp)
 }
 
 /*
- * This fills in the pool_name, image_name, image_name_len, rbd_dev,
- * rbd_md_name, and name fields of the given rbd_dev, based on the
- * list of monitor addresses and other options provided via
- * /sys/bus/rbd/add.  Returns a pointer to a dynamically-allocated
- * copy of the snapshot name to map if successful, or a
- * pointer-coded error otherwise.
+ * Parse the options provided for an "rbd add" (i.e., rbd image
+ * mapping) request.  These arrive via a write to /sys/bus/rbd/add,
+ * and the data written is passed here via a NUL-terminated buffer.
+ * Returns 0 if successful or an error code otherwise.
+ *
+ * The information extracted from these options is recorded in
+ * the other parameters which return dynamically-allocated
+ * structures:
+ *  ceph_opts
+ *      The address of a pointer that will refer to a ceph options
+ *      structure.  Caller must release the returned pointer using
+ *      ceph_destroy_options() when it is no longer needed.
+ *  rbd_opts
+ *     Address of an rbd options pointer.  Fully initialized by
+ *     this function; caller must release with kfree().
+ *  spec
+ *     Address of an rbd image specification pointer.  Fully
+ *     initialized by this function based on parsed options.
+ *     Caller must release with rbd_spec_put().
  *
- * Note: rbd_dev is assumed to have been initially zero-filled.
+ * The options passed take this form:
+ *  <mon_addrs> <options> <pool_name> <image_name> [<snap_id>]
+ * where:
+ *  <mon_addrs>
+ *      A comma-separated list of one or more monitor addresses.
+ *      A monitor address is an ip address, optionally followed
+ *      by a port number (separated by a colon).
+ *        I.e.:  ip1[:port1][,ip2[:port2]...]
+ *  <options>
+ *      A comma-separated list of ceph and/or rbd options.
+ *  <pool_name>
+ *      The name of the rados pool containing the rbd image.
+ *  <image_name>
+ *      The name of the image in that pool to map.
+ *  <snap_id>
+ *      An optional snapshot id.  If provided, the mapping will
+ *      present data from the image at the time that snapshot was
+ *      created.  The image head is used if no snapshot id is
+ *      provided.  Snapshot mappings are always read-only.
  */
-static char *rbd_add_parse_args(struct rbd_device *rbd_dev,
-                               const char *buf,
-                               const char **mon_addrs,
-                               size_t *mon_addrs_size,
-                               char *options,
-                               size_t options_size)
+static int rbd_add_parse_args(const char *buf,
+                               struct ceph_options **ceph_opts,
+                               struct rbd_options **opts,
+                               struct rbd_spec **rbd_spec)
 {
        size_t len;
-       char *err_ptr = ERR_PTR(-EINVAL);
-       char *snap_name;
+       char *options;
+       const char *mon_addrs;
+       size_t mon_addrs_size;
+       struct rbd_spec *spec = NULL;
+       struct rbd_options *rbd_opts = NULL;
+       struct ceph_options *copts;
+       int ret;
 
        /* The first four tokens are required */
 
        len = next_token(&buf);
        if (!len)
-               return err_ptr;
-       *mon_addrs_size = len + 1;
-       *mon_addrs = buf;
-
+               return -EINVAL; /* Missing monitor address(es) */
+       mon_addrs = buf;
+       mon_addrs_size = len + 1;
        buf += len;
 
-       len = copy_token(&buf, options, options_size);
-       if (!len || len >= options_size)
-               return err_ptr;
+       ret = -EINVAL;
+       options = dup_token(&buf, NULL);
+       if (!options)
+               return -ENOMEM;
+       if (!*options)
+               goto out_err;   /* Missing options */
 
-       err_ptr = ERR_PTR(-ENOMEM);
-       rbd_dev->pool_name = dup_token(&buf, NULL);
-       if (!rbd_dev->pool_name)
-               goto out_err;
+       spec = rbd_spec_alloc();
+       if (!spec)
+               goto out_mem;
 
-       rbd_dev->image_name = dup_token(&buf, &rbd_dev->image_name_len);
-       if (!rbd_dev->image_name)
-               goto out_err;
+       spec->pool_name = dup_token(&buf, NULL);
+       if (!spec->pool_name)
+               goto out_mem;
+       if (!*spec->pool_name)
+               goto out_err;   /* Missing pool name */
 
-       /* Snapshot name is optional */
+       spec->image_name = dup_token(&buf, &spec->image_name_len);
+       if (!spec->image_name)
+               goto out_mem;
+       if (!*spec->image_name)
+               goto out_err;   /* Missing image name */
+
+       /*
+        * Snapshot name is optional; default is to use "-"
+        * (indicating the head/no snapshot).
+        */
        len = next_token(&buf);
        if (!len) {
                buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */
                len = sizeof (RBD_SNAP_HEAD_NAME) - 1;
-       }
-       snap_name = kmalloc(len + 1, GFP_KERNEL);
-       if (!snap_name)
+       } else if (len > RBD_MAX_SNAP_NAME_LEN) {
+               ret = -ENAMETOOLONG;
                goto out_err;
-       memcpy(snap_name, buf, len);
-       *(snap_name + len) = '\0';
+       }
+       spec->snap_name = kmalloc(len + 1, GFP_KERNEL);
+       if (!spec->snap_name)
+               goto out_mem;
+       memcpy(spec->snap_name, buf, len);
+       *(spec->snap_name + len) = '\0';
 
-dout("    SNAP_NAME is <%s>, len is %zd\n", snap_name, len);
+       /* Initialize all rbd options to the defaults */
 
-       return snap_name;
+       rbd_opts = kzalloc(sizeof (*rbd_opts), GFP_KERNEL);
+       if (!rbd_opts)
+               goto out_mem;
+
+       rbd_opts->read_only = RBD_READ_ONLY_DEFAULT;
+
+       copts = ceph_parse_options(options, mon_addrs,
+                                       mon_addrs + mon_addrs_size - 1,
+                                       parse_rbd_opts_token, rbd_opts);
+       if (IS_ERR(copts)) {
+               ret = PTR_ERR(copts);
+               goto out_err;
+       }
+       kfree(options);
 
+       *ceph_opts = copts;
+       *opts = rbd_opts;
+       *rbd_spec = spec;
+
+       return 0;
+out_mem:
+       ret = -ENOMEM;
 out_err:
-       kfree(rbd_dev->image_name);
-       rbd_dev->image_name = NULL;
-       rbd_dev->image_name_len = 0;
-       kfree(rbd_dev->pool_name);
-       rbd_dev->pool_name = NULL;
+       kfree(rbd_opts);
+       rbd_spec_put(spec);
+       kfree(options);
 
-       return err_ptr;
+       return ret;
 }
 
 /*
@@ -2813,15 +3311,23 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
        void *response;
        void *p;
 
+       /*
+        * When probing a parent image, the image id is already
+        * known (and the image name likely is not).  There's no
+        * need to fetch the image id again in this case.
+        */
+       if (rbd_dev->spec->image_id)
+               return 0;
+
        /*
         * First, see if the format 2 image id file exists, and if
         * so, get the image's persistent id from it.
         */
-       size = sizeof (RBD_ID_PREFIX) + rbd_dev->image_name_len;
+       size = sizeof (RBD_ID_PREFIX) + rbd_dev->spec->image_name_len;
        object_name = kmalloc(size, GFP_NOIO);
        if (!object_name)
                return -ENOMEM;
-       sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->image_name);
+       sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->spec->image_name);
        dout("rbd id object name is %s\n", object_name);
 
        /* Response will be an encoded string, which includes a length */
@@ -2841,17 +3347,18 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
        dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
        if (ret < 0)
                goto out;
+       ret = 0;    /* rbd_req_sync_exec() can return positive */
 
        p = response;
-       rbd_dev->image_id = ceph_extract_encoded_string(&p,
+       rbd_dev->spec->image_id = ceph_extract_encoded_string(&p,
                                                p + RBD_IMAGE_ID_LEN_MAX,
-                                               &rbd_dev->image_id_len,
+                                               &rbd_dev->spec->image_id_len,
                                                GFP_NOIO);
-       if (IS_ERR(rbd_dev->image_id)) {
-               ret = PTR_ERR(rbd_dev->image_id);
-               rbd_dev->image_id = NULL;
+       if (IS_ERR(rbd_dev->spec->image_id)) {
+               ret = PTR_ERR(rbd_dev->spec->image_id);
+               rbd_dev->spec->image_id = NULL;
        } else {
-               dout("image_id is %s\n", rbd_dev->image_id);
+               dout("image_id is %s\n", rbd_dev->spec->image_id);
        }
 out:
        kfree(response);
@@ -2867,26 +3374,33 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
 
        /* Version 1 images have no id; empty string is used */
 
-       rbd_dev->image_id = kstrdup("", GFP_KERNEL);
-       if (!rbd_dev->image_id)
+       rbd_dev->spec->image_id = kstrdup("", GFP_KERNEL);
+       if (!rbd_dev->spec->image_id)
                return -ENOMEM;
-       rbd_dev->image_id_len = 0;
+       rbd_dev->spec->image_id_len = 0;
 
        /* Record the header object name for this rbd image. */
 
-       size = rbd_dev->image_name_len + sizeof (RBD_SUFFIX);
+       size = rbd_dev->spec->image_name_len + sizeof (RBD_SUFFIX);
        rbd_dev->header_name = kmalloc(size, GFP_KERNEL);
        if (!rbd_dev->header_name) {
                ret = -ENOMEM;
                goto out_err;
        }
-       sprintf(rbd_dev->header_name, "%s%s", rbd_dev->image_name, RBD_SUFFIX);
+       sprintf(rbd_dev->header_name, "%s%s",
+               rbd_dev->spec->image_name, RBD_SUFFIX);
 
        /* Populate rbd image metadata */
 
        ret = rbd_read_header(rbd_dev, &rbd_dev->header);
        if (ret < 0)
                goto out_err;
+
+       /* Version 1 images have no parent (no layering) */
+
+       rbd_dev->parent_spec = NULL;
+       rbd_dev->parent_overlap = 0;
+
        rbd_dev->image_format = 1;
 
        dout("discovered version 1 image, header name is %s\n",
@@ -2897,8 +3411,8 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
 out_err:
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
-       kfree(rbd_dev->image_id);
-       rbd_dev->image_id = NULL;
+       kfree(rbd_dev->spec->image_id);
+       rbd_dev->spec->image_id = NULL;
 
        return ret;
 }
@@ -2913,12 +3427,12 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
         * Image id was filled in by the caller.  Record the header
         * object name for this rbd image.
         */
-       size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->image_id_len;
+       size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->spec->image_id_len;
        rbd_dev->header_name = kmalloc(size, GFP_KERNEL);
        if (!rbd_dev->header_name)
                return -ENOMEM;
        sprintf(rbd_dev->header_name, "%s%s",
-                       RBD_HEADER_PREFIX, rbd_dev->image_id);
+                       RBD_HEADER_PREFIX, rbd_dev->spec->image_id);
 
        /* Get the size and object order for the image */
 
@@ -2932,12 +3446,20 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
        if (ret < 0)
                goto out_err;
 
-       /* Get the features for the image */
+       /* Get the and check features for the image */
 
        ret = rbd_dev_v2_features(rbd_dev);
        if (ret < 0)
                goto out_err;
 
+       /* If the image supports layering, get the parent info */
+
+       if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
+               ret = rbd_dev_v2_parent_info(rbd_dev);
+               if (ret < 0)
+                       goto out_err;
+       }
+
        /* crypto and compression type aren't (yet) supported for v2 images */
 
        rbd_dev->header.crypt_type = 0;
@@ -2955,8 +3477,11 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
        dout("discovered version 2 image, header name is %s\n",
                rbd_dev->header_name);
 
-       return -ENOTSUPP;
+       return 0;
 out_err:
+       rbd_dev->parent_overlap = 0;
+       rbd_spec_put(rbd_dev->parent_spec);
+       rbd_dev->parent_spec = NULL;
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
        kfree(rbd_dev->header.object_prefix);
@@ -2965,91 +3490,22 @@ out_err:
        return ret;
 }
 
-/*
- * Probe for the existence of the header object for the given rbd
- * device.  For format 2 images this includes determining the image
- * id.
- */
-static int rbd_dev_probe(struct rbd_device *rbd_dev)
+static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       /*
-        * Get the id from the image id object.  If it's not a
-        * format 2 image, we'll get ENOENT back, and we'll assume
-        * it's a format 1 image.
-        */
-       ret = rbd_dev_image_id(rbd_dev);
-       if (ret)
-               ret = rbd_dev_v1_probe(rbd_dev);
-       else
-               ret = rbd_dev_v2_probe(rbd_dev);
+       /* no need to lock here, as rbd_dev is not registered yet */
+       ret = rbd_dev_snaps_update(rbd_dev);
        if (ret)
-               dout("probe failed, returning %d\n", ret);
-
-       return ret;
-}
-
-static ssize_t rbd_add(struct bus_type *bus,
-                      const char *buf,
-                      size_t count)
-{
-       char *options;
-       struct rbd_device *rbd_dev = NULL;
-       const char *mon_addrs = NULL;
-       size_t mon_addrs_size = 0;
-       struct ceph_osd_client *osdc;
-       int rc = -ENOMEM;
-       char *snap_name;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
-
-       options = kmalloc(count, GFP_KERNEL);
-       if (!options)
-               goto err_out_mem;
-       rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL);
-       if (!rbd_dev)
-               goto err_out_mem;
-
-       /* static rbd_device initialization */
-       spin_lock_init(&rbd_dev->lock);
-       INIT_LIST_HEAD(&rbd_dev->node);
-       INIT_LIST_HEAD(&rbd_dev->snaps);
-       init_rwsem(&rbd_dev->header_rwsem);
-
-       /* parse add command */
-       snap_name = rbd_add_parse_args(rbd_dev, buf,
-                               &mon_addrs, &mon_addrs_size, options, count);
-       if (IS_ERR(snap_name)) {
-               rc = PTR_ERR(snap_name);
-               goto err_out_mem;
-       }
-
-       rc = rbd_get_client(rbd_dev, mon_addrs, mon_addrs_size - 1, options);
-       if (rc < 0)
-               goto err_out_args;
-
-       /* pick the pool */
-       osdc = &rbd_dev->rbd_client->client->osdc;
-       rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name);
-       if (rc < 0)
-               goto err_out_client;
-       rbd_dev->pool_id = rc;
-
-       rc = rbd_dev_probe(rbd_dev);
-       if (rc < 0)
-               goto err_out_client;
-       rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
+               return ret;
 
-       /* no need to lock here, as rbd_dev is not registered yet */
-       rc = rbd_dev_snaps_update(rbd_dev);
-       if (rc)
-               goto err_out_header;
+       ret = rbd_dev_probe_update_spec(rbd_dev);
+       if (ret)
+               goto err_out_snaps;
 
-       rc = rbd_dev_set_mapping(rbd_dev, snap_name);
-       if (rc)
-               goto err_out_header;
+       ret = rbd_dev_set_mapping(rbd_dev);
+       if (ret)
+               goto err_out_snaps;
 
        /* generate unique id: find highest unique id, add one */
        rbd_dev_id_get(rbd_dev);
@@ -3061,34 +3517,33 @@ static ssize_t rbd_add(struct bus_type *bus,
 
        /* Get our block major device number. */
 
-       rc = register_blkdev(0, rbd_dev->name);
-       if (rc < 0)
+       ret = register_blkdev(0, rbd_dev->name);
+       if (ret < 0)
                goto err_out_id;
-       rbd_dev->major = rc;
+       rbd_dev->major = ret;
 
        /* Set up the blkdev mapping. */
 
-       rc = rbd_init_disk(rbd_dev);
-       if (rc)
+       ret = rbd_init_disk(rbd_dev);
+       if (ret)
                goto err_out_blkdev;
 
-       rc = rbd_bus_add_dev(rbd_dev);
-       if (rc)
+       ret = rbd_bus_add_dev(rbd_dev);
+       if (ret)
                goto err_out_disk;
 
        /*
         * At this point cleanup in the event of an error is the job
         * of the sysfs code (initiated by rbd_bus_del_dev()).
         */
-
        down_write(&rbd_dev->header_rwsem);
-       rc = rbd_dev_snaps_register(rbd_dev);
+       ret = rbd_dev_snaps_register(rbd_dev);
        up_write(&rbd_dev->header_rwsem);
-       if (rc)
+       if (ret)
                goto err_out_bus;
 
-       rc = rbd_init_watch_dev(rbd_dev);
-       if (rc)
+       ret = rbd_init_watch_dev(rbd_dev);
+       if (ret)
                goto err_out_bus;
 
        /* Everything's ready.  Announce the disk to the world. */
@@ -3098,37 +3553,119 @@ static ssize_t rbd_add(struct bus_type *bus,
        pr_info("%s: added with size 0x%llx\n", rbd_dev->disk->disk_name,
                (unsigned long long) rbd_dev->mapping.size);
 
-       return count;
-
+       return ret;
 err_out_bus:
        /* this will also clean up rest of rbd_dev stuff */
 
        rbd_bus_del_dev(rbd_dev);
-       kfree(options);
-       return rc;
 
+       return ret;
 err_out_disk:
        rbd_free_disk(rbd_dev);
 err_out_blkdev:
        unregister_blkdev(rbd_dev->major, rbd_dev->name);
 err_out_id:
        rbd_dev_id_put(rbd_dev);
-err_out_header:
-       rbd_header_free(&rbd_dev->header);
+err_out_snaps:
+       rbd_remove_all_snaps(rbd_dev);
+
+       return ret;
+}
+
+/*
+ * Probe for the existence of the header object for the given rbd
+ * device.  For format 2 images this includes determining the image
+ * id.
+ */
+static int rbd_dev_probe(struct rbd_device *rbd_dev)
+{
+       int ret;
+
+       /*
+        * Get the id from the image id object.  If it's not a
+        * format 2 image, we'll get ENOENT back, and we'll assume
+        * it's a format 1 image.
+        */
+       ret = rbd_dev_image_id(rbd_dev);
+       if (ret)
+               ret = rbd_dev_v1_probe(rbd_dev);
+       else
+               ret = rbd_dev_v2_probe(rbd_dev);
+       if (ret) {
+               dout("probe failed, returning %d\n", ret);
+
+               return ret;
+       }
+
+       ret = rbd_dev_probe_finish(rbd_dev);
+       if (ret)
+               rbd_header_free(&rbd_dev->header);
+
+       return ret;
+}
+
+static ssize_t rbd_add(struct bus_type *bus,
+                      const char *buf,
+                      size_t count)
+{
+       struct rbd_device *rbd_dev = NULL;
+       struct ceph_options *ceph_opts = NULL;
+       struct rbd_options *rbd_opts = NULL;
+       struct rbd_spec *spec = NULL;
+       struct rbd_client *rbdc;
+       struct ceph_osd_client *osdc;
+       int rc = -ENOMEM;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       /* parse add command */
+       rc = rbd_add_parse_args(buf, &ceph_opts, &rbd_opts, &spec);
+       if (rc < 0)
+               goto err_out_module;
+
+       rbdc = rbd_get_client(ceph_opts);
+       if (IS_ERR(rbdc)) {
+               rc = PTR_ERR(rbdc);
+               goto err_out_args;
+       }
+       ceph_opts = NULL;       /* rbd_dev client now owns this */
+
+       /* pick the pool */
+       osdc = &rbdc->client->osdc;
+       rc = ceph_pg_poolid_by_name(osdc->osdmap, spec->pool_name);
+       if (rc < 0)
+               goto err_out_client;
+       spec->pool_id = (u64) rc;
+
+       rbd_dev = rbd_dev_create(rbdc, spec);
+       if (!rbd_dev)
+               goto err_out_client;
+       rbdc = NULL;            /* rbd_dev now owns this */
+       spec = NULL;            /* rbd_dev now owns this */
+
+       rbd_dev->mapping.read_only = rbd_opts->read_only;
+       kfree(rbd_opts);
+       rbd_opts = NULL;        /* done with this */
+
+       rc = rbd_dev_probe(rbd_dev);
+       if (rc < 0)
+               goto err_out_rbd_dev;
+
+       return count;
+err_out_rbd_dev:
+       rbd_dev_destroy(rbd_dev);
 err_out_client:
-       kfree(rbd_dev->header_name);
-       rbd_put_client(rbd_dev);
-       kfree(rbd_dev->image_id);
+       rbd_put_client(rbdc);
 err_out_args:
-       kfree(rbd_dev->mapping.snap_name);
-       kfree(rbd_dev->image_name);
-       kfree(rbd_dev->pool_name);
-err_out_mem:
-       kfree(rbd_dev);
-       kfree(options);
+       if (ceph_opts)
+               ceph_destroy_options(ceph_opts);
+       kfree(rbd_opts);
+       rbd_spec_put(spec);
+err_out_module:
+       module_put(THIS_MODULE);
 
        dout("Error adding device %s\n", buf);
-       module_put(THIS_MODULE);
 
        return (ssize_t) rc;
 }
@@ -3163,7 +3700,6 @@ static void rbd_dev_release(struct device *dev)
        if (rbd_dev->watch_event)
                rbd_req_sync_unwatch(rbd_dev);
 
-       rbd_put_client(rbd_dev);
 
        /* clean up and free blkdev */
        rbd_free_disk(rbd_dev);
@@ -3173,13 +3709,9 @@ static void rbd_dev_release(struct device *dev)
        rbd_header_free(&rbd_dev->header);
 
        /* done with the id, and with the rbd_dev */
-       kfree(rbd_dev->mapping.snap_name);
-       kfree(rbd_dev->image_id);
-       kfree(rbd_dev->header_name);
-       kfree(rbd_dev->pool_name);
-       kfree(rbd_dev->image_name);
        rbd_dev_id_put(rbd_dev);
-       kfree(rbd_dev);
+       rbd_assert(rbd_dev->rbd_client != NULL);
+       rbd_dev_destroy(rbd_dev);
 
        /* release module ref */
        module_put(THIS_MODULE);
@@ -3211,7 +3743,12 @@ static ssize_t rbd_remove(struct bus_type *bus,
                goto done;
        }
 
-       __rbd_remove_all_snaps(rbd_dev);
+       if (rbd_dev->open_count) {
+               ret = -EBUSY;
+               goto done;
+       }
+
+       rbd_remove_all_snaps(rbd_dev);
        rbd_bus_del_dev(rbd_dev);
 
 done:
index cbe77fa105baace065c8714c348c3cf782391b78..49d77cbcf8bdb0601ac9db5f1ad80309a80cb32e 100644 (file)
@@ -46,8 +46,6 @@
 #define RBD_MIN_OBJ_ORDER       16
 #define RBD_MAX_OBJ_ORDER       30
 
-#define RBD_MAX_SEG_NAME_LEN   128
-
 #define RBD_COMP_NONE          0
 #define RBD_CRYPT_NONE         0
 
index 9dcf76a10bb64584b2d43bfbcc4d06a735711f43..5814deb6963d52a875708e78a4a3a38eb148145e 100644 (file)
@@ -25,7 +25,7 @@
 #define DRV_MODULE_VERSION     "1.0"
 #define DRV_MODULE_RELDATE     "June 25, 2007"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
@@ -461,7 +461,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
        int op_len, err;
        void *req_buf;
 
-       if (!(((u64)1 << ((u64)op - 1)) & port->operations))
+       if (!(((u64)1 << (u64)op) & port->operations))
                return -EOPNOTSUPP;
 
        switch (op) {
@@ -592,7 +592,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
        return err;
 }
 
-static int __devinit vdc_alloc_tx_ring(struct vdc_port *port)
+static int vdc_alloc_tx_ring(struct vdc_port *port)
 {
        struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
        unsigned long len, entry_size;
@@ -725,7 +725,7 @@ static struct vio_driver_ops vdc_vio_ops = {
        .handshake_complete     = vdc_handshake_complete,
 };
 
-static void __devinit print_version(void)
+static void print_version(void)
 {
        static int version_printed;
 
@@ -733,8 +733,7 @@ static void __devinit print_version(void)
                printk(KERN_INFO "%s", version);
 }
 
-static int __devinit vdc_port_probe(struct vio_dev *vdev,
-                                   const struct vio_device_id *id)
+static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 {
        struct mdesc_handle *hp;
        struct vdc_port *port;
index 6d5a914b9619c98a12475222d0bc75be80e603ee..765fa2b3d33763449bd8f322f2183b456e1bca5f 100644 (file)
@@ -788,8 +788,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
        return get_disk(swd->unit[drive].disk);
 }
 
-static int __devinit swim_add_floppy(struct swim_priv *swd,
-                                    enum drive_location location)
+static int swim_add_floppy(struct swim_priv *swd, enum drive_location location)
 {
        struct floppy_state *fs = &swd->unit[swd->floppy_count];
        struct swim __iomem *base = swd->base;
@@ -812,7 +811,7 @@ static int __devinit swim_add_floppy(struct swim_priv *swd,
        return 0;
 }
 
-static int __devinit swim_floppy_init(struct swim_priv *swd)
+static int swim_floppy_init(struct swim_priv *swd)
 {
        int err;
        int drive;
@@ -875,7 +874,7 @@ exit_put_disks:
        return err;
 }
 
-static int __devinit swim_probe(struct platform_device *dev)
+static int swim_probe(struct platform_device *dev)
 {
        struct resource *res;
        struct swim __iomem *swim_base;
@@ -936,7 +935,7 @@ out:
        return ret;
 }
 
-static int __devexit swim_remove(struct platform_device *dev)
+static int swim_remove(struct platform_device *dev)
 {
        struct swim_priv *swd = platform_get_drvdata(dev);
        int drive;
@@ -972,7 +971,7 @@ static int __devexit swim_remove(struct platform_device *dev)
 
 static struct platform_driver swim_driver = {
        .probe  = swim_probe,
-       .remove = __devexit_p(swim_remove),
+       .remove = swim_remove,
        .driver   = {
                .name   = CARDNAME,
                .owner  = THIS_MODULE,
index 89ddab127e33df525924b73f23501fc9fcab1006..57763c54363aaf18a03f44464c7496f1c0fd4232 100644 (file)
@@ -1194,7 +1194,8 @@ static int swim3_add_device(struct macio_dev *mdev, int index)
        return rc;
 }
 
-static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match)
+static int swim3_attach(struct macio_dev *mdev,
+                       const struct of_device_id *match)
 {
        struct gendisk *disk;
        int index, rc;
index eb0d8216f557434b36e6fbc809b75c33bbbc1292..ad70868f8a967b40bc866bc5430387b55f4601ac 100644 (file)
@@ -789,8 +789,7 @@ static const struct block_device_operations mm_fops = {
        .revalidate_disk = mm_revalidate,
 };
 
-static int __devinit mm_pci_probe(struct pci_dev *dev,
-                               const struct pci_device_id *id)
+static int mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int ret = -ENODEV;
        struct cardinfo *card = &cards[num_cards];
index 0bdde8fba3970d81010736f3a1b4bf5f9fb53a07..8ad21a25bc0d92cc80f48f69f4556bdcc6ef6fa2 100644 (file)
@@ -696,7 +696,7 @@ static const struct device_attribute dev_attr_cache_type_rw =
        __ATTR(cache_type, S_IRUGO|S_IWUSR,
               virtblk_cache_type_show, virtblk_cache_type_store);
 
-static int __devinit virtblk_probe(struct virtio_device *vdev)
+static int virtblk_probe(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk;
        struct request_queue *q;
@@ -885,10 +885,11 @@ out:
        return err;
 }
 
-static void __devexit virtblk_remove(struct virtio_device *vdev)
+static void virtblk_remove(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk = vdev->priv;
        int index = vblk->index;
+       int refc;
 
        /* Prevent config work handler from accessing the device. */
        mutex_lock(&vblk->config_lock);
@@ -903,11 +904,15 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
 
        flush_work(&vblk->config_work);
 
+       refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
        put_disk(vblk->disk);
        mempool_destroy(vblk->pool);
        vdev->config->del_vqs(vdev);
        kfree(vblk);
-       ida_simple_remove(&vd_index_ida, index);
+
+       /* Only free device id if we don't have any users */
+       if (refc == 1)
+               ida_simple_remove(&vd_index_ida, index);
 }
 
 #ifdef CONFIG_PM
@@ -961,19 +966,14 @@ static unsigned int features[] = {
        VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
 };
 
-/*
- * virtio_blk causes spurious section mismatch warning by
- * simultaneously referring to a __devinit and a __devexit function.
- * Use __refdata to avoid this warning.
- */
-static struct virtio_driver __refdata virtio_blk = {
+static struct virtio_driver virtio_blk = {
        .feature_table          = features,
        .feature_table_size     = ARRAY_SIZE(features),
        .driver.name            = KBUILD_MODNAME,
        .driver.owner           = THIS_MODULE,
        .id_table               = id_table,
        .probe                  = virtblk_probe,
-       .remove                 = __devexit_p(virtblk_remove),
+       .remove                 = virtblk_remove,
        .config_changed         = virtblk_config_changed,
 #ifdef CONFIG_PM
        .freeze                 = virtblk_freeze,
index 74374fb762aa5bcf835e73a7390f12b7403525ee..5ac841ff6cc73acd59c7439722ab799a27fac93b 100644 (file)
@@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
 static void make_response(struct xen_blkif *blkif, u64 id,
                          unsigned short op, int st);
 
-#define foreach_grant(pos, rbtree, node) \
-       for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \
+#define foreach_grant_safe(pos, n, rbtree, node) \
+       for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
+            (n) = rb_next(&(pos)->node); \
             &(pos)->node != NULL; \
-            (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node))
+            (pos) = container_of(n, typeof(*(pos)), node), \
+            (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
 
 
 static void add_persistent_gnt(struct rb_root *root,
@@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
        struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct persistent_gnt *persistent_gnt;
+       struct rb_node *n;
        int ret = 0;
        int segs_to_unmap = 0;
 
-       foreach_grant(persistent_gnt, root, node) {
+       foreach_grant_safe(persistent_gnt, n, root, node) {
                BUG_ON(persistent_gnt->handle ==
                        BLKBACK_INVALID_HANDLE);
                gnttab_set_unmap_op(&unmap[segs_to_unmap],
@@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
                        persistent_gnt->handle);
 
                pages[segs_to_unmap] = persistent_gnt->page;
-               rb_erase(&persistent_gnt->node, root);
-               kfree(persistent_gnt);
-               num--;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
                        !rb_next(&persistent_gnt->node)) {
@@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
                        BUG_ON(ret);
                        segs_to_unmap = 0;
                }
+
+               rb_erase(&persistent_gnt->node, root);
+               kfree(persistent_gnt);
+               num--;
        }
        BUG_ON(num != 0);
 }
index 96e9b00db08118a164d03845df86139169e78f71..11043c18ac5ab01fcfd2e492fff70a87260143fd 100644 (file)
@@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 {
        struct llist_node *all_gnts;
        struct grant *persistent_gnt;
+       struct llist_node *n;
 
        /* Prevent new requests being issued until we fix things up. */
        spin_lock_irq(&info->io_lock);
@@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
        /* Remove all persistent grants */
        if (info->persistent_gnts_c) {
                all_gnts = llist_del_all(&info->persistent_gnts);
-               llist_for_each_entry(persistent_gnt, all_gnts, node) {
+               llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) {
                        gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
                        __free_page(pfn_to_page(persistent_gnt->pfn));
                        kfree(persistent_gnt);
@@ -835,7 +836,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                             struct blkif_response *bret)
 {
-       int i;
+       int i = 0;
        struct bio_vec *bvec;
        struct req_iterator iter;
        unsigned long flags;
@@ -852,7 +853,8 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                 */
                rq_for_each_segment(bvec, s->request, iter) {
                        BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE);
-                       i = offset >> PAGE_SHIFT;
+                       if (bvec->bv_offset < offset)
+                               i++;
                        BUG_ON(i >= s->req.u.rw.nr_segments);
                        shared_data = kmap_atomic(
                                pfn_to_page(s->grants_used[i]->pfn));
@@ -861,7 +863,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                                bvec->bv_len);
                        bvec_kunmap_irq(bvec_data, &flags);
                        kunmap_atomic(shared_data);
-                       offset += bvec->bv_len;
+                       offset = bvec->bv_offset + bvec->bv_len;
                }
        }
        /* Add the persistent grant into the list of free grants */
index 1a17e338735e363b3ebdf7624aca334d507144c9..1f38643173caa3968f6f1b53f778a2a4f24411fc 100644 (file)
@@ -961,7 +961,7 @@ static const struct block_device_operations ace_fops = {
 /* --------------------------------------------------------------------
  * SystemACE device setup/teardown code
  */
-static int __devinit ace_setup(struct ace_device *ace)
+static int ace_setup(struct ace_device *ace)
 {
        u16 version;
        u16 val;
@@ -1074,7 +1074,7 @@ err_ioremap:
        return -ENOMEM;
 }
 
-static void __devexit ace_teardown(struct ace_device *ace)
+static void ace_teardown(struct ace_device *ace)
 {
        if (ace->gd) {
                del_gendisk(ace->gd);
@@ -1092,9 +1092,8 @@ static void __devexit ace_teardown(struct ace_device *ace)
        iounmap(ace->baseaddr);
 }
 
-static int __devinit
-ace_alloc(struct device *dev, int id, resource_size_t physaddr,
-         int irq, int bus_width)
+static int ace_alloc(struct device *dev, int id, resource_size_t physaddr,
+                    int irq, int bus_width)
 {
        struct ace_device *ace;
        int rc;
@@ -1135,7 +1134,7 @@ err_noreg:
        return rc;
 }
 
-static void __devexit ace_free(struct device *dev)
+static void ace_free(struct device *dev)
 {
        struct ace_device *ace = dev_get_drvdata(dev);
        dev_dbg(dev, "ace_free(%p)\n", dev);
@@ -1151,7 +1150,7 @@ static void __devexit ace_free(struct device *dev)
  * Platform Bus Support
  */
 
-static int __devinit ace_probe(struct platform_device *dev)
+static int ace_probe(struct platform_device *dev)
 {
        resource_size_t physaddr = 0;
        int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
@@ -1182,7 +1181,7 @@ static int __devinit ace_probe(struct platform_device *dev)
 /*
  * Platform bus remove() method
  */
-static int __devexit ace_remove(struct platform_device *dev)
+static int ace_remove(struct platform_device *dev)
 {
        ace_free(&dev->dev);
        return 0;
@@ -1190,7 +1189,7 @@ static int __devexit ace_remove(struct platform_device *dev)
 
 #if defined(CONFIG_OF)
 /* Match table for of_platform binding */
-static const struct of_device_id ace_of_match[] __devinitconst = {
+static const struct of_device_id ace_of_match[] = {
        { .compatible = "xlnx,opb-sysace-1.00.b", },
        { .compatible = "xlnx,opb-sysace-1.00.c", },
        { .compatible = "xlnx,xps-sysace-1.00.a", },
@@ -1204,7 +1203,7 @@ MODULE_DEVICE_TABLE(of, ace_of_match);
 
 static struct platform_driver ace_platform_driver = {
        .probe = ace_probe,
-       .remove = __devexit_p(ace_remove),
+       .remove = ace_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = "xsysace",
index b00000e8aef6f9cb06955049d3fa4faaba25e38b..33c9a44a967899ac5b46e9b3e9951b2e80ff164d 100644 (file)
@@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0x311D) },
        { USB_DEVICE(0x13d3, 0x3375) },
        { USB_DEVICE(0x04CA, 0x3005) },
+       { USB_DEVICE(0x04CA, 0x3006) },
+       { USB_DEVICE(0x04CA, 0x3008) },
        { USB_DEVICE(0x13d3, 0x3362) },
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0930, 0x0219) },
        { USB_DEVICE(0x0489, 0xe057) },
+       { USB_DEVICE(0x13d3, 0x3393) },
+       { USB_DEVICE(0x0489, 0xe04e) },
+       { USB_DEVICE(0x0489, 0xe056) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -104,10 +109,15 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
index a1d4ede5b892d4516b294f91aca91633864e7d43..7e351e345476c1bcc2141f95e41fe43a3e65e612 100644 (file)
@@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
index 0c48b0e05ed6e7165a221399822e894e09c9fa18..fe7191663bbde4bdafdb3d2097af30de450059b9 100644 (file)
@@ -52,7 +52,7 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
        return 0;
 }
 
-static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
+static int omap_ocp2scp_probe(struct platform_device *pdev)
 {
        int ret;
        unsigned res_cnt, i;
@@ -116,7 +116,7 @@ err0:
        return ret;
 }
 
-static int __devexit omap_ocp2scp_remove(struct platform_device *pdev)
+static int omap_ocp2scp_remove(struct platform_device *pdev)
 {
        pm_runtime_disable(&pdev->dev);
        device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
@@ -134,7 +134,7 @@ MODULE_DEVICE_TABLE(of, omap_ocp2scp_id_table);
 
 static struct platform_driver omap_ocp2scp_driver = {
        .probe          = omap_ocp2scp_probe,
-       .remove         = __devexit_p(omap_ocp2scp_remove),
+       .remove         = omap_ocp2scp_remove,
        .driver         = {
                .name   = "omap-ocp2scp",
                .owner  = THIS_MODULE,
index ab911a33f8a894a9ea06d04428e4db3b50d7c342..feeecae623f66721a734f524e9fcf8fd0511a5f4 100644 (file)
@@ -128,7 +128,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
        return IRQ_HANDLED;
 }
 
-static int __devinit omap4_l3_probe(struct platform_device *pdev)
+static int omap4_l3_probe(struct platform_device *pdev)
 {
        static struct omap4_l3 *l3;
        struct resource *res;
@@ -219,7 +219,7 @@ err0:
        return ret;
 }
 
-static int __devexit omap4_l3_remove(struct platform_device *pdev)
+static int omap4_l3_remove(struct platform_device *pdev)
 {
        struct omap4_l3 *l3 = platform_get_drvdata(pdev);
 
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, l3_noc_match);
 
 static struct platform_driver omap4_l3_driver = {
        .probe          = omap4_l3_probe,
-       .remove         = __devexit_p(omap4_l3_remove),
+       .remove         = omap4_l3_remove,
        .driver         = {
                .name           = "omap_l3_noc",
                .owner          = THIS_MODULE,
index 75d485afe56c7bf685e4f83e76473ca3516a6f54..d59cdcb8fe399b43c714370c1a5a3cb68cbed91d 100644 (file)
@@ -557,7 +557,7 @@ static irqreturn_t gdrom_dma_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit gdrom_set_interrupt_handlers(void)
+static int gdrom_set_interrupt_handlers(void)
 {
        int err;
 
@@ -681,7 +681,7 @@ static void gdrom_request(struct request_queue *rq)
 }
 
 /* Print string identifying GD ROM device */
-static int __devinit gdrom_outputversion(void)
+static int gdrom_outputversion(void)
 {
        struct gdrom_id *id;
        char *model_name, *manuf_name, *firmw_ver;
@@ -715,7 +715,7 @@ free_id:
 }
 
 /* set the default mode for DMA transfer */
-static int __devinit gdrom_init_dma_mode(void)
+static int gdrom_init_dma_mode(void)
 {
        __raw_writeb(0x13, GDROM_ERROR_REG);
        __raw_writeb(0x22, GDROM_INTSEC_REG);
@@ -736,7 +736,7 @@ static int __devinit gdrom_init_dma_mode(void)
        return 0;
 }
 
-static void __devinit probe_gdrom_setupcd(void)
+static void probe_gdrom_setupcd(void)
 {
        gd.cd_info->ops = &gdrom_ops;
        gd.cd_info->capacity = 1;
@@ -745,7 +745,7 @@ static void __devinit probe_gdrom_setupcd(void)
                CDC_SELECT_DISC;
 }
 
-static void __devinit probe_gdrom_setupdisk(void)
+static void probe_gdrom_setupdisk(void)
 {
        gd.disk->major = gdrom_major;
        gd.disk->first_minor = 1;
@@ -753,7 +753,7 @@ static void __devinit probe_gdrom_setupdisk(void)
        strcpy(gd.disk->disk_name, GDROM_DEV_NAME);
 }
 
-static int __devinit probe_gdrom_setupqueue(void)
+static int probe_gdrom_setupqueue(void)
 {
        blk_queue_logical_block_size(gd.gdrom_rq, GDROM_HARD_SECTOR);
        /* using DMA so memory will need to be contiguous */
@@ -768,7 +768,7 @@ static int __devinit probe_gdrom_setupqueue(void)
  * register this as a block device and as compliant with the
  * universal CD Rom driver interface
  */
-static int __devinit probe_gdrom(struct platform_device *devptr)
+static int probe_gdrom(struct platform_device *devptr)
 {
        int err;
        /* Start the device */
@@ -838,7 +838,7 @@ probe_fail_no_mem:
        return err;
 }
 
-static int __devexit remove_gdrom(struct platform_device *devptr)
+static int remove_gdrom(struct platform_device *devptr)
 {
        flush_work(&work);
        blk_cleanup_queue(gd.gdrom_rq);
@@ -854,7 +854,7 @@ static int __devexit remove_gdrom(struct platform_device *devptr)
 
 static struct platform_driver gdrom_driver = {
        .probe = probe_gdrom,
-       .remove = __devexit_p(remove_gdrom),
+       .remove = remove_gdrom,
        .driver = {
                        .name = GDROM_DEV_NAME,
        },
index 478493543b32391a8f520c84c223851c50304cfd..443cd6751ca21f3fe9ff985f77ace62112d43d8e 100644 (file)
@@ -299,8 +299,7 @@ static struct agp_device_ids ali_agp_device_ids[] =
        { }, /* dummy final entry, always present */
 };
 
-static int __devinit agp_ali_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct agp_device_ids *devs = ali_agp_device_ids;
        struct agp_bridge_data *bridge;
index 1b2101160e98ce9550c7ad833b0a5f25e08b6259..779f0ab845a949063ffc578dd31d7a758b7c0482 100644 (file)
@@ -405,8 +405,8 @@ static struct agp_device_ids amd_agp_device_ids[] =
        { }, /* dummy final entry, always present */
 };
 
-static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int agp_amdk7_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
index 061d46209b1a97422449cb4d9d1b65abf3437277..d79d692d05b8f3c4a2d87e3422569ef084f365f8 100644 (file)
@@ -240,7 +240,7 @@ static const struct agp_bridge_driver amd_8151_driver = {
 };
 
 /* Some basic sanity checks for the aperture. */
-static int __devinit agp_aperture_valid(u64 aper, u32 size)
+static int agp_aperture_valid(u64 aper, u32 size)
 {
        if (!aperture_valid(aper, size, 32*1024*1024))
                return 0;
@@ -267,8 +267,7 @@ static int __devinit agp_aperture_valid(u64 aper, u32 size)
  * to allocate that much memory. But at least error out cleanly instead of
  * crashing.
  */
-static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
-                                                                u16 cap)
+static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap)
 {
        u32 aper_low, aper_hi;
        u64 aper, nb_aper;
@@ -326,7 +325,7 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
        return 0;
 }
 
-static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
+static int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
 {
        int i;
 
@@ -352,7 +351,7 @@ static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
 }
 
 /* Handle AMD 8151 quirks */
-static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
+static void amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
 {
        char *revstring;
 
@@ -390,7 +389,7 @@ static const struct aper_size_info_32 uli_sizes[7] =
        {8, 2048, 1, 4},
        {4, 1024, 0, 3}
 };
-static int __devinit uli_agp_init(struct pci_dev *pdev)
+static int uli_agp_init(struct pci_dev *pdev)
 {
        u32 httfea,baseaddr,enuscr;
        struct pci_dev *dev1;
@@ -513,8 +512,8 @@ put:
        return ret;
 }
 
-static int __devinit agp_amd64_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int agp_amd64_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
index ed0433576e74e8cde3ce8caff0919bb6e704b58d..0628d7b65c71c4073d2ff1428a2e7dfad4b5d720 100644 (file)
@@ -490,8 +490,7 @@ static struct agp_device_ids ati_agp_device_ids[] =
        { }, /* dummy final entry, always present */
 };
 
-static int __devinit agp_ati_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct agp_device_ids *devs = ati_agp_device_ids;
        struct agp_bridge_data *bridge;
index 55f3e33a309fbc03f191ca640fa309dc6b798fa8..6974d50320532af7280bbd8ea9b593998c435f6d 100644 (file)
@@ -343,8 +343,8 @@ static const struct agp_bridge_driver efficeon_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int agp_efficeon_probe(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
index d328b662e50da33f4c1ed57c10257a55033319af..15b240ea4848f1b83e9f4c816ed381e11c175ee4 100644 (file)
@@ -587,8 +587,8 @@ const struct agp_bridge_driver intel_i460_driver = {
        .cant_use_aperture      = true,
 };
 
-static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
-                                         const struct pci_device_id *ent)
+static int agp_intel_i460_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
@@ -637,7 +637,7 @@ static struct pci_driver agp_intel_i460_pci_driver = {
        .name           = "agpgart-intel-i460",
        .id_table       = agp_intel_i460_pci_table,
        .probe          = agp_intel_i460_probe,
-       .remove         = __devexit_p(agp_intel_i460_remove),
+       .remove         = agp_intel_i460_remove,
 };
 
 static int __init agp_intel_i460_init(void)
index f3a8f52b5a00eabebc4f6d338155c7c92c591530..a426ee1f57a6fd71b30fbd80429cac7c97aa1b4c 100644 (file)
@@ -732,8 +732,8 @@ static const struct intel_agp_driver_description {
        { 0, NULL, NULL }
 };
 
-static int __devinit agp_intel_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int agp_intel_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr = 0;
@@ -912,7 +912,7 @@ static struct pci_driver agp_intel_pci_driver = {
        .name           = "agpgart-intel",
        .id_table       = agp_intel_pci_table,
        .probe          = agp_intel_probe,
-       .remove         = __devexit_p(agp_intel_remove),
+       .remove         = agp_intel_remove,
 #ifdef CONFIG_PM
        .resume         = agp_intel_resume,
 #endif
index 66e0868000f4fb1441e80ea5176407941bf21a8d..62be3ec0da4b1ae6f8f9cb9f05f6b0fb1eed2740 100644 (file)
@@ -332,8 +332,8 @@ static const struct agp_bridge_driver nvidia_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int agp_nvidia_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
index a18791d7718a9d1bcc3e5512b161275c481e0b15..05b8d0241bdefe2df440bf7637f37efe7ee367df 100644 (file)
@@ -270,7 +270,7 @@ const struct agp_bridge_driver sgi_tioca_driver = {
        .num_aperture_sizes = 1,
 };
 
-static int __devinit agp_sgi_init(void)
+static int agp_sgi_init(void)
 {
        unsigned int j;
        struct tioca_kernel *info;
index 93d1d31f9d0cf2f7a7811c6994aff22bc5dec9f5..79c838c434bc89806a81ee0d260f5acce9a5a3b6 100644 (file)
@@ -154,7 +154,7 @@ static int sis_broken_chipsets[] = {
        0 // terminator
 };
 
-static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
+static void sis_get_driver(struct agp_bridge_data *bridge)
 {
        int i;
 
@@ -180,8 +180,7 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
 }
 
 
-static int __devinit agp_sis_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
index 26020fb8d7a992b3daae19b5bf8b72922bee698a..9b163b49d976323fae9828f963f5e593031ffb68 100644 (file)
@@ -445,8 +445,8 @@ static const struct agp_bridge_driver sworks_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
-                                          const struct pci_device_id *ent)
+static int agp_serverworks_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
 {
        struct agp_bridge_data *bridge;
        struct pci_dev *bridge_dev;
index 011967ad3eedfb7a447261ed0c1e9150ab8b8c12..a56ee9bedd112ddeea5551ba922a7d767ab7cd3b 100644 (file)
@@ -592,8 +592,8 @@ static struct agp_device_ids uninorth_agp_device_ids[] = {
        },
 };
 
-static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
+static int agp_uninorth_probe(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        struct agp_device_ids *devs = uninorth_agp_device_ids;
        struct agp_bridge_data *bridge;
index 6818595bb863d6f3e8f1a8c2d10d21718fdcc791..74d3aa3773bf2b3300a7d3212607cca16c8d7277 100644 (file)
@@ -438,8 +438,7 @@ static void check_via_agp3 (struct agp_bridge_data *bridge)
 }
 
 
-static int __devinit agp_via_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct agp_device_ids *devs = via_agp_device_ids;
        struct agp_bridge_data *bridge;
index 5a4a6e70478b469418ad5d5da36eebc640de0f2a..7c73d4aca36b146f569682c04e65b9cacd72c4d7 100644 (file)
@@ -138,7 +138,7 @@ static const struct dev_pm_ops atmel_trng_pm_ops = {
 
 static struct platform_driver atmel_trng_driver = {
        .probe          = atmel_trng_probe,
-       .remove         = __devexit_p(atmel_trng_remove),
+       .remove         = atmel_trng_remove,
        .driver         = {
                .name   = "atmel-trng",
                .owner  = THIS_MODULE,
index ae95bcb18d4a8390d9c0cdd99047ddabb982c097..f343b7d0dfa1047c24319be8f447e4f90deaea2d 100644 (file)
@@ -61,7 +61,7 @@ static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data)
        return 4;
 }
 
-static int __devinit bcm63xx_rng_probe(struct platform_device *pdev)
+static int bcm63xx_rng_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct clk *clk;
@@ -161,7 +161,7 @@ static int bcm63xx_rng_remove(struct platform_device *pdev)
 
 static struct platform_driver bcm63xx_rng_driver = {
        .probe          = bcm63xx_rng_probe,
-       .remove         = __devexit_p(bcm63xx_rng_remove),
+       .remove         = bcm63xx_rng_remove,
        .driver         = {
                .name   = "bcm63xx-rng",
                .owner  = THIS_MODULE,
index bdc852ea76323772743fe4972b5bc532dbc23144..48bbfeca4b5de82a870eae679c59e0d8baca4751 100644 (file)
@@ -101,7 +101,7 @@ static int exynos_read(struct hwrng *rng, void *buf,
        return 4;
 }
 
-static int __devinit exynos_rng_probe(struct platform_device *pdev)
+static int exynos_rng_probe(struct platform_device *pdev)
 {
        struct exynos_rng *exynos_rng;
 
@@ -172,7 +172,7 @@ static struct platform_driver exynos_rng_driver = {
                .pm     = &exynos_rng_pm_ops,
        },
        .probe          = exynos_rng_probe,
-       .remove         = __devexit_p(exynos_rng_remove),
+       .remove         = exynos_rng_remove,
 };
 
 module_platform_driver(exynos_rng_driver);
index d68a72a08b5128d9ac175b4338c6bb2aaccd018e..20b962e1d83265fdb6ff8504179a7948894164fb 100644 (file)
@@ -611,7 +611,7 @@ static void n2rng_work(struct work_struct *work)
                schedule_delayed_work(&np->work, HZ * 2);
 }
 
-static void __devinit n2rng_driver_version(void)
+static void n2rng_driver_version(void)
 {
        static int n2rng_version_printed;
 
@@ -620,7 +620,7 @@ static void __devinit n2rng_driver_version(void)
 }
 
 static const struct of_device_id n2rng_match[];
-static int __devinit n2rng_probe(struct platform_device *op)
+static int n2rng_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
        int multi_capable;
@@ -767,7 +767,7 @@ static struct platform_driver n2rng_driver = {
                .of_match_table = n2rng_match,
        },
        .probe          = n2rng_probe,
-       .remove         = __devexit_p(n2rng_remove),
+       .remove         = n2rng_remove,
 };
 
 module_platform_driver(n2rng_driver);
index 5c34c092af711cd9c92705b745726ad9fac3f6cd..1eada566ca701f02468f7400b7cc8221e1a91a7f 100644 (file)
@@ -56,7 +56,7 @@ static int octeon_rng_data_read(struct hwrng *rng, u32 *data)
        return sizeof(u32);
 }
 
-static int __devinit octeon_rng_probe(struct platform_device *pdev)
+static int octeon_rng_probe(struct platform_device *pdev)
 {
        struct resource *res_ports;
        struct resource *res_result;
index 45e467dcc8c886996966a2488c148b68d7f792b2..d8c54e253761c5e2025c2e3941868b7e282eb8b3 100644 (file)
@@ -104,7 +104,7 @@ static struct hwrng omap_rng_ops = {
        .data_read      = omap_rng_data_read,
 };
 
-static int __devinit omap_rng_probe(struct platform_device *pdev)
+static int omap_rng_probe(struct platform_device *pdev)
 {
        struct omap_rng_private_data *priv;
        int ret;
index a1f70407cc9e03070cd627230726b4246602e986..c6df5b29af08f7f7ba99f6439b0d5d6f120379c7 100644 (file)
@@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = {
        .data_read      = pasemi_rng_data_read,
 };
 
-static int __devinit rng_probe(struct platform_device *ofdev)
+static int rng_probe(struct platform_device *ofdev)
 {
        void __iomem *rng_regs;
        struct device_node *rng_np = ofdev->dev.of_node;
index d4b24c1dd48e37e4077ca01b56bf191b35bc6990..973b95113edf7580e09bcb078db0038c047dd7f6 100644 (file)
@@ -181,7 +181,7 @@ static const struct dev_pm_ops picoxcell_trng_pm_ops = {
 
 static struct platform_driver picoxcell_trng_driver = {
        .probe          = picoxcell_trng_probe,
-       .remove         = __devexit_p(picoxcell_trng_remove),
+       .remove         = picoxcell_trng_remove,
        .driver         = {
                .name   = "picoxcell-trng",
                .owner  = THIS_MODULE,
index af6506a69cd9473343538d48bf17cb32a9877e92..732c330805fd318451be8e3654c484bed6416de8 100644 (file)
@@ -90,7 +90,7 @@ static struct hwrng ppc4xx_rng = {
        .data_read = ppc4xx_rng_data_read,
 };
 
-static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
+static int ppc4xx_rng_probe(struct platform_device *dev)
 {
        void __iomem *rng_regs;
        int err = 0;
index 3a1abc9417e4e8fd3e86628f75d4e3d71521fea7..849db199c02c1f363a17848b2ca428a9e3b724ad 100644 (file)
@@ -88,7 +88,7 @@ static struct hwrng timeriomem_rng_ops = {
        .priv           = 0,
 };
 
-static int __devinit timeriomem_rng_probe(struct platform_device *pdev)
+static int timeriomem_rng_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int ret;
@@ -146,7 +146,7 @@ static struct platform_driver timeriomem_rng_driver = {
                .owner          = THIS_MODULE,
        },
        .probe          = timeriomem_rng_probe,
-       .remove         = __devexit_p(timeriomem_rng_remove),
+       .remove         = timeriomem_rng_remove,
 };
 
 module_platform_driver(timeriomem_rng_driver);
index 621f595f1a98b55b066d6e77a710e7c31a6d91c6..b65c10395959b507480a028d7a6dd12a02ff0871 100644 (file)
@@ -147,7 +147,7 @@ static struct virtio_driver virtio_rng_driver = {
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
        .probe =        virtrng_probe,
-       .remove =       __devexit_p(virtrng_remove),
+       .remove =       virtrng_remove,
 #ifdef CONFIG_PM
        .freeze =       virtrng_freeze,
        .restore =      virtrng_restore,
index cfdfecd5bc763026762bd9e26b08e4e3c15e7b67..1c7fdcd22a98f0ee3d5ae92959ef2467124c98c9 100644 (file)
@@ -2243,7 +2243,7 @@ static const struct pnp_device_id pnp_dev_table[] = {
 static struct pnp_driver ipmi_pnp_driver = {
        .name           = DEVICE_NAME,
        .probe          = ipmi_pnp_probe,
-       .remove         = __devexit_p(ipmi_pnp_remove),
+       .remove         = ipmi_pnp_remove,
        .id_table       = pnp_dev_table,
 };
 #endif
@@ -2546,7 +2546,7 @@ static struct pci_driver ipmi_pci_driver = {
        .name =         DEVICE_NAME,
        .id_table =     ipmi_pci_devices,
        .probe =        ipmi_pci_probe,
-       .remove =       __devexit_p(ipmi_pci_remove),
+       .remove =       ipmi_pci_remove,
 };
 #endif /* CONFIG_PCI */
 
@@ -2661,7 +2661,7 @@ static struct platform_driver ipmi_driver = {
                .of_match_table = ipmi_match,
        },
        .probe          = ipmi_probe,
-       .remove         = __devexit_p(ipmi_remove),
+       .remove         = ipmi_remove,
 };
 
 static int wait_for_msg_done(struct smi_info *smi_info)
index c594cb16c37bf5312f7b38946c6e3a562cc16c18..ee4dbeafb377c5a7786e97372962db2a05904427 100644 (file)
@@ -2062,7 +2062,8 @@ static void virtcons_remove(struct virtio_device *vdev)
        /* Disable interrupts for vqs */
        vdev->config->reset(vdev);
        /* Finish up work that's lined up */
-       cancel_work_sync(&portdev->control_work);
+       if (use_multiport(portdev))
+               cancel_work_sync(&portdev->control_work);
 
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
                unplug_port(port);
@@ -2186,11 +2187,7 @@ static struct virtio_driver virtio_console = {
 #endif
 };
 
-/*
- * virtio_rproc_serial refers to __devinit function which causes
- * section mismatch warnings. So use __refdata to silence warnings.
- */
-static struct virtio_driver __refdata virtio_rproc_serial = {
+static struct virtio_driver virtio_rproc_serial = {
        .feature_table = rproc_serial_features,
        .feature_table_size = ARRAY_SIZE(rproc_serial_features),
        .driver.name =  "virtio_rproc_serial",
index bc1e713e7b9cb282e2c601ee14ddf27bfda2eb62..3af729b1b89d16f48692b3bdb7fce217cf1e92f0 100644 (file)
@@ -78,7 +78,7 @@ static struct clk_init_data wm831x_clkout_init = {
        .flags = CLK_IS_ROOT,
 };
 
-static int __devinit twl6040_clk_probe(struct platform_device *pdev)
+static int twl6040_clk_probe(struct platform_device *pdev)
 {
        struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
        struct twl6040_clk *clkdata;
@@ -100,7 +100,7 @@ static int __devinit twl6040_clk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit twl6040_clk_remove(struct platform_device *pdev)
+static int twl6040_clk_remove(struct platform_device *pdev)
 {
        struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
 
@@ -115,7 +115,7 @@ static struct platform_driver twl6040_clk_driver = {
                .owner = THIS_MODULE,
        },
        .probe = twl6040_clk_probe,
-       .remove = __devexit_p(twl6040_clk_remove),
+       .remove = twl6040_clk_remove,
 };
 
 module_platform_driver(twl6040_clk_driver);
index ff004578a119e72d989d3c9baeb45dbf84f17b7b..9dd2551a0a41aebdb10f780b6657e9f3ce3de94c 100644 (file)
@@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
 
        clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
        if (WARN_ON(!clks))
-               return;
+               goto clks_out;
 
        for_each_node_by_type(dn, "cpu") {
                struct clk_init_data init;
@@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node)
                int cpu, err;
 
                if (WARN_ON(!clk_name))
-                       return;
+                       goto bail_out;
 
                err = of_property_read_u32(dn, "reg", &cpu);
                if (WARN_ON(err))
-                       return;
+                       goto bail_out;
 
                sprintf(clk_name, "cpu%d", cpu);
                parent_clk = of_clk_get(node, 0);
@@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node)
        return;
 bail_out:
        kfree(clks);
+       while(ncpus--)
+               kfree(cpuclk[ncpus].clk_name);
+clks_out:
        kfree(cpuclk);
 }
 
index c6d3c263b070cc2a66303fc09a861dfae2560c8f..8fa5408b6c7dfeef356ec102d6bf0eab3662835e 100644 (file)
@@ -32,7 +32,7 @@ struct mvebu_soc_descr {
 
 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
 
-static struct clk __init *mvebu_clk_gating_get_src(
+static struct clk *mvebu_clk_gating_get_src(
        struct of_phandle_args *clkspec, void *data)
 {
        struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
index e27c52317ffe41a7ab3ff595ff277eec52b789ef..9f7400d74fa77d9a8ef1a7c3b6933544f5a22985 100644 (file)
@@ -34,7 +34,7 @@ static int ab9540_reg_clks(struct device *dev)
        return 0;
 }
 
-static int __devinit abx500_clk_probe(struct platform_device *pdev)
+static int abx500_clk_probe(struct platform_device *pdev)
 {
        struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent);
        int ret;
index 5d1b9268bcaf4a99d3f7024852c962209a62bb5d..6efe4d1ab3aa7939cf4f431ca0891f4290b807c0 100644 (file)
@@ -73,7 +73,7 @@ static struct clocksource clocksource_acpi_pm = {
 
 
 #ifdef CONFIG_PCI
-static int __devinitdata acpi_pm_good;
+static int acpi_pm_good;
 static int __init acpi_pm_good_setup(char *__str)
 {
        acpi_pm_good = 1;
@@ -102,7 +102,7 @@ static inline void acpi_pm_need_workaround(void)
  * incorrect when read). As a result, the ACPI free running count up
  * timer specification is violated due to erroneous reads.
  */
-static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
+static void acpi_pm_check_blacklist(struct pci_dev *dev)
 {
        if (acpi_pm_good)
                return;
@@ -120,7 +120,7 @@ static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
                        acpi_pm_check_blacklist);
 
-static void __devinit acpi_pm_check_graylist(struct pci_dev *dev)
+static void acpi_pm_check_graylist(struct pci_dev *dev)
 {
        if (acpi_pm_good)
                return;
index 372051d1bba87b5796a68a543a5d628c61317642..e6a553cb73e807545270e3a873295b8b88dfc907 100644 (file)
@@ -311,7 +311,7 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)
        clockevents_config_and_register(ced, 1, 2, 0xffffffff);
 }
 
-static int __devinit em_sti_probe(struct platform_device *pdev)
+static int em_sti_probe(struct platform_device *pdev)
 {
        struct em_sti_priv *p;
        struct resource *res;
@@ -379,12 +379,12 @@ err0:
        return ret;
 }
 
-static int __devexit em_sti_remove(struct platform_device *pdev)
+static int em_sti_remove(struct platform_device *pdev)
 {
        return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
-static const struct of_device_id em_sti_dt_ids[] __devinitconst = {
+static const struct of_device_id em_sti_dt_ids[] = {
        { .compatible = "renesas,em-sti", },
        {},
 };
@@ -392,7 +392,7 @@ MODULE_DEVICE_TABLE(of, em_sti_dt_ids);
 
 static struct platform_driver em_sti_device_driver = {
        .probe          = em_sti_probe,
-       .remove         = __devexit_p(em_sti_remove),
+       .remove         = em_sti_remove,
        .driver         = {
                .name   = "em_sti",
                .of_match_table = em_sti_dt_ids,
index a5f7829f27993b8fefea105357229413b78e5309..488c14cc8dbf4848085142ca03e171ed35526b40 100644 (file)
@@ -726,7 +726,7 @@ err0:
        return ret;
 }
 
-static int __devinit sh_cmt_probe(struct platform_device *pdev)
+static int sh_cmt_probe(struct platform_device *pdev)
 {
        struct sh_cmt_priv *p = platform_get_drvdata(pdev);
        struct sh_timer_config *cfg = pdev->dev.platform_data;
@@ -767,14 +767,14 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit sh_cmt_remove(struct platform_device *pdev)
+static int sh_cmt_remove(struct platform_device *pdev)
 {
        return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
 static struct platform_driver sh_cmt_device_driver = {
        .probe          = sh_cmt_probe,
-       .remove         = __devexit_p(sh_cmt_remove),
+       .remove         = sh_cmt_remove,
        .driver         = {
                .name   = "sh_cmt",
        }
index c5eea858054aa4e67195edf69c1b1951fa8cf11c..83943e27cfac9193e659ecf7221afcfb48bcd73d 100644 (file)
@@ -321,7 +321,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
        return ret;
 }
 
-static int __devinit sh_mtu2_probe(struct platform_device *pdev)
+static int sh_mtu2_probe(struct platform_device *pdev)
 {
        struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
        struct sh_timer_config *cfg = pdev->dev.platform_data;
@@ -362,14 +362,14 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit sh_mtu2_remove(struct platform_device *pdev)
+static int sh_mtu2_remove(struct platform_device *pdev)
 {
        return -EBUSY; /* cannot unregister clockevent */
 }
 
 static struct platform_driver sh_mtu2_device_driver = {
        .probe          = sh_mtu2_probe,
-       .remove         = __devexit_p(sh_mtu2_remove),
+       .remove         = sh_mtu2_remove,
        .driver         = {
                .name   = "sh_mtu2",
        }
index 0cc4add882795ed048e5b98a9e215a758b8ad147..b4502edce2a140eb3d1f197d0cb39c294e5f0b2f 100644 (file)
@@ -484,7 +484,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
        return ret;
 }
 
-static int __devinit sh_tmu_probe(struct platform_device *pdev)
+static int sh_tmu_probe(struct platform_device *pdev)
 {
        struct sh_tmu_priv *p = platform_get_drvdata(pdev);
        struct sh_timer_config *cfg = pdev->dev.platform_data;
@@ -525,14 +525,14 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit sh_tmu_remove(struct platform_device *pdev)
+static int sh_tmu_remove(struct platform_device *pdev)
 {
        return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
 static struct platform_driver sh_tmu_device_driver = {
        .probe          = sh_tmu_probe,
-       .remove         = __devexit_p(sh_tmu_remove),
+       .remove         = sh_tmu_remove,
        .driver         = {
                .name   = "sh_tmu",
        }
index 965b7811e04f37100151dc441b7713cdee065bbf..7b695913cb309afa55f253eb7ae2273945dda041 100644 (file)
@@ -256,7 +256,7 @@ static struct cn_dev cdev = {
        .input   = cn_rx_skb,
 };
 
-static int __devinit cn_init(void)
+static int cn_init(void)
 {
        struct cn_dev *dev = &cdev;
        struct netlink_kernel_cfg cfg = {
@@ -281,7 +281,7 @@ static int __devinit cn_init(void)
        return 0;
 }
 
-static void __devexit cn_fini(void)
+static void cn_fini(void)
 {
        struct cn_dev *dev = &cdev;
 
index ea512f47b789b49c842a78388f15957fb65d62be..e0a899f25e37445491574f34e8350032d6d228ae 100644 (file)
@@ -20,6 +20,9 @@ if CPU_FREQ
 config CPU_FREQ_TABLE
        tristate
 
+config CPU_FREQ_GOV_COMMON
+       bool
+
 config CPU_FREQ_STAT
        tristate "CPU frequency translation statistics"
        select CPU_FREQ_TABLE
@@ -141,6 +144,7 @@ config CPU_FREQ_GOV_USERSPACE
 config CPU_FREQ_GOV_ONDEMAND
        tristate "'ondemand' cpufreq policy governor"
        select CPU_FREQ_TABLE
+       select CPU_FREQ_GOV_COMMON
        help
          'ondemand' - This driver adds a dynamic cpufreq policy governor.
          The governor does a periodic polling and 
@@ -159,6 +163,7 @@ config CPU_FREQ_GOV_ONDEMAND
 config CPU_FREQ_GOV_CONSERVATIVE
        tristate "'conservative' cpufreq governor"
        depends on CPU_FREQ
+       select CPU_FREQ_GOV_COMMON
        help
          'conservative' - this driver is rather similar to the 'ondemand'
          governor both in its source code and its purpose, the difference is
index 934854ae5eb4a436205d644c76c8011a5c41de3e..7227cd7340423c595a2a1b29488e864662198634 100644 (file)
@@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI
 config X86_POWERNOW_K8
        tristate "AMD Opteron/Athlon64 PowerNow!"
        select CPU_FREQ_TABLE
-       depends on ACPI && ACPI_PROCESSOR
+       depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
        help
          This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
          Support for K10 and newer processors is now in acpi-cpufreq.
index 1f254ec087c1c398d3da2035d477e37d8523b969..fadc4d496e2fc55383c2f9ddf6c59b9ff2072ec3 100644 (file)
@@ -7,8 +7,9 @@ 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 cpufreq_governor.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)    += cpufreq_ondemand.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_COMMON)              += cpufreq_governor.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
index 0d048f6a2b23a3bf9476a658cac846ccd321bd3c..7b0d49d78c61fc6c9fd312b0d05663ad42edf099 100644 (file)
@@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict,
 late_initcall(acpi_cpufreq_init);
 module_exit(acpi_cpufreq_exit);
 
+static const struct x86_cpu_id acpi_cpufreq_ids[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_ACPI),
+       X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids);
+
 MODULE_ALIAS("acpi");
index 52bf36d599f575fcdd0bfe4fc3788db0d492e5a8..debc5a7c8db6207feeb9c428ccc44b8fcaed8d2f 100644 (file)
@@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
        }
 
        if (cpu_reg) {
+               rcu_read_lock();
                opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
                if (IS_ERR(opp)) {
+                       rcu_read_unlock();
                        pr_err("failed to find OPP for %ld\n", freq_Hz);
                        return PTR_ERR(opp);
                }
                volt = opp_get_voltage(opp);
+               rcu_read_unlock();
                tol = volt * voltage_tolerance / 100;
                volt_old = regulator_get_voltage(cpu_reg);
        }
@@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void)
                 */
                for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                        ;
+               rcu_read_lock();
                opp = opp_find_freq_exact(cpu_dev,
                                freq_table[0].frequency * 1000, true);
                min_uV = opp_get_voltage(opp);
                opp = opp_find_freq_exact(cpu_dev,
                                freq_table[i-1].frequency * 1000, true);
                max_uV = opp_get_voltage(opp);
+               rcu_read_unlock();
                ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
                if (ret > 0)
                        transition_latency += ret * 1000;
index e40e508096443b683d7e3b9b2571af2a9a0d6c17..9d7732b810445f6b73318e574924b6bed6ac6829 100644 (file)
@@ -364,18 +364,21 @@ static int __init cpufreq_stats_init(void)
        if (ret)
                return ret;
 
+       register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+       for_each_online_cpu(cpu)
+               cpufreq_update_policy(cpu);
+
        ret = cpufreq_register_notifier(&notifier_trans_block,
                                CPUFREQ_TRANSITION_NOTIFIER);
        if (ret) {
                cpufreq_unregister_notifier(&notifier_policy_block,
                                CPUFREQ_POLICY_NOTIFIER);
+               unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+               for_each_online_cpu(cpu)
+                       cpufreq_stats_free_table(cpu);
                return ret;
        }
 
-       register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
-       for_each_online_cpu(cpu) {
-               cpufreq_update_policy(cpu);
-       }
        return 0;
 }
 static void __exit cpufreq_stats_exit(void)
index f1fa500ac1056e30242cfc4de6b94d267ada23d0..1180d536d1eb6cf8c2d59b4d1432a0f65be85675 100644 (file)
@@ -77,7 +77,7 @@ static unsigned int longhaul_index;
 static int scale_voltage;
 static int disable_acpi_c3;
 static int revid_errata;
-
+static int enable;
 
 /* Clock ratios multiplied by 10 */
 static int mults[32];
@@ -965,6 +965,10 @@ static int __init longhaul_init(void)
        if (!x86_match_cpu(longhaul_id))
                return -ENODEV;
 
+       if (!enable) {
+               printk(KERN_ERR PFX "Option \"enable\" not set. Aborting.\n");
+               return -ENODEV;
+       }
 #ifdef CONFIG_SMP
        if (num_online_cpus() > 1) {
                printk(KERN_ERR PFX "More than 1 CPU detected, "
@@ -1021,6 +1025,10 @@ MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
  * such. */
 module_param(revid_errata, int, 0644);
 MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
+/* By default driver is disabled to prevent incompatible
+ * system freeze. */
+module_param(enable, int, 0644);
+MODULE_PARM_DESC(enable, "Enable driver");
 
 MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
 MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors.");
index 1f3417a8322dfe8b0ca773873e058f7eb3a6c283..97102b05843fa580435ae0ae5b872d9467b577df 100644 (file)
@@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy,
        freq = ret;
 
        if (mpu_reg) {
+               rcu_read_lock();
                opp = opp_find_freq_ceil(mpu_dev, &freq);
                if (IS_ERR(opp)) {
+                       rcu_read_unlock();
                        dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
                                __func__, freqs.new);
                        return -EINVAL;
                }
                volt = opp_get_voltage(opp);
+               rcu_read_unlock();
                tol = volt * OPP_TOLERANCE / 100;
                volt_old = regulator_get_voltage(mpu_reg);
        }
index 3265844839bfe9c79ef8849705262a52d16cc4e1..2a297f86dbad25be5f17e0f41029e92dd23afeaf 100644 (file)
@@ -209,7 +209,7 @@ inline int cpuidle_coupled_set_not_ready(struct cpuidle_coupled *coupled)
        int all;
        int ret;
 
-       all = coupled->online_count || (coupled->online_count << WAITING_BITS);
+       all = coupled->online_count | (coupled->online_count << WAITING_BITS);
        ret = atomic_add_unless(&coupled->ready_waiting_counts,
                -MAX_WAITING_CPUS, all);
 
index 8df53dd8dbe17b4bb0c0d432bbec56d31895dc84..e1f6860e069c7350d3fbb5bb499a67bfc581f760 100644 (file)
@@ -69,24 +69,15 @@ int cpuidle_play_dead(void)
 {
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
-       int i, dead_state = -1;
-       int power_usage = -1;
+       int i;
 
        if (!drv)
                return -ENODEV;
 
        /* Find lowest-power state that supports long-term idle */
-       for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
-               struct cpuidle_state *s = &drv->states[i];
-
-               if (s->power_usage < power_usage && s->enter_dead) {
-                       power_usage = s->power_usage;
-                       dead_state = i;
-               }
-       }
-
-       if (dead_state != -1)
-               return drv->states[dead_state].enter_dead(dev, dead_state);
+       for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--)
+               if (drv->states[i].enter_dead)
+                       return drv->states[i].enter_dead(dev, i);
 
        return -ENODEV;
 }
index 3af841fb397a0cda095b9ca794c04271c5164332..422c7b69ba7c50e728fa3af5af346a85a553af8f 100644 (file)
@@ -19,34 +19,9 @@ DEFINE_SPINLOCK(cpuidle_driver_lock);
 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)
-{
-       int i;
-
-       /*
-        * cpuidle driver should set the drv->power_specified bit
-        * before registering if the driver provides
-        * power_usage numbers.
-        *
-        * If power_specified is not set,
-        * we fill in power_usage with decreasing values as the
-        * cpuidle code has an implicit assumption that state Cn
-        * uses less power than C(n-1).
-        *
-        * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
-        * an power value of -1.  So we use -2, -3, etc, for other
-        * c-states.
-        */
-       for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
-               drv->states[i].power_usage = -1 - i;
-}
-
 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)
@@ -235,16 +210,10 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
  */
 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;
+       return __cpuidle_get_cpu_driver(dev->cpu);
 }
 EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
 
index bd40b943b6db134eb30f0f6fe3fc0cf1dc7aaad0..fe343a06b7da3278ba68c9c15c261ea14afde685 100644 (file)
@@ -312,7 +312,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
        struct menu_device *data = &__get_cpu_var(menu_devices);
        int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
-       int power_usage = -1;
        int i;
        int multiplier;
        struct timespec t;
@@ -383,11 +382,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
                if (s->exit_latency * multiplier > data->predicted_us)
                        continue;
 
-               if (s->power_usage < power_usage) {
-                       power_usage = s->power_usage;
-                       data->last_state_idx = i;
-                       data->exit_us = s->exit_latency;
-               }
+               data->last_state_idx = i;
+               data->exit_us = s->exit_latency;
        }
 
        /* not deepest C-state chosen for low predicted residency */
index 340942946106d22489124923a2ccd766bc22f2ef..428754af62366cda8fe71dee47b128c5da602969 100644 (file)
@@ -374,7 +374,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
        /* state statistics */
-       for (i = 0; i < drv->state_count; i++) {
+       for (i = 0; i < device->state_count; i++) {
                kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
                if (!kobj)
                        goto error_state;
index 8061336e07e7c74789e46a86438756dddc855e6e..c9d9d5c16f94903ec5c90e939ecbb84767585474 100644 (file)
@@ -1036,7 +1036,7 @@ err_aes_algs:
        return err;
 }
 
-static int __devinit atmel_aes_probe(struct platform_device *pdev)
+static int atmel_aes_probe(struct platform_device *pdev)
 {
        struct atmel_aes_dev *aes_dd;
        struct aes_platform_data        *pdata;
@@ -1152,7 +1152,7 @@ aes_dd_err:
        return err;
 }
 
-static int __devexit atmel_aes_remove(struct platform_device *pdev)
+static int atmel_aes_remove(struct platform_device *pdev)
 {
        static struct atmel_aes_dev *aes_dd;
 
@@ -1185,7 +1185,7 @@ static int __devexit atmel_aes_remove(struct platform_device *pdev)
 
 static struct platform_driver atmel_aes_driver = {
        .probe          = atmel_aes_probe,
-       .remove         = __devexit_p(atmel_aes_remove),
+       .remove         = atmel_aes_remove,
        .driver         = {
                .name   = "atmel_aes",
                .owner  = THIS_MODULE,
index bcdf55fdc6236e49afdc4ade1ece2ed24b61a755..4918e9424d3112a4b5feae51fc30babba444437c 100644 (file)
@@ -964,7 +964,7 @@ err_sha_algs:
        return err;
 }
 
-static int __devinit atmel_sha_probe(struct platform_device *pdev)
+static int atmel_sha_probe(struct platform_device *pdev)
 {
        struct atmel_sha_dev *sha_dd;
        struct device *dev = &pdev->dev;
@@ -1063,7 +1063,7 @@ sha_dd_err:
        return err;
 }
 
-static int __devexit atmel_sha_remove(struct platform_device *pdev)
+static int atmel_sha_remove(struct platform_device *pdev)
 {
        static struct atmel_sha_dev *sha_dd;
 
@@ -1093,7 +1093,7 @@ static int __devexit atmel_sha_remove(struct platform_device *pdev)
 
 static struct platform_driver atmel_sha_driver = {
        .probe          = atmel_sha_probe,
-       .remove         = __devexit_p(atmel_sha_remove),
+       .remove         = atmel_sha_remove,
        .driver         = {
                .name   = "atmel_sha",
                .owner  = THIS_MODULE,
index 7495f98c722135ea76820a63496138bbc7491f73..7c73fbb17538adaaf7550b96889c66d9b8f0b04e 100644 (file)
@@ -1053,7 +1053,7 @@ err_tdes_algs:
        return err;
 }
 
-static int __devinit atmel_tdes_probe(struct platform_device *pdev)
+static int atmel_tdes_probe(struct platform_device *pdev)
 {
        struct atmel_tdes_dev *tdes_dd;
        struct device *dev = &pdev->dev;
@@ -1162,7 +1162,7 @@ tdes_dd_err:
        return err;
 }
 
-static int __devexit atmel_tdes_remove(struct platform_device *pdev)
+static int atmel_tdes_remove(struct platform_device *pdev)
 {
        static struct atmel_tdes_dev *tdes_dd;
 
@@ -1195,7 +1195,7 @@ static int __devexit atmel_tdes_remove(struct platform_device *pdev)
 
 static struct platform_driver atmel_tdes_driver = {
        .probe          = atmel_tdes_probe,
-       .remove         = __devexit_p(atmel_tdes_remove),
+       .remove         = atmel_tdes_remove,
        .driver         = {
                .name   = "atmel_tdes",
                .owner  = THIS_MODULE,
index 5398580b431340eb85210cd80393872a730a15c3..a22f1a9f895f587b00662c7442258e161fcdc017 100644 (file)
@@ -586,7 +586,7 @@ static int bfin_crypto_crc_suspend(struct platform_device *pdev, pm_message_t st
  *     bfin_crypto_crc_probe - Initialize module
  *
  */
-static int __devinit bfin_crypto_crc_probe(struct platform_device *pdev)
+static int bfin_crypto_crc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct resource *res;
@@ -707,7 +707,7 @@ out_error_free_mem:
  *     bfin_crypto_crc_remove - Initialize module
  *
  */
-static int __devexit bfin_crypto_crc_remove(struct platform_device *pdev)
+static int bfin_crypto_crc_remove(struct platform_device *pdev)
 {
        struct bfin_crypto_crc *crc = platform_get_drvdata(pdev);
 
@@ -731,7 +731,7 @@ static int __devexit bfin_crypto_crc_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_crypto_crc_driver = {
        .probe     = bfin_crypto_crc_probe,
-       .remove    = __devexit_p(bfin_crypto_crc_remove),
+       .remove    = bfin_crypto_crc_remove,
        .suspend   = bfin_crypto_crc_suspend,
        .resume    = bfin_crypto_crc_resume,
        .driver    = {
index bf20dd891705890ad544086af82cfaf7e4a97fac..1c56f63524f27b2139860518f3ee672fdeef07cb 100644 (file)
@@ -420,7 +420,7 @@ static struct platform_driver caam_driver = {
                .of_match_table = caam_match,
        },
        .probe       = caam_probe,
-       .remove      = __devexit_p(caam_remove),
+       .remove      = caam_remove,
 };
 
 module_platform_driver(caam_driver);
index 51f196d77f2185cacaf8a53ff965081669593f6f..0c9ff497172425f617bd753c912b7b62567c7e74 100644 (file)
@@ -498,8 +498,7 @@ static struct crypto_alg geode_ecb_alg = {
        }
 };
 
-static void __devexit
-geode_aes_remove(struct pci_dev *dev)
+static void geode_aes_remove(struct pci_dev *dev)
 {
        crypto_unregister_alg(&geode_alg);
        crypto_unregister_alg(&geode_ecb_alg);
@@ -513,8 +512,7 @@ geode_aes_remove(struct pci_dev *dev)
 }
 
 
-static int __devinit
-geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int ret;
        ret = pci_enable_device(dev);
@@ -582,7 +580,7 @@ static struct pci_driver geode_aes_driver = {
        .name = "Geode LX AES",
        .id_table = geode_aes_tbl,
        .probe = geode_aes_probe,
-       .remove = __devexit_p(geode_aes_remove)
+       .remove = geode_aes_remove,
 };
 
 module_pci_driver(geode_aes_driver);
index fda32968a66b660cf5ff4faf3048394736458264..ebf130e894b50da2bb69bf08a7d3f5210af70d7d 100644 (file)
@@ -2561,7 +2561,7 @@ static void hifn_tasklet_callback(unsigned long data)
                hifn_process_queue(dev);
 }
 
-static int __devinit hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int err, i;
        struct hifn_device *dev;
@@ -2696,7 +2696,7 @@ err_out_disable_pci_device:
        return err;
 }
 
-static void __devexit hifn_remove(struct pci_dev *pdev)
+static void hifn_remove(struct pci_dev *pdev)
 {
        int i;
        struct hifn_device *dev;
@@ -2740,7 +2740,7 @@ static struct pci_driver hifn_pci_driver = {
        .name     = "hifn795x",
        .id_table = hifn_pci_tbl,
        .probe    = hifn_probe,
-       .remove   = __devexit_p(hifn_remove),
+       .remove   = hifn_remove,
 };
 
 static int __init hifn_init(void)
index 24ccae453e7940c8e74c60c245072eb7754354cc..ce6290e5471ab3ca2e46857b7c7e8550cae66768 100644 (file)
@@ -1184,7 +1184,7 @@ MODULE_DEVICE_TABLE(of, mv_cesa_of_match_table);
 
 static struct platform_driver marvell_crypto = {
        .probe          = mv_probe,
-       .remove         = __devexit_p(mv_remove),
+       .remove         = mv_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "mv_crypto",
index aab257403b4a54ac4d75d4db3340c9b48855478b..e1f0ab413c3b80a59b55bb4f079524067c09d22f 100644 (file)
@@ -34,7 +34,7 @@
 #define DRV_MODULE_VERSION     "0.2"
 #define DRV_MODULE_RELDATE     "July 28, 2011"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@@ -1388,7 +1388,7 @@ static int n2_cipher_cra_init(struct crypto_tfm *tfm)
        return 0;
 }
 
-static int __devinit __n2_register_one_cipher(const struct n2_cipher_tmpl *tmpl)
+static int __n2_register_one_cipher(const struct n2_cipher_tmpl *tmpl)
 {
        struct n2_cipher_alg *p = kzalloc(sizeof(*p), GFP_KERNEL);
        struct crypto_alg *alg;
@@ -1424,7 +1424,7 @@ static int __devinit __n2_register_one_cipher(const struct n2_cipher_tmpl *tmpl)
        return err;
 }
 
-static int __devinit __n2_register_one_hmac(struct n2_ahash_alg *n2ahash)
+static int __n2_register_one_hmac(struct n2_ahash_alg *n2ahash)
 {
        struct n2_hmac_alg *p = kzalloc(sizeof(*p), GFP_KERNEL);
        struct ahash_alg *ahash;
@@ -1462,7 +1462,7 @@ static int __devinit __n2_register_one_hmac(struct n2_ahash_alg *n2ahash)
        return err;
 }
 
-static int __devinit __n2_register_one_ahash(const struct n2_hash_tmpl *tmpl)
+static int __n2_register_one_ahash(const struct n2_hash_tmpl *tmpl)
 {
        struct n2_ahash_alg *p = kzalloc(sizeof(*p), GFP_KERNEL);
        struct hash_alg_common *halg;
@@ -1517,7 +1517,7 @@ static int __devinit __n2_register_one_ahash(const struct n2_hash_tmpl *tmpl)
        return err;
 }
 
-static int __devinit n2_register_algs(void)
+static int n2_register_algs(void)
 {
        int i, err = 0;
 
@@ -1545,7 +1545,7 @@ out:
        return err;
 }
 
-static void __devexit n2_unregister_algs(void)
+static void n2_unregister_algs(void)
 {
        mutex_lock(&spu_lock);
        if (!--algs_registered)
@@ -1822,8 +1822,8 @@ static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *de
        return err;
 }
 
-static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
-                                  struct spu_mdesc_info *ip)
+static int get_irq_props(struct mdesc_handle *mdesc, u64 node,
+                        struct spu_mdesc_info *ip)
 {
        const u64 *ino;
        int ino_len;
@@ -1851,10 +1851,10 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
        return 0;
 }
 
-static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc,
-                                         struct platform_device *dev,
-                                         struct spu_mdesc_info *ip,
-                                         const char *node_name)
+static int grab_mdesc_irq_props(struct mdesc_handle *mdesc,
+                               struct platform_device *dev,
+                               struct spu_mdesc_info *ip,
+                               const char *node_name)
 {
        const unsigned int *reg;
        u64 node;
@@ -1883,7 +1883,7 @@ static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc,
 static unsigned long n2_spu_hvapi_major;
 static unsigned long n2_spu_hvapi_minor;
 
-static int __devinit n2_spu_hvapi_register(void)
+static int n2_spu_hvapi_register(void)
 {
        int err;
 
@@ -1909,7 +1909,7 @@ static void n2_spu_hvapi_unregister(void)
 
 static int global_ref;
 
-static int __devinit grab_global_resources(void)
+static int grab_global_resources(void)
 {
        int err = 0;
 
@@ -1973,7 +1973,7 @@ static void release_global_resources(void)
        mutex_unlock(&spu_lock);
 }
 
-static struct n2_crypto * __devinit alloc_n2cp(void)
+static struct n2_crypto *alloc_n2cp(void)
 {
        struct n2_crypto *np = kzalloc(sizeof(struct n2_crypto), GFP_KERNEL);
 
@@ -1993,7 +1993,7 @@ static void free_n2cp(struct n2_crypto *np)
        kfree(np);
 }
 
-static void __devinit n2_spu_driver_version(void)
+static void n2_spu_driver_version(void)
 {
        static int n2_spu_version_printed;
 
@@ -2001,7 +2001,7 @@ static void __devinit n2_spu_driver_version(void)
                pr_info("%s", version);
 }
 
-static int __devinit n2_crypto_probe(struct platform_device *dev)
+static int n2_crypto_probe(struct platform_device *dev)
 {
        struct mdesc_handle *mdesc;
        const char *full_name;
@@ -2077,7 +2077,7 @@ out_free_n2cp:
        return err;
 }
 
-static int __devexit n2_crypto_remove(struct platform_device *dev)
+static int n2_crypto_remove(struct platform_device *dev)
 {
        struct n2_crypto *np = dev_get_drvdata(&dev->dev);
 
@@ -2092,7 +2092,7 @@ static int __devexit n2_crypto_remove(struct platform_device *dev)
        return 0;
 }
 
-static struct n2_mau * __devinit alloc_ncp(void)
+static struct n2_mau *alloc_ncp(void)
 {
        struct n2_mau *mp = kzalloc(sizeof(struct n2_mau), GFP_KERNEL);
 
@@ -2112,7 +2112,7 @@ static void free_ncp(struct n2_mau *mp)
        kfree(mp);
 }
 
-static int __devinit n2_mau_probe(struct platform_device *dev)
+static int n2_mau_probe(struct platform_device *dev)
 {
        struct mdesc_handle *mdesc;
        const char *full_name;
@@ -2179,7 +2179,7 @@ out_free_ncp:
        return err;
 }
 
-static int __devexit n2_mau_remove(struct platform_device *dev)
+static int n2_mau_remove(struct platform_device *dev)
 {
        struct n2_mau *mp = dev_get_drvdata(&dev->dev);
 
@@ -2217,7 +2217,7 @@ static struct platform_driver n2_crypto_driver = {
                .of_match_table =       n2_crypto_match,
        },
        .probe          =       n2_crypto_probe,
-       .remove         =       __devexit_p(n2_crypto_remove),
+       .remove         =       n2_crypto_remove,
 };
 
 static struct of_device_id n2_mau_match[] = {
@@ -2245,7 +2245,7 @@ static struct platform_driver n2_mau_driver = {
                .of_match_table =       n2_mau_match,
        },
        .probe          =       n2_mau_probe,
-       .remove         =       __devexit_p(n2_mau_remove),
+       .remove         =       n2_mau_remove,
 };
 
 static int __init n2_init(void)
index f7a8a16aa7d39d796a07385540eddf60df79661d..c767f232e6933bc876adedd56a1f7e655f93c815 100644 (file)
@@ -634,8 +634,7 @@ void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
        nx_ctx->out_sg = NULL;
 }
 
-static int __devinit nx_probe(struct vio_dev *viodev,
-                             const struct vio_device_id *id)
+static int nx_probe(struct vio_dev *viodev, const struct vio_device_id *id)
 {
        dev_dbg(&viodev->dev, "driver probed: %s resource id: 0x%x\n",
                viodev->name, viodev->resource_id);
@@ -653,7 +652,7 @@ static int __devinit nx_probe(struct vio_dev *viodev,
        return nx_register_algs();
 }
 
-static int __devexit nx_remove(struct vio_dev *viodev)
+static int nx_remove(struct vio_dev *viodev)
 {
        dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
                viodev->unit_address);
@@ -689,7 +688,7 @@ static void __exit nx_fini(void)
        vio_unregister_driver(&nx_driver.viodriver);
 }
 
-static struct vio_device_id nx_crypto_driver_ids[] __devinitdata = {
+static struct vio_device_id nx_crypto_driver_ids[] = {
        { "ibm,sym-encryption-v1", "ibm,sym-encryption" },
        { "", "" }
 };
index 1d75e6f95a5877fab7c987dfe5b50bf2d8394017..90d34adc2a66ba36ccfce82142e154db04e87d83 100644 (file)
@@ -1137,7 +1137,7 @@ static void omap_sham_dma_cleanup(struct omap_sham_dev *dd)
        }
 }
 
-static int __devinit omap_sham_probe(struct platform_device *pdev)
+static int omap_sham_probe(struct platform_device *pdev)
 {
        struct omap_sham_dev *dd;
        struct device *dev = &pdev->dev;
@@ -1250,7 +1250,7 @@ data_err:
        return err;
 }
 
-static int __devexit omap_sham_remove(struct platform_device *pdev)
+static int omap_sham_remove(struct platform_device *pdev)
 {
        static struct omap_sham_dev *dd;
        int i;
index c983f869d2b7a58e0a7e7978e294dae6dd0cc5d4..2096d4685a9e362a1837f58ee8b3477a4340a410 100644 (file)
@@ -1708,7 +1708,7 @@ static bool spacc_is_compatible(struct platform_device *pdev,
        return false;
 }
 
-static int __devinit spacc_probe(struct platform_device *pdev)
+static int spacc_probe(struct platform_device *pdev)
 {
        int i, err, ret = -EINVAL;
        struct resource *mem, *irq;
@@ -1841,7 +1841,7 @@ static int __devinit spacc_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit spacc_remove(struct platform_device *pdev)
+static int spacc_remove(struct platform_device *pdev)
 {
        struct spacc_alg *alg, *next;
        struct spacc_engine *engine = platform_get_drvdata(pdev);
@@ -1868,7 +1868,7 @@ static const struct platform_device_id spacc_id_table[] = {
 
 static struct platform_driver spacc_driver = {
        .probe          = spacc_probe,
-       .remove         = __devexit_p(spacc_remove),
+       .remove         = spacc_remove,
        .driver         = {
                .name   = "picochip,spacc",
 #ifdef CONFIG_PM
index eb32fd8cad147eacbaaf115516945736fa37ad7d..85ea7525fa36242bda4cb21c37ce788981d3b502 100644 (file)
@@ -1047,7 +1047,7 @@ out:
        return err;
 }
 
-static int __devexit tegra_aes_remove(struct platform_device *pdev)
+static int tegra_aes_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct tegra_aes_dev *dd = platform_get_drvdata(pdev);
@@ -1074,7 +1074,7 @@ static int __devexit tegra_aes_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_aes_of_match[] __devinitdata = {
+static struct of_device_id tegra_aes_of_match[] = {
        { .compatible = "nvidia,tegra20-aes", },
        { .compatible = "nvidia,tegra30-aes", },
        { },
@@ -1082,7 +1082,7 @@ static struct of_device_id tegra_aes_of_match[] __devinitdata = {
 
 static struct platform_driver tegra_aes_driver = {
        .probe  = tegra_aes_probe,
-       .remove = __devexit_p(tegra_aes_remove),
+       .remove = tegra_aes_remove,
        .driver = {
                .name   = "tegra-aes",
                .owner  = THIS_MODULE,
index 53766f39aaddfd5db9147842b40825fb1399453b..3b367973a8028c5d1cd32bd823bcf9e005d269b6 100644 (file)
@@ -994,6 +994,11 @@ module_exit(devfreq_exit);
  * @freq:      The frequency given to target function
  * @flags:     Flags handed from devfreq framework.
  *
+ * 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
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
 struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
                                    u32 flags)
index 741837208716e293d06bbe9cfa94fac4051303d4..46d94e9e95b53ae033af012ef745822e0b7f5ccd 100644 (file)
@@ -73,6 +73,16 @@ enum busclk_level_idx {
 #define EX4210_LV_NUM  (LV_2 + 1)
 #define EX4x12_LV_NUM  (LV_4 + 1)
 
+/**
+ * struct busfreq_opp_info - opp information for bus
+ * @rate:      Frequency in hertz
+ * @volt:      Voltage in microvolts corresponding to this OPP
+ */
+struct busfreq_opp_info {
+       unsigned long rate;
+       unsigned long volt;
+};
+
 struct busfreq_data {
        enum exynos4_busf_type type;
        struct device *dev;
@@ -80,7 +90,7 @@ struct busfreq_data {
        bool disabled;
        struct regulator *vdd_int;
        struct regulator *vdd_mif; /* Exynos4412/4212 only */
-       struct opp *curr_opp;
+       struct busfreq_opp_info curr_oppinfo;
        struct exynos4_ppmu dmc[2];
 
        struct notifier_block pm_notifier;
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
 };
 
 
-static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4210_set_busclk(struct busfreq_data *data,
+                                struct busfreq_opp_info *oppi)
 {
        unsigned int index;
        unsigned int tmp;
 
        for (index = LV_0; index < EX4210_LV_NUM; index++)
-               if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk)
+               if (oppi->rate == exynos4210_busclk_table[index].clk)
                        break;
 
        if (index == EX4210_LV_NUM)
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
        return 0;
 }
 
-static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4x12_set_busclk(struct busfreq_data *data,
+                                struct busfreq_opp_info *oppi)
 {
        unsigned int index;
        unsigned int tmp;
 
        for (index = LV_0; index < EX4x12_LV_NUM; index++)
-               if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk)
+               if (oppi->rate == exynos4x12_mifclk_table[index].clk)
                        break;
 
        if (index == EX4x12_LV_NUM)
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk)
        return -EINVAL;
 }
 
-static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
-                              struct opp *oldopp)
+static int exynos4_bus_setvolt(struct busfreq_data *data,
+                              struct busfreq_opp_info *oppi,
+                              struct busfreq_opp_info *oldoppi)
 {
        int err = 0, tmp;
-       unsigned long volt = opp_get_voltage(opp);
+       unsigned long volt = oppi->volt;
 
        switch (data->type) {
        case TYPE_BUSF_EXYNOS4210:
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
                if (err)
                        break;
 
-               tmp = exynos4x12_get_intspec(opp_get_freq(opp));
+               tmp = exynos4x12_get_intspec(oppi->rate);
                if (tmp < 0) {
                        err = tmp;
                        regulator_set_voltage(data->vdd_mif,
-                                             opp_get_voltage(oldopp),
+                                             oldoppi->volt,
                                              MAX_SAFEVOLT);
                        break;
                }
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
                /*  Try to recover */
                if (err)
                        regulator_set_voltage(data->vdd_mif,
-                                             opp_get_voltage(oldopp),
+                                             oldoppi->volt,
                                              MAX_SAFEVOLT);
                break;
        default:
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data *data = platform_get_drvdata(pdev);
-       struct opp *opp = devfreq_recommended_opp(dev, _freq, flags);
-       unsigned long freq = opp_get_freq(opp);
-       unsigned long old_freq = opp_get_freq(data->curr_opp);
+       struct opp *opp;
+       unsigned long freq;
+       unsigned long old_freq = data->curr_oppinfo.rate;
+       struct busfreq_opp_info new_oppinfo;
 
-       if (IS_ERR(opp))
+       rcu_read_lock();
+       opp = devfreq_recommended_opp(dev, _freq, flags);
+       if (IS_ERR(opp)) {
+               rcu_read_unlock();
                return PTR_ERR(opp);
+       }
+       new_oppinfo.rate = opp_get_freq(opp);
+       new_oppinfo.volt = opp_get_voltage(opp);
+       rcu_read_unlock();
+       freq = new_oppinfo.rate;
 
        if (old_freq == freq)
                return 0;
 
-       dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp));
+       dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt);
 
        mutex_lock(&data->lock);
 
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                goto out;
 
        if (old_freq < freq)
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
        if (err)
                goto out;
 
        if (old_freq != freq) {
                switch (data->type) {
                case TYPE_BUSF_EXYNOS4210:
-                       err = exynos4210_set_busclk(data, opp);
+                       err = exynos4210_set_busclk(data, &new_oppinfo);
                        break;
                case TYPE_BUSF_EXYNOS4x12:
-                       err = exynos4x12_set_busclk(data, opp);
+                       err = exynos4x12_set_busclk(data, &new_oppinfo);
                        break;
                default:
                        err = -EINVAL;
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                goto out;
 
        if (old_freq > freq)
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
        if (err)
                goto out;
 
-       data->curr_opp = opp;
+       data->curr_oppinfo = new_oppinfo;
 out:
        mutex_unlock(&data->lock);
        return err;
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev,
 
        exynos4_read_ppmu(data);
        busier_dmc = exynos4_get_busier_dmc(data);
-       stat->current_frequency = opp_get_freq(data->curr_opp);
+       stat->current_frequency = data->curr_oppinfo.rate;
 
        if (busier_dmc)
                addr = S5P_VA_DMC1;
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
        struct busfreq_data *data = container_of(this, struct busfreq_data,
                                                 pm_notifier);
        struct opp *opp;
+       struct busfreq_opp_info new_oppinfo;
        unsigned long maxfreq = ULONG_MAX;
        int err = 0;
 
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
 
                data->disabled = true;
 
+               rcu_read_lock();
                opp = opp_find_freq_floor(data->dev, &maxfreq);
+               if (IS_ERR(opp)) {
+                       rcu_read_unlock();
+                       dev_err(data->dev, "%s: unable to find a min freq\n",
+                               __func__);
+                       return PTR_ERR(opp);
+               }
+               new_oppinfo.rate = opp_get_freq(opp);
+               new_oppinfo.volt = opp_get_voltage(opp);
+               rcu_read_unlock();
 
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
                if (err)
                        goto unlock;
 
                switch (data->type) {
                case TYPE_BUSF_EXYNOS4210:
-                       err = exynos4210_set_busclk(data, opp);
+                       err = exynos4210_set_busclk(data, &new_oppinfo);
                        break;
                case TYPE_BUSF_EXYNOS4x12:
-                       err = exynos4x12_set_busclk(data, opp);
+                       err = exynos4x12_set_busclk(data, &new_oppinfo);
                        break;
                default:
                        err = -EINVAL;
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                if (err)
                        goto unlock;
 
-               data->curr_opp = opp;
+               data->curr_oppinfo = new_oppinfo;
 unlock:
                mutex_unlock(&data->lock);
                if (err)
@@ -980,7 +1016,7 @@ unlock:
        return NOTIFY_DONE;
 }
 
-static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
+static int exynos4_busfreq_probe(struct platform_device *pdev)
 {
        struct busfreq_data *data;
        struct opp *opp;
@@ -1027,13 +1063,17 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
                }
        }
 
+       rcu_read_lock();
        opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
        if (IS_ERR(opp)) {
+               rcu_read_unlock();
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
                        exynos4_devfreq_profile.initial_freq);
                return PTR_ERR(opp);
        }
-       data->curr_opp = opp;
+       data->curr_oppinfo.rate = opp_get_freq(opp);
+       data->curr_oppinfo.volt = opp_get_voltage(opp);
+       rcu_read_unlock();
 
        platform_set_drvdata(pdev, data);
 
@@ -1056,7 +1096,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
+static int exynos4_busfreq_remove(struct platform_device *pdev)
 {
        struct busfreq_data *data = platform_get_drvdata(pdev);
 
@@ -1087,7 +1127,7 @@ static const struct platform_device_id exynos4_busfreq_id[] = {
 
 static struct platform_driver exynos4_busfreq_driver = {
        .probe  = exynos4_busfreq_probe,
-       .remove = __devexit_p(exynos4_busfreq_remove),
+       .remove = exynos4_busfreq_remove,
        .id_table = exynos4_busfreq_id,
        .driver = {
                .name   = "exynos4-busfreq",
index 8f0b111af4de435c75f62d0e1b85ac3db2d38f6e..3e8ba02ba29227a89d4950b18d64811c7b9b5667 100644 (file)
@@ -1634,7 +1634,7 @@ static int dw_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit dw_remove(struct platform_device *pdev)
+static int dw_remove(struct platform_device *pdev)
 {
        struct dw_dma           *dw = platform_get_drvdata(pdev);
        struct dw_dma_chan      *dwc, *_dwc;
index 232b4583ae93b3f3f68b14e4dbaff04d4d72361f..f424298f1ac5094513f6ac9f3e3a64cbaa681ba6 100644 (file)
@@ -585,7 +585,7 @@ err_reg1:
        return ret;
 }
 
-static int __devexit edma_remove(struct platform_device *pdev)
+static int edma_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct edma_cc *ecc = dev_get_drvdata(dev);
index dbf0e6f8de8a8c64d4b29b33b9c834ae3ab904c7..a7dcf78b1ff809e4a6a865884779856330d15510 100644 (file)
@@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                        break;
                }
 
-               imxdmac->hw_chaining = 1;
-               if (!imxdma_hw_chain(imxdmac))
-                       return -EINVAL;
+               imxdmac->hw_chaining = 0;
+
                imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) |
                        ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) |
                        CCR_REN;
index bc764afacd9ba748ce572dea5d4bb39258f898f9..a0de82e21a7c30d00f122071783c9280583990f4 100644 (file)
@@ -1308,7 +1308,7 @@ err_enable_device:
  * Free up all resources and data
  * Call shutdown_dma to complete contoller and chan cleanup
  */
-static void __devexit intel_mid_dma_remove(struct pci_dev *pdev)
+static void intel_mid_dma_remove(struct pci_dev *pdev)
 {
        struct middma_device *device = pci_get_drvdata(pdev);
 
index d6668071bd0d4cfca02996978818d65a62ce7630..9b041858d10dcb6bdc1fcbef9eab59006116c96d 100644 (file)
@@ -242,8 +242,7 @@ static struct dca_ops ioat_dca_ops = {
 };
 
 
-struct dca_provider * __devinit
-ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 {
        struct dca_provider *dca;
        struct ioat_dca_priv *ioatdca;
@@ -408,8 +407,7 @@ static int ioat2_dca_count_dca_slots(void __iomem *iobase, u16 dca_offset)
        return slots;
 }
 
-struct dca_provider * __devinit
-ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 {
        struct dca_provider *dca;
        struct ioat_dca_priv *ioatdca;
@@ -621,8 +619,7 @@ static inline int dca3_tag_map_invalid(u8 *tag_map)
                (tag_map[4] == DCA_TAG_MAP_VALID));
 }
 
-struct dca_provider * __devinit
-ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 {
        struct dca_provider *dca;
        struct ioat_dca_priv *ioatdca;
index 73b2b65cb1deed2ccfb16d5f3e81dbeaa47f7ec1..1a68a8ba87e6c74f2f5afb72afac2d0254eae5cd 100644 (file)
@@ -782,7 +782,7 @@ static void ioat1_dma_start_null_desc(struct ioat_dma_chan *ioat)
  */
 #define IOAT_TEST_SIZE 2000
 
-static void __devinit ioat_dma_test_callback(void *dma_async_param)
+static void ioat_dma_test_callback(void *dma_async_param)
 {
        struct completion *cmp = dma_async_param;
 
@@ -793,7 +793,7 @@ static void __devinit ioat_dma_test_callback(void *dma_async_param)
  * ioat_dma_self_test - Perform a IOAT transaction to verify the HW works.
  * @device: device to be tested
  */
-int __devinit ioat_dma_self_test(struct ioatdma_device *device)
+int ioat_dma_self_test(struct ioatdma_device *device)
 {
        int i;
        u8 *src;
@@ -994,7 +994,7 @@ static void ioat_disable_interrupts(struct ioatdma_device *device)
        writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
 }
 
-int __devinit ioat_probe(struct ioatdma_device *device)
+int ioat_probe(struct ioatdma_device *device)
 {
        int err = -ENODEV;
        struct dma_device *dma = &device->common;
@@ -1049,7 +1049,7 @@ err_dma_pool:
        return err;
 }
 
-int __devinit ioat_register(struct ioatdma_device *device)
+int ioat_register(struct ioatdma_device *device)
 {
        int err = dma_async_device_register(&device->common);
 
@@ -1183,7 +1183,7 @@ void ioat_kobject_del(struct ioatdma_device *device)
        }
 }
 
-int __devinit ioat1_dma_probe(struct ioatdma_device *device, int dca)
+int ioat1_dma_probe(struct ioatdma_device *device, int dca)
 {
        struct pci_dev *pdev = device->pdev;
        struct dma_device *dma;
@@ -1216,7 +1216,7 @@ int __devinit ioat1_dma_probe(struct ioatdma_device *device, int dca)
        return err;
 }
 
-void __devexit ioat_dma_remove(struct ioatdma_device *device)
+void ioat_dma_remove(struct ioatdma_device *device)
 {
        struct dma_device *dma = &device->common;
 
index 5e8fe01ba69d574c3eef5cf0cb8f3ab765fb7c72..087935f1565f583df394476ae8bf85abfd84c6d0 100644 (file)
@@ -303,13 +303,12 @@ static inline void ioat_unmap(struct pci_dev *pdev, dma_addr_t addr, size_t len,
                pci_unmap_page(pdev, addr, len, direction);
 }
 
-int __devinit ioat_probe(struct ioatdma_device *device);
-int __devinit ioat_register(struct ioatdma_device *device);
-int __devinit ioat1_dma_probe(struct ioatdma_device *dev, int dca);
-int __devinit ioat_dma_self_test(struct ioatdma_device *device);
-void __devexit ioat_dma_remove(struct ioatdma_device *device);
-struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,
-                                             void __iomem *iobase);
+int ioat_probe(struct ioatdma_device *device);
+int ioat_register(struct ioatdma_device *device);
+int ioat1_dma_probe(struct ioatdma_device *dev, int dca);
+int ioat_dma_self_test(struct ioatdma_device *device);
+void ioat_dma_remove(struct ioatdma_device *device);
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
 dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan);
 void ioat_init_channel(struct ioatdma_device *device,
                       struct ioat_chan_common *chan, int idx);
index b9d66785144511ff294cb59096d6de1b766cbece..82d4e306c32e8d8efb609834d859dc3723fbe30d 100644 (file)
@@ -862,7 +862,7 @@ struct kobj_type ioat2_ktype = {
        .default_attrs = ioat2_attrs,
 };
 
-int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
+int ioat2_dma_probe(struct ioatdma_device *device, int dca)
 {
        struct pci_dev *pdev = device->pdev;
        struct dma_device *dma;
index be2a55b95c2365848a6da33de2bf91269ea97b14..e100f644e3446449d09cc09dbc639d096d75d305 100644 (file)
@@ -155,10 +155,10 @@ static inline void ioat2_set_chainaddr(struct ioat2_dma_chan *ioat, u64 addr)
               chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
 }
 
-int __devinit ioat2_dma_probe(struct ioatdma_device *dev, int dca);
-int __devinit ioat3_dma_probe(struct ioatdma_device *dev, int dca);
-struct dca_provider * __devinit ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
-struct dca_provider * __devinit ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+int ioat2_dma_probe(struct ioatdma_device *dev, int dca);
+int ioat3_dma_probe(struct ioatdma_device *dev, int dca);
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
 int ioat2_check_space_lock(struct ioat2_dma_chan *ioat, int num_descs);
 int ioat2_enumerate_channels(struct ioatdma_device *device);
 struct dma_async_tx_descriptor *
index f7f1dc62c15c1a0dc4d27f676f86eefaebe73e5e..3e9d66920eb3491d85b8c6027ac786a76242e107 100644 (file)
@@ -836,7 +836,7 @@ ioat3_prep_interrupt_lock(struct dma_chan *c, unsigned long flags)
        return &desc->txd;
 }
 
-static void __devinit ioat3_dma_test_callback(void *dma_async_param)
+static void ioat3_dma_test_callback(void *dma_async_param)
 {
        struct completion *cmp = dma_async_param;
 
@@ -844,7 +844,7 @@ static void __devinit ioat3_dma_test_callback(void *dma_async_param)
 }
 
 #define IOAT_NUM_SRC_TEST 6 /* must be <= 8 */
-static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device)
+static int ioat_xor_val_self_test(struct ioatdma_device *device)
 {
        int i, src_idx;
        struct page *dest;
@@ -951,7 +951,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device)
                        goto free_resources;
                }
        }
-       dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE);
+       dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE);
 
        /* skip validate if the capability is not present */
        if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask))
@@ -1096,7 +1096,7 @@ out:
        return err;
 }
 
-static int __devinit ioat3_dma_self_test(struct ioatdma_device *device)
+static int ioat3_dma_self_test(struct ioatdma_device *device)
 {
        int rc = ioat_dma_self_test(device);
 
@@ -1187,7 +1187,7 @@ static bool is_snb_ioat(struct pci_dev *pdev)
        }
 }
 
-int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
+int ioat3_dma_probe(struct ioatdma_device *device, int dca)
 {
        struct pci_dev *pdev = device->pdev;
        int dca_en = system_has_dca_enabled(pdev);
index bfa9a3536e092c6fe465a646a10624921b5814f1..4f686c527ab606750951c98af85acdb007f303ed 100644 (file)
@@ -109,9 +109,8 @@ static struct pci_device_id ioat_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
 
-static int __devinit ioat_pci_probe(struct pci_dev *pdev,
-                                   const struct pci_device_id *id);
-static void __devexit ioat_remove(struct pci_dev *pdev);
+static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void ioat_remove(struct pci_dev *pdev);
 
 static int ioat_dca_enabled = 1;
 module_param(ioat_dca_enabled, int, 0644);
@@ -141,7 +140,7 @@ alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase)
        return d;
 }
 
-static int __devinit ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        void __iomem * const *iomap;
        struct device *dev = &pdev->dev;
@@ -195,7 +194,7 @@ static int __devinit ioat_pci_probe(struct pci_dev *pdev, const struct pci_devic
        return 0;
 }
 
-static void __devexit ioat_remove(struct pci_dev *pdev)
+static void ioat_remove(struct pci_dev *pdev)
 {
        struct ioatdma_device *device = pci_get_drvdata(pdev);
 
index 9072e173b86079b7bc0caea10d25e8b75979bb32..eacb8be99812dc85168d0d521346f5e7f4d01ea6 100644 (file)
@@ -1406,7 +1406,7 @@ out:
 }
 #endif
 
-static int __devexit iop_adma_remove(struct platform_device *dev)
+static int iop_adma_remove(struct platform_device *dev)
 {
        struct iop_adma_device *device = platform_get_drvdata(dev);
        struct dma_chan *chan, *_chan;
index 13bdf4a7e1ec67a0bfe9bfb0e1938707c2d8c339..c6d98c00f05c9bbe64a87696194cc12f29094bb3 100644 (file)
@@ -712,7 +712,7 @@ static void dma_do_tasklet(unsigned long data)
        }
 }
 
-static int __devexit mmp_pdma_remove(struct platform_device *op)
+static int mmp_pdma_remove(struct platform_device *op)
 {
        struct mmp_pdma_device *pdev = platform_get_drvdata(op);
 
index 323821c0c095ecf0001ee3d13826499ca2b0c5ef..a9f1cd56689c06a1995aaca6ee53717ecc28a5e0 100644 (file)
@@ -467,7 +467,7 @@ static void mmp_tdma_issue_pending(struct dma_chan *chan)
        mmp_tdma_enable_chan(tdmac);
 }
 
-static int __devexit mmp_tdma_remove(struct platform_device *pdev)
+static int mmp_tdma_remove(struct platform_device *pdev)
 {
        struct mmp_tdma_device *tdev = platform_get_drvdata(pdev);
 
index 2cd024a91d402103386d1c1e2f749859c3e10849..2d956732aa3d262aa2c5e1c603ff530bab31db78 100644 (file)
@@ -799,7 +799,7 @@ static int mpc_dma_probe(struct platform_device *op)
        return retval;
 }
 
-static int __devexit mpc_dma_remove(struct platform_device *op)
+static int mpc_dma_remove(struct platform_device *op)
 {
        struct device *dev = &op->dev;
        struct mpc_dma *mdma = dev_get_drvdata(dev);
index ac71f555dd729cd0a234f02b473f06271f36ae89..e17fad03cb804b7d538bd2928923a50928475d4f 100644 (file)
@@ -1361,13 +1361,16 @@ static int mv_xor_probe(struct platform_device *pdev)
 err_channel_add:
        for (i = 0; i < MV_XOR_MAX_CHANNELS; i++)
                if (xordev->channels[i]) {
+                       mv_xor_channel_remove(xordev->channels[i]);
                        if (pdev->dev.of_node)
                                irq_dispose_mapping(xordev->channels[i]->irq);
-                       mv_xor_channel_remove(xordev->channels[i]);
                }
 
-       clk_disable_unprepare(xordev->clk);
-       clk_put(xordev->clk);
+       if (!IS_ERR(xordev->clk)) {
+               clk_disable_unprepare(xordev->clk);
+               clk_put(xordev->clk);
+       }
+
        return ret;
 }
 
index eca1c4ddf039db8ff04daf99ee3fbdfc1135904f..3f2617255ef21b07fde6a6d71279e1ec80ba91ce 100644 (file)
@@ -961,7 +961,7 @@ err_free_mem:
        return err;
 }
 
-static void __devexit pch_dma_remove(struct pci_dev *pdev)
+static void pch_dma_remove(struct pci_dev *pdev)
 {
        struct pch_dma *pd = pci_get_drvdata(pdev);
        struct pch_dma_chan *pd_chan;
index 95555f37ea6da96fcd78e0964b493cc4711f189a..80680eee017141aa86f72388e0a98305533e7966 100644 (file)
@@ -2988,7 +2988,7 @@ probe_err1:
        return ret;
 }
 
-static int __devexit pl330_remove(struct amba_device *adev)
+static int pl330_remove(struct amba_device *adev)
 {
        struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
        struct dma_pl330_chan *pch, *_p;
index b94afc339e7f9156624323fb91568981903dc604..5d3d95569a1e76afc6e294a09ccf538846cae9f6 100644 (file)
@@ -4592,7 +4592,7 @@ out:
 /**
  * ppc440spe_adma_remove - remove the asynch device
  */
-static int __devexit ppc440spe_adma_remove(struct platform_device *ofdev)
+static int ppc440spe_adma_remove(struct platform_device *ofdev)
 {
        struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
        struct device_node *np = ofdev->dev.of_node;
@@ -4905,7 +4905,7 @@ out_free:
        return ret;
 }
 
-static const struct of_device_id ppc440spe_adma_of_match[] __devinitconst = {
+static const struct of_device_id ppc440spe_adma_of_match[] = {
        { .compatible   = "ibm,dma-440spe", },
        { .compatible   = "amcc,xor-accelerator", },
        {},
index 2ad628df822303012c56fd6583de54c69f00989f..461a91ab70bb4feca82cd27c1582f81c2905bcde 100644 (file)
@@ -967,7 +967,7 @@ static int sa11x0_dma_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit sa11x0_dma_remove(struct platform_device *pdev)
+static int sa11x0_dma_remove(struct platform_device *pdev)
 {
        struct sa11x0_dma_dev *d = platform_get_drvdata(pdev);
        unsigned pch;
index 8201bb4e0cd7f74397bf1bd4d0960d4ed6cb9a6e..3315e4be9b854e6b100fcfe002b3d616190fbe25 100644 (file)
@@ -880,7 +880,7 @@ ermrdmars:
        return err;
 }
 
-static int __devexit sh_dmae_remove(struct platform_device *pdev)
+static int sh_dmae_remove(struct platform_device *pdev)
 {
        struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
        struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
index c3de6edb96511bdf1e1e1201563f5d6c550fbcb1..94674a96c64613a0b2e79b04a62d4c1f4007c0d0 100644 (file)
@@ -655,7 +655,7 @@ irq_dispose:
        return ret;
 }
 
-static int __devexit sirfsoc_dma_remove(struct platform_device *op)
+static int sirfsoc_dma_remove(struct platform_device *op)
 {
        struct device *dev = &op->dev;
        struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
index efdfffa13349f517d95ee362a9ac37606fed1a16..3cad856fe67f9f9518cbf79b0f02bd41c32733b8 100644 (file)
@@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get(
                if (async_tx_test_ack(&dma_desc->txd)) {
                        list_del(&dma_desc->node);
                        spin_unlock_irqrestore(&tdc->lock, flags);
+                       dma_desc->txd.flags = 0;
                        return dma_desc;
                }
        }
@@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
                                        TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT;
        ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
 
-       csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC;
+       csr |= TEGRA_APBDMA_CSR_FLOW;
+       if (flags & DMA_PREP_INTERRUPT)
+               csr |= TEGRA_APBDMA_CSR_IE_EOC;
        csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
 
        apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
@@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
                mem += len;
        }
        sg_req->last_sg = true;
-       dma_desc->txd.flags = 0;
+       if (flags & DMA_CTRL_ACK)
+               dma_desc->txd.flags = DMA_CTRL_ACK;
 
        /*
         * Make sure that mode should not be conflicting with currently
@@ -1184,7 +1188,7 @@ static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
        .max_dma_count          = 1024UL * 64,
 };
 
-static const struct of_device_id tegra_dma_of_match[] __devinitconst = {
+static const struct of_device_id tegra_dma_of_match[] = {
        {
                .compatible = "nvidia,tegra30-apbdma",
                .data = &tegra30_dma_chip_data,
@@ -1360,7 +1364,7 @@ err_pm_disable:
        return ret;
 }
 
-static int __devexit tegra_dma_remove(struct platform_device *pdev)
+static int tegra_dma_remove(struct platform_device *pdev)
 {
        struct tegra_dma *tdma = platform_get_drvdata(pdev);
        int i;
@@ -1403,7 +1407,7 @@ static int tegra_dma_runtime_resume(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops tegra_dma_dev_pm_ops __devinitconst = {
+static const struct dev_pm_ops tegra_dma_dev_pm_ops = {
 #ifdef CONFIG_PM_RUNTIME
        .runtime_suspend = tegra_dma_runtime_suspend,
        .runtime_resume = tegra_dma_runtime_resume,
index 98cf51e1544c54d6bf61e98b709fcc5fae6a44de..952f823901a6cb5d168ce0b90f2429383ed5bfc3 100644 (file)
@@ -798,7 +798,7 @@ err_release_region:
 
 }
 
-static int __devexit td_remove(struct platform_device *pdev)
+static int td_remove(struct platform_device *pdev)
 {
        struct timb_dma *td = platform_get_drvdata(pdev);
        struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 4c6c876d9dc3f0fa949352c89039a00b3c0bc79a..66719925970f74755865320e81a83fb43a5d8992 100644 (file)
@@ -4,6 +4,9 @@
 #      Licensed and distributed under the GPL
 #
 
+config EDAC_SUPPORT
+       bool
+
 menuconfig EDAC
        bool "EDAC (Error Detection And Correction) reporting"
        depends on HAS_IOMEM
@@ -27,13 +30,8 @@ menuconfig EDAC
          There is also a mailing list for the EDAC project, which can
          be found via the sourceforge page.
 
-config EDAC_SUPPORT
-       bool
-
 if EDAC
 
-comment "Reporting subsystems"
-
 config EDAC_LEGACY_SYSFS
        bool "EDAC legacy sysfs"
        default y
index f74a684269ff6c8ceb25241d82816ddbab035888..ad8bf2aa629d3b23510053f6c88b23c0c2d9d504 100644 (file)
@@ -2563,8 +2563,8 @@ err_ret:
        return ret;
 }
 
-static int __devinit amd64_probe_one_instance(struct pci_dev *pdev,
-                                            const struct pci_device_id *mc_type)
+static int amd64_probe_one_instance(struct pci_dev *pdev,
+                                   const struct pci_device_id *mc_type)
 {
        u8 nid = get_node_id(pdev);
        struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
@@ -2612,7 +2612,7 @@ err_out:
        return ret;
 }
 
-static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
+static void amd64_remove_one_instance(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct amd64_pvt *pvt;
@@ -2686,7 +2686,7 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table);
 static struct pci_driver amd64_pci_driver = {
        .name           = EDAC_MOD_STR,
        .probe          = amd64_probe_one_instance,
-       .remove         = __devexit_p(amd64_remove_one_instance),
+       .remove         = amd64_remove_one_instance,
        .id_table       = amd64_pci_table,
 };
 
index 29eeb68a200caf7cb091698d1acbecf4eca80bcb..96e3ee3460a566a96928eb45b332ced184902fe8 100644 (file)
@@ -301,8 +301,8 @@ fail:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit amd76x_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int amd76x_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        edac_dbg(0, "\n");
 
@@ -318,7 +318,7 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev,
  *     structure for the device then delete the mci and free the
  *     resources.
  */
-static void __devexit amd76x_remove_one(struct pci_dev *pdev)
+static void amd76x_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
 static struct pci_driver amd76x_driver = {
        .name = EDAC_MOD_STR,
        .probe = amd76x_init_one,
-       .remove = __devexit_p(amd76x_remove_one),
+       .remove = amd76x_remove_one,
        .id_table = amd76x_pci_tbl,
 };
 
index a1bbd8edd2575e4faf0633c972f1a6cf12a3815a..c2eaf334b90b0f4c2cff3cc4039c1c85577fbcaf 100644 (file)
@@ -124,7 +124,7 @@ static void cell_edac_check(struct mem_ctl_info *mci)
        }
 }
 
-static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
+static void cell_edac_init_csrows(struct mem_ctl_info *mci)
 {
        struct csrow_info               *csrow = mci->csrows[0];
        struct dimm_info                *dimm;
@@ -164,7 +164,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
        }
 }
 
-static int __devinit cell_edac_probe(struct platform_device *pdev)
+static int cell_edac_probe(struct platform_device *pdev)
 {
        struct cbe_mic_tm_regs __iomem  *regs;
        struct mem_ctl_info             *mci;
@@ -233,7 +233,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit cell_edac_remove(struct platform_device *pdev)
+static int cell_edac_remove(struct platform_device *pdev)
 {
        struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev);
        if (mci)
@@ -247,7 +247,7 @@ static struct platform_driver cell_edac_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = cell_edac_probe,
-       .remove         = __devexit_p(cell_edac_remove),
+       .remove         = cell_edac_remove,
 };
 
 static int __init cell_edac_init(void)
index c2ef1349587368d666d9465a3c6996b893d10771..7f3c57113ba11c1d8867a3cdd4f65894c3b37f29 100644 (file)
@@ -932,7 +932,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase)
        return dual;
 }
 
-static int __devinit cpc925_probe(struct platform_device *pdev)
+static int cpc925_probe(struct platform_device *pdev)
 {
        static int edac_mc_idx;
        struct mem_ctl_info *mci;
index a5ed6b795fd4331452dd112626218c102f565d40..644fec54681fcb5c56bac57a5ced18505ee4da46 100644 (file)
@@ -1390,8 +1390,7 @@ fail:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit e752x_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        edac_dbg(0, "\n");
 
@@ -1402,7 +1401,7 @@ static int __devinit e752x_init_one(struct pci_dev *pdev,
        return e752x_probe1(pdev, ent->driver_data);
 }
 
-static void __devexit e752x_remove_one(struct pci_dev *pdev)
+static void e752x_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct e752x_pvt *pvt;
@@ -1445,7 +1444,7 @@ MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
 static struct pci_driver e752x_driver = {
        .name = EDAC_MOD_STR,
        .probe = e752x_init_one,
-       .remove = __devexit_p(e752x_remove_one),
+       .remove = e752x_remove_one,
        .id_table = e752x_pci_tbl,
 };
 
index 9ff57f361a43384e0d86be624067fb64cdc6e36b..1c4056a5038396e11c10945d695de060d00ad47c 100644 (file)
@@ -528,8 +528,7 @@ fail0:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit e7xxx_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        edac_dbg(0, "\n");
 
@@ -538,7 +537,7 @@ static int __devinit e7xxx_init_one(struct pci_dev *pdev,
                -EIO : e7xxx_probe1(pdev, ent->driver_data);
 }
 
-static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
+static void e7xxx_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct e7xxx_pvt *pvt;
@@ -579,7 +578,7 @@ MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
 static struct pci_driver e7xxx_driver = {
        .name = EDAC_MOD_STR,
        .probe = e7xxx_init_one,
-       .remove = __devexit_p(e7xxx_remove_one),
+       .remove = e7xxx_remove_one,
        .id_table = e7xxx_pci_tbl,
 };
 
index 281f566a5513d907fefc67da9237a2ec41ab8679..d1e9eb191f2bd77ff72614c0819885d31dcf473d 100644 (file)
@@ -340,7 +340,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
        /*
         * Alocate and fill the csrow/channels structs
         */
-       mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL);
+       mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL);
        if (!mci->csrows)
                goto error;
        for (row = 0; row < tot_csrows; row++) {
@@ -351,7 +351,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
                csr->csrow_idx = row;
                csr->mci = mci;
                csr->nr_channels = tot_channels;
-               csr->channels = kcalloc(sizeof(*csr->channels), tot_channels,
+               csr->channels = kcalloc(tot_channels, sizeof(*csr->channels),
                                        GFP_KERNEL);
                if (!csr->channels)
                        goto error;
@@ -369,7 +369,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
        /*
         * Allocate and fill the dimm structs
         */
-       mci->dimms  = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL);
+       mci->dimms  = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL);
        if (!mci->dimms)
                goto error;
 
index de2df92f9c77126709d2c8388b2d88ba7f6ed55c..0ca1ca71157f2b7320e418d13deceeb63965c030 100644 (file)
@@ -472,8 +472,7 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
                        device_remove_file(&csrow->dev,
                                                dynamic_csrow_ce_count_attr[chan]);
                }
-               put_device(&mci->csrows[i]->dev);
-               device_del(&mci->csrows[i]->dev);
+               device_unregister(&mci->csrows[i]->dev);
        }
 }
 #endif
@@ -1055,11 +1054,9 @@ fail:
                struct dimm_info *dimm = mci->dimms[i];
                if (dimm->nr_pages == 0)
                        continue;
-               put_device(&dimm->dev);
-               device_del(&dimm->dev);
+               device_unregister(&dimm->dev);
        }
-       put_device(&mci->dev);
-       device_del(&mci->dev);
+       device_unregister(&mci->dev);
        bus_unregister(&mci->bus);
        kfree(mci->bus.name);
        return err;
@@ -1086,16 +1083,14 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
                if (dimm->nr_pages == 0)
                        continue;
                edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev));
-               put_device(&dimm->dev);
-               device_del(&dimm->dev);
+               device_unregister(&dimm->dev);
        }
 }
 
 void edac_unregister_sysfs(struct mem_ctl_info *mci)
 {
        edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
-       put_device(&mci->dev);
-       device_del(&mci->dev);
+       device_unregister(&mci->dev);
        bus_unregister(&mci->bus);
        kfree(mci->bus.name);
 }
@@ -1159,8 +1154,6 @@ int __init edac_mc_sysfs_init(void)
 
 void __exit edac_mc_sysfs_exit(void)
 {
-       put_device(mci_pdev);
-       device_del(mci_pdev);
+       device_unregister(mci_pdev);
        edac_put_sysfs_subsys();
-       kfree(mci_pdev);
 }
index dc6e905ee1a5402126496bd06838302a1b26165f..0056c4dae9d52cc24985200dbb58b724be73c3ed 100644 (file)
@@ -256,7 +256,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj,
        struct edac_pci_dev_attribute *edac_pci_dev;
        edac_pci_dev = (struct edac_pci_dev_attribute *)attr;
 
-       if (edac_pci_dev->show)
+       if (edac_pci_dev->store)
                return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
        return -EIO;
 }
index e599b00c05a823f788ce5c36e17f740cdb06e91d..c2bd8c6a43499b74d4c29a0490a49a89a6ead12b 100644 (file)
@@ -50,7 +50,7 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit highbank_l2_err_probe(struct platform_device *pdev)
+static int highbank_l2_err_probe(struct platform_device *pdev)
 {
        struct edac_device_ctl_info *dci;
        struct hb_l2_drvdata *drvdata;
index 7ea4cc2e8bd2292ca8871b6d27493d94ab9cda80..4695dd2d71fd87b6886a4947786ce9290c540127 100644 (file)
@@ -119,7 +119,7 @@ static const struct file_operations highbank_mc_debug_inject_fops = {
        .llseek = generic_file_llseek,
 };
 
-static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
 {
        if (mci->debugfs)
                debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
@@ -127,11 +127,11 @@ static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
 ;
 }
 #else
-static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
 {}
 #endif
 
-static int __devinit highbank_mc_probe(struct platform_device *pdev)
+static int highbank_mc_probe(struct platform_device *pdev)
 {
        struct edac_mc_layer layers[2];
        struct mem_ctl_info *mci;
index d3d19cc4e9a1a48eccb84820dbe8df519955cc96..694efcbf19c097d45f715c06eda1f234bc89788c 100644 (file)
@@ -455,8 +455,7 @@ fail:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit i3000_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int i3000_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int rc;
 
@@ -472,7 +471,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i3000_remove_one(struct pci_dev *pdev)
+static void i3000_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -502,7 +501,7 @@ MODULE_DEVICE_TABLE(pci, i3000_pci_tbl);
 static struct pci_driver i3000_driver = {
        .name = EDAC_MOD_STR,
        .probe = i3000_init_one,
-       .remove = __devexit_p(i3000_remove_one),
+       .remove = i3000_remove_one,
        .id_table = i3000_pci_tbl,
 };
 
index b6653a6fc5d56af68e55b0f2ea10855a1927ee2f..4e8337602e781fed8d99ffbbb099a5523e585160 100644 (file)
@@ -419,8 +419,7 @@ fail:
        return rc;
 }
 
-static int __devinit i3200_init_one(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
+static int i3200_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int rc;
 
@@ -436,7 +435,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i3200_remove_one(struct pci_dev *pdev)
+static void i3200_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct i3200_priv *priv;
@@ -467,7 +466,7 @@ MODULE_DEVICE_TABLE(pci, i3200_pci_tbl);
 static struct pci_driver i3200_driver = {
        .name = EDAC_MOD_STR,
        .probe = i3200_init_one,
-       .remove = __devexit_p(i3200_remove_one),
+       .remove = i3200_remove_one,
        .id_table = i3200_pci_tbl,
 };
 
index 6a49dd00b81b8fce1181a0e0d436bb8e4ce211d5..63b2194e8c20683b38570d269300c82e96d8a3bf 100644 (file)
@@ -1489,8 +1489,7 @@ fail0:
  *             negative on error
  *             count (>= 0)
  */
-static int __devinit i5000_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *id)
+static int i5000_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rc;
 
@@ -1509,7 +1508,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev,
  *     i5000_remove_one        destructor for one instance of device
  *
  */
-static void __devexit i5000_remove_one(struct pci_dev *pdev)
+static void i5000_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -1547,7 +1546,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl);
 static struct pci_driver i5000_driver = {
        .name = KBUILD_BASENAME,
        .probe = i5000_init_one,
-       .remove = __devexit_p(i5000_remove_one),
+       .remove = i5000_remove_one,
        .id_table = i5000_pci_tbl,
 };
 
index c4b5e5f868e85ea1e60b0a301d0a7bdc68585a2e..d6955b2cc99fa47bc9ac665fa93eb5f59cafc88e 100644 (file)
@@ -638,8 +638,7 @@ static struct pci_dev *pci_get_device_func(unsigned vendor,
        return ret;
 }
 
-static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
-                                           int csrow)
+static unsigned long i5100_npages(struct mem_ctl_info *mci, int csrow)
 {
        struct i5100_priv *priv = mci->pvt_info;
        const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow);
@@ -660,7 +659,7 @@ static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
                ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
 }
 
-static void __devinit i5100_init_mtr(struct mem_ctl_info *mci)
+static void i5100_init_mtr(struct mem_ctl_info *mci)
 {
        struct i5100_priv *priv = mci->pvt_info;
        struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
@@ -732,7 +731,7 @@ static int i5100_read_spd_byte(const struct mem_ctl_info *mci,
  *   o not the only way to may chip selects to dimm slots
  *   o investigate if there is some way to obtain this map from the bios
  */
-static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
+static void i5100_init_dimm_csmap(struct mem_ctl_info *mci)
 {
        struct i5100_priv *priv = mci->pvt_info;
        int i;
@@ -762,8 +761,8 @@ static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
        }
 }
 
-static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
-                                            struct mem_ctl_info *mci)
+static void i5100_init_dimm_layout(struct pci_dev *pdev,
+                                  struct mem_ctl_info *mci)
 {
        struct i5100_priv *priv = mci->pvt_info;
        int i;
@@ -784,8 +783,8 @@ static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
        i5100_init_dimm_csmap(mci);
 }
 
-static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
-                                             struct mem_ctl_info *mci)
+static void i5100_init_interleaving(struct pci_dev *pdev,
+                                   struct mem_ctl_info *mci)
 {
        u16 w;
        u32 dw;
@@ -830,7 +829,7 @@ static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
        i5100_init_mtr(mci);
 }
 
-static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
+static void i5100_init_csrows(struct mem_ctl_info *mci)
 {
        int i;
        struct i5100_priv *priv = mci->pvt_info;
@@ -864,8 +863,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
        }
 }
 
-static int __devinit i5100_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
+static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rc;
        struct mem_ctl_info *mci;
@@ -1020,7 +1018,7 @@ bail:
        return ret;
 }
 
-static void __devexit i5100_remove_one(struct pci_dev *pdev)
+static void i5100_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct i5100_priv *priv;
@@ -1054,7 +1052,7 @@ MODULE_DEVICE_TABLE(pci, i5100_pci_tbl);
 static struct pci_driver i5100_driver = {
        .name = KBUILD_BASENAME,
        .probe = i5100_init_one,
-       .remove = __devexit_p(i5100_remove_one),
+       .remove = i5100_remove_one,
        .id_table = i5100_pci_tbl,
 };
 
index 277246998b805024517f0641841996e8bfd85d29..0a05bbceb08f4e870eb97f50443f6c7e6447676a 100644 (file)
@@ -1373,8 +1373,7 @@ fail0:
  *             negative on error
  *             count (>= 0)
  */
-static int __devinit i5400_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *id)
+static int i5400_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rc;
 
@@ -1393,7 +1392,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev,
  *     i5400_remove_one        destructor for one instance of device
  *
  */
-static void __devexit i5400_remove_one(struct pci_dev *pdev)
+static void i5400_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -1431,7 +1430,7 @@ MODULE_DEVICE_TABLE(pci, i5400_pci_tbl);
 static struct pci_driver i5400_driver = {
        .name = "i5400_edac",
        .probe = i5400_init_one,
-       .remove = __devexit_p(i5400_remove_one),
+       .remove = i5400_remove_one,
        .id_table = i5400_pci_tbl,
 };
 
index 9d669cd43618b605d7db354fde86df8c90c64f08..087c27bc5d4247b9b7647f4c4c7695e6a2445036 100644 (file)
@@ -923,7 +923,7 @@ static void i7300_put_devices(struct mem_ctl_info *mci)
  *    Device 21 function 0:            PCI_DEVICE_ID_INTEL_I7300_MCH_FB0
  *    Device 22 function 0:            PCI_DEVICE_ID_INTEL_I7300_MCH_FB1
  */
-static int __devinit i7300_get_devices(struct mem_ctl_info *mci)
+static int i7300_get_devices(struct mem_ctl_info *mci)
 {
        struct i7300_pvt *pvt;
        struct pci_dev *pdev;
@@ -1008,8 +1008,7 @@ error:
  * @pdev: struct pci_dev pointer
  * @id: struct pci_device_id pointer - currently unused
  */
-static int __devinit i7300_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
+static int i7300_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer layers[3];
@@ -1122,7 +1121,7 @@ fail0:
  * i7300_remove_one() - Remove the driver
  * @pdev: struct pci_dev pointer
  */
-static void __devexit i7300_remove_one(struct pci_dev *pdev)
+static void i7300_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        char *tmp;
@@ -1163,7 +1162,7 @@ MODULE_DEVICE_TABLE(pci, i7300_pci_tbl);
 static struct pci_driver i7300_driver = {
        .name = "i7300_edac",
        .probe = i7300_init_one,
-       .remove = __devexit_p(i7300_remove_one),
+       .remove = i7300_remove_one,
        .id_table = i7300_pci_tbl,
 };
 
index 10c8c00d6469398a211dc23b413d4d6495851b5a..e213d030b0dd7968756193f185a5661b7a4b9441 100644 (file)
@@ -2305,8 +2305,7 @@ fail0:
  *             < 0 for error code
  */
 
-static int __devinit i7core_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id)
+static int i7core_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rc, count = 0;
        struct i7core_dev *i7core_dev;
@@ -2368,7 +2367,7 @@ fail0:
  *     i7core_remove   destructor for one instance of device
  *
  */
-static void __devexit i7core_remove(struct pci_dev *pdev)
+static void i7core_remove(struct pci_dev *pdev)
 {
        struct i7core_dev *i7core_dev;
 
@@ -2409,7 +2408,7 @@ MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
 static struct pci_driver i7core_driver = {
        .name     = "i7core_edac",
        .probe    = i7core_probe,
-       .remove   = __devexit_p(i7core_remove),
+       .remove   = i7core_remove,
        .id_table = i7core_pci_tbl,
 };
 
index 90f303db5d1dfd0d6ee0b4d77a0e1b899834fa68..57fdb77903ba9a142513a94cabd7b5775defed1a 100644 (file)
@@ -353,8 +353,8 @@ fail:
 EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1);
 
 /* returns count (>= 0), or negative on error */
-static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
-                                               const struct pci_device_id *ent)
+static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent)
 {
        int rc;
 
@@ -369,7 +369,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
+static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -399,7 +399,7 @@ MODULE_DEVICE_TABLE(pci, i82443bxgx_pci_tbl);
 static struct pci_driver i82443bxgx_edacmc_driver = {
        .name = EDAC_MOD_STR,
        .probe = i82443bxgx_edacmc_init_one,
-       .remove = __devexit_p(i82443bxgx_edacmc_remove_one),
+       .remove = i82443bxgx_edacmc_remove_one,
        .id_table = i82443bxgx_pci_tbl,
 };
 
index 1faa749715131c1e19b34134d6c01626fb34dd7a..3e3e431c83011313dadc901afe8347501a23e911 100644 (file)
@@ -254,8 +254,8 @@ fail:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit i82860_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int i82860_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        int rc;
 
@@ -273,7 +273,7 @@ static int __devinit i82860_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i82860_remove_one(struct pci_dev *pdev)
+static void i82860_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
 static struct pci_driver i82860_driver = {
        .name = EDAC_MOD_STR,
        .probe = i82860_init_one,
-       .remove = __devexit_p(i82860_remove_one),
+       .remove = i82860_remove_one,
        .id_table = i82860_pci_tbl,
 };
 
index 3e416b1a6b53680b3f5d78f3a579fb04439caa62..2f8535fc451e64745be644b6a685b6be414005ed 100644 (file)
@@ -479,8 +479,8 @@ fail0:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit i82875p_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int i82875p_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        int rc;
 
@@ -498,7 +498,7 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i82875p_remove_one(struct pci_dev *pdev)
+static void i82875p_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct i82875p_pvt *pvt = NULL;
@@ -541,7 +541,7 @@ MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
 static struct pci_driver i82875p_driver = {
        .name = EDAC_MOD_STR,
        .probe = i82875p_init_one,
-       .remove = __devexit_p(i82875p_remove_one),
+       .remove = i82875p_remove_one,
        .id_table = i82875p_pci_tbl,
 };
 
index a98020409fa9933181fe93a550fdb2abaf572ebd..0c8d4b0eaa32876c1eecc8f83b708242244855a1 100644 (file)
@@ -592,8 +592,8 @@ fail0:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit i82975x_init_one(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
+static int i82975x_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        int rc;
 
@@ -610,7 +610,7 @@ static int __devinit i82975x_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit i82975x_remove_one(struct pci_dev *pdev)
+static void i82975x_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct i82975x_pvt *pvt;
@@ -643,7 +643,7 @@ MODULE_DEVICE_TABLE(pci, i82975x_pci_tbl);
 static struct pci_driver i82975x_driver = {
        .name = EDAC_MOD_STR,
        .probe = i82975x_init_one,
-       .remove = __devexit_p(i82975x_remove_one),
+       .remove = i82975x_remove_one,
        .id_table = i82975x_pci_tbl,
 };
 
index 4fe66fa183ec964acc27781ed8f8b90eaaaa41eb..42a840d530a527ef5c6cad6da6de932bacd4f6aa 100644 (file)
@@ -212,7 +212,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int mpc85xx_pci_err_probe(struct platform_device *op)
 {
        struct edac_pci_ctl_info *pci;
        struct mpc85xx_pci_pdata *pdata;
@@ -504,7 +504,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_l2_err_probe(struct platform_device *op)
+static int mpc85xx_l2_err_probe(struct platform_device *op)
 {
        struct edac_device_ctl_info *edac_dev;
        struct mpc85xx_l2_pdata *pdata;
@@ -885,7 +885,7 @@ static irqreturn_t mpc85xx_mc_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
+static void mpc85xx_init_csrows(struct mem_ctl_info *mci)
 {
        struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
        struct csrow_info *csrow;
@@ -964,7 +964,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
        }
 }
 
-static int __devinit mpc85xx_mc_err_probe(struct platform_device *op)
+static int mpc85xx_mc_err_probe(struct platform_device *op)
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer layers[2];
index 2b315c2edc3cac14c5247e33a398283fd098b26d..542fad70e360d60f7c51c7db8f39ab9dc3de9038 100644 (file)
@@ -100,7 +100,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
+static int mv64x60_pci_err_probe(struct platform_device *pdev)
 {
        struct edac_pci_ctl_info *pci;
        struct mv64x60_pci_pdata *pdata;
@@ -221,7 +221,7 @@ static int mv64x60_pci_err_remove(struct platform_device *pdev)
 
 static struct platform_driver mv64x60_pci_err_driver = {
        .probe = mv64x60_pci_err_probe,
-       .remove = __devexit_p(mv64x60_pci_err_remove),
+       .remove = mv64x60_pci_err_remove,
        .driver = {
                   .name = "mv64x60_pci_err",
        }
@@ -271,7 +271,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev)
+static int mv64x60_sram_err_probe(struct platform_device *pdev)
 {
        struct edac_device_ctl_info *edac_dev;
        struct mv64x60_sram_pdata *pdata;
@@ -439,7 +439,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev)
+static int mv64x60_cpu_err_probe(struct platform_device *pdev)
 {
        struct edac_device_ctl_info *edac_dev;
        struct resource *r;
@@ -697,7 +697,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
        dimm->edac_mode = EDAC_SECDED;
 }
 
-static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
+static int mv64x60_mc_err_probe(struct platform_device *pdev)
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer layers[2];
index 40fde6a51ed6f820220a3ca7f1b9b276d5376a25..7e98084d36451efe894f5f33c1a3b77748183af3 100644 (file)
@@ -131,7 +131,7 @@ static void octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c)
                _octeon_l2c_poll_oct2(l2c, i);
 }
 
-static int __devinit octeon_l2c_probe(struct platform_device *pdev)
+static int octeon_l2c_probe(struct platform_device *pdev)
 {
        struct edac_device_ctl_info *l2c;
 
index 33bca766e37d236ce30132e1b339b7fbcd710b45..93412d6b3af1703ccfd220aa759fbf8d553eeec7 100644 (file)
@@ -86,7 +86,7 @@ static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci)
                cvmx_write_csr(CVMX_LMCX_INT(mci->mc_idx), int_reg.u64);
 }
 
-static int __devinit octeon_lmc_edac_probe(struct platform_device *pdev)
+static int octeon_lmc_edac_probe(struct platform_device *pdev)
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer layers[1];
index 14a5e57f2b32218ebf0276a712a5d46e34bdc628..0f83c33a7d1fcbb08180d60609aafc92e76a6425 100644 (file)
@@ -82,7 +82,7 @@ static int  co_cache_error_event(struct notifier_block *this,
        return NOTIFY_STOP;
 }
 
-static int __devinit co_cache_error_probe(struct platform_device *pdev)
+static int co_cache_error_probe(struct platform_device *pdev)
 {
        struct co_cache_error *p = devm_kzalloc(&pdev->dev, sizeof(*p),
                                                GFP_KERNEL);
index 758c1ef5fc9ea12fba2c93d593bf95b4ceb93c07..9ca73cec74e75a7d4476d3f387ccfb7a022dc1a0 100644 (file)
@@ -58,7 +58,7 @@ static void octeon_pci_poll(struct edac_pci_ctl_info *pci)
        }
 }
 
-static int __devinit octeon_pci_probe(struct platform_device *pdev)
+static int octeon_pci_probe(struct platform_device *pdev)
 {
        struct edac_pci_ctl_info *pci;
        int res = 0;
index 2d35b78ada3c819a5879d9357eadbb5ec2da00e7..9c971b57553022ec7857ae6b1ca41c03bc551584 100644 (file)
@@ -188,8 +188,8 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci,
        return 0;
 }
 
-static int __devinit pasemi_edac_probe(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
+static int pasemi_edac_probe(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        struct mem_ctl_info *mci = NULL;
        struct edac_mc_layer layers[2];
@@ -266,7 +266,7 @@ fail:
        return -ENODEV;
 }
 
-static void __devexit pasemi_edac_remove(struct pci_dev *pdev)
+static void pasemi_edac_remove(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev);
 
@@ -287,7 +287,7 @@ MODULE_DEVICE_TABLE(pci, pasemi_edac_pci_tbl);
 static struct pci_driver pasemi_edac_driver = {
        .name = MODULE_NAME,
        .probe = pasemi_edac_probe,
-       .remove = __devexit_p(pasemi_edac_remove),
+       .remove = pasemi_edac_remove,
        .id_table = pasemi_edac_pci_tbl,
 };
 
index bf09576359911c51f8d548b04605387c77466a1e..ef6b7e08f4856817163ef6dbf9d14aee90c65b9a 100644 (file)
@@ -838,8 +838,7 @@ ppc4xx_edac_isr(int irq, void *dev_id)
  *
  * Returns a device type width enumeration.
  */
-static enum dev_type __devinit
-ppc4xx_edac_get_dtype(u32 mcopt1)
+static enum dev_type ppc4xx_edac_get_dtype(u32 mcopt1)
 {
        switch (mcopt1 & SDRAM_MCOPT1_WDTH_MASK) {
        case SDRAM_MCOPT1_WDTH_16:
@@ -862,8 +861,7 @@ ppc4xx_edac_get_dtype(u32 mcopt1)
  *
  * Returns a memory type enumeration.
  */
-static enum mem_type __devinit
-ppc4xx_edac_get_mtype(u32 mcopt1)
+static enum mem_type ppc4xx_edac_get_mtype(u32 mcopt1)
 {
        bool rden = ((mcopt1 & SDRAM_MCOPT1_RDEN_MASK) == SDRAM_MCOPT1_RDEN);
 
@@ -893,8 +891,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1)
  * Returns 0 if OK; otherwise, -EINVAL if the memory bank size
  * configuration cannot be determined.
  */
-static int __devinit
-ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
+static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
 {
        const struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
        int status = 0;
@@ -1011,11 +1008,9 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
  *
  * Returns 0 if OK; otherwise, < 0 on error.
  */
-static int __devinit
-ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
-                   struct platform_device *op,
-                   const dcr_host_t *dcr_host,
-                   u32 mcopt1)
+static int ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
+                              struct platform_device *op,
+                              const dcr_host_t *dcr_host, u32 mcopt1)
 {
        int status = 0;
        const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
@@ -1105,8 +1100,8 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
  * Returns 0 if OK; otherwise, -ENODEV if the interrupts could not be
  * mapped and assigned.
  */
-static int __devinit
-ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci)
+static int ppc4xx_edac_register_irq(struct platform_device *op,
+                                   struct mem_ctl_info *mci)
 {
        int status = 0;
        int ded_irq, sec_irq;
@@ -1183,8 +1178,8 @@ ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci)
  * Returns 0 if the DCRs were successfully mapped; otherwise, < 0 on
  * error.
  */
-static int __devinit
-ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host)
+static int ppc4xx_edac_map_dcrs(const struct device_node *np,
+                               dcr_host_t *dcr_host)
 {
        unsigned int dcr_base, dcr_len;
 
@@ -1232,7 +1227,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host)
  * Returns 0 if the controller instance was successfully bound to the
  * driver; otherwise, < 0 on error.
  */
-static int __devinit ppc4xx_edac_probe(struct platform_device *op)
+static int ppc4xx_edac_probe(struct platform_device *op)
 {
        int status = 0;
        u32 mcopt1, memcheck;
index f854debd553306a6eeae079067c2a35bc6a5988d..2fd6a549090584b8ac69848acfd30750a9f68e0b 100644 (file)
@@ -359,8 +359,8 @@ fail:
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit r82600_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int r82600_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        edac_dbg(0, "\n");
 
@@ -368,7 +368,7 @@ static int __devinit r82600_init_one(struct pci_dev *pdev,
        return r82600_probe1(pdev, ent->driver_data);
 }
 
-static void __devexit r82600_remove_one(struct pci_dev *pdev)
+static void r82600_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -397,7 +397,7 @@ MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
 static struct pci_driver r82600_driver = {
        .name = EDAC_MOD_STR,
        .probe = r82600_init_one,
-       .remove = __devexit_p(r82600_remove_one),
+       .remove = r82600_remove_one,
        .id_table = r82600_pci_tbl,
 };
 
index 5715b7c2c5177a6c76ed732fb6f20de9b7578220..da7e2986e3d53c9aa721b9f1dd60901672828cc4 100644 (file)
@@ -1692,8 +1692,7 @@ fail0:
  *             < 0 for error code
  */
 
-static int __devinit sbridge_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id)
+static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rc;
        u8 mc, num_mc = 0;
@@ -1744,7 +1743,7 @@ fail0:
  *     sbridge_remove  destructor for one instance of device
  *
  */
-static void __devexit sbridge_remove(struct pci_dev *pdev)
+static void sbridge_remove(struct pci_dev *pdev)
 {
        struct sbridge_dev *sbridge_dev;
 
@@ -1785,7 +1784,7 @@ MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
 static struct pci_driver sbridge_driver = {
        .name     = "sbridge_edac",
        .probe    = sbridge_probe,
-       .remove   = __devexit_p(sbridge_remove),
+       .remove   = sbridge_remove,
        .id_table = sbridge_pci_tbl,
 };
 
index 1e904b7b79a042671c83bb10e07547bfcf3eee12..a0820536b7d9d8edf0905ed04bf913d6fb6f21db 100644 (file)
@@ -82,7 +82,7 @@ static void tile_edac_check(struct mem_ctl_info *mci)
  * Initialize the 'csrows' table within the mci control structure with the
  * addressing of memory.
  */
-static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
+static int tile_edac_init_csrows(struct mem_ctl_info *mci)
 {
        struct csrow_info       *csrow = mci->csrows[0];
        struct tile_edac_priv   *priv = mci->pvt_info;
@@ -120,7 +120,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
        return 0;
 }
 
-static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
+static int tile_edac_mc_probe(struct platform_device *pdev)
 {
        char                    hv_file[32];
        int                     hv_devhdl;
@@ -186,7 +186,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tile_edac_mc_remove(struct platform_device *pdev)
+static int tile_edac_mc_remove(struct platform_device *pdev)
 {
        struct mem_ctl_info *mci = platform_get_drvdata(pdev);
 
@@ -202,7 +202,7 @@ static struct platform_driver tile_edac_mc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tile_edac_mc_probe,
-       .remove         = __devexit_p(tile_edac_mc_remove),
+       .remove         = tile_edac_mc_remove,
 };
 
 /*
index 08a992693e62ed8b7e994782ce824945001f220a..c9db24d95caad3b7550f936a24bd802428b8d4e2 100644 (file)
@@ -418,8 +418,7 @@ fail:
        return rc;
 }
 
-static int __devinit x38_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int x38_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int rc;
 
@@ -435,7 +434,7 @@ static int __devinit x38_init_one(struct pci_dev *pdev,
        return rc;
 }
 
-static void __devexit x38_remove_one(struct pci_dev *pdev)
+static void x38_remove_one(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
 
@@ -464,7 +463,7 @@ MODULE_DEVICE_TABLE(pci, x38_pci_tbl);
 static struct pci_driver x38_driver = {
        .name = EDAC_MOD_STR,
        .probe = x38_init_one,
-       .remove = __devexit_p(x38_remove_one),
+       .remove = x38_remove_one,
        .id_table = x38_pci_tbl,
 };
 
index ea5ac2dc1233748a7722fec6df4e5d3aa0b44f49..8e77c02edb24608d10aff9c186ce95aa0f4e5e47 100644 (file)
@@ -537,7 +537,7 @@ static struct attribute_group dcdbas_attr_group = {
        .attrs = dcdbas_dev_attrs,
 };
 
-static int __devinit dcdbas_probe(struct platform_device *dev)
+static int dcdbas_probe(struct platform_device *dev)
 {
        int i, error;
 
@@ -575,7 +575,7 @@ static int __devinit dcdbas_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit dcdbas_remove(struct platform_device *dev)
+static int dcdbas_remove(struct platform_device *dev)
 {
        int i;
 
@@ -593,7 +593,7 @@ static struct platform_driver dcdbas_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = dcdbas_probe,
-       .remove         = __devexit_p(dcdbas_remove),
+       .remove         = dcdbas_remove,
 };
 
 /**
index b298158cb9224dd24eb65c5c00d2733b5d6cfc98..982f1f5f5742f21da9206f62fa622ce17adefe9f 100644 (file)
@@ -16,6 +16,7 @@
  */
 static char dmi_empty_string[] = "        ";
 
+static u16 __initdata dmi_ver;
 /*
  * Catch too early calls to dmi_check_system():
  */
@@ -118,12 +119,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
        return 0;
 }
 
-static int __init dmi_checksum(const u8 *buf)
+static int __init dmi_checksum(const u8 *buf, u8 len)
 {
        u8 sum = 0;
        int a;
 
-       for (a = 0; a < 15; a++)
+       for (a = 0; a < len; a++)
                sum += buf[a];
 
        return sum == 0;
@@ -161,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
                return;
 
        for (i = 0; i < 16 && (is_ff || is_00); i++) {
-               if(d[i] != 0x00) is_ff = 0;
-               if(d[i] != 0xFF) is_00 = 0;
+               if (d[i] != 0x00)
+                       is_00 = 0;
+               if (d[i] != 0xFF)
+                       is_ff = 0;
        }
 
        if (is_ff || is_00)
@@ -172,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
        if (!s)
                return;
 
-       sprintf(s, "%pUB", d);
+       /*
+        * As of version 2.6 of the SMBIOS specification, the first 3 fields of
+        * the UUID are supposed to be little-endian encoded.  The specification
+        * says that this is the defacto standard.
+        */
+       if (dmi_ver >= 0x0206)
+               sprintf(s, "%pUL", d);
+       else
+               sprintf(s, "%pUB", d);
 
         dmi_ident[slot] = s;
 }
@@ -404,35 +415,63 @@ static int __init dmi_present(const char __iomem *p)
        u8 buf[15];
 
        memcpy_fromio(buf, p, 15);
-       if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+       if (dmi_checksum(buf, 15)) {
                dmi_num = (buf[13] << 8) | buf[12];
                dmi_len = (buf[7] << 8) | buf[6];
                dmi_base = (buf[11] << 24) | (buf[10] << 16) |
                        (buf[9] << 8) | buf[8];
 
-               /*
-                * DMI version 0.0 means that the real version is taken from
-                * the SMBIOS version, which we don't know at this point.
-                */
-               if (buf[14] != 0)
-                       printk(KERN_INFO "DMI %d.%d present.\n",
-                              buf[14] >> 4, buf[14] & 0xF);
-               else
-                       printk(KERN_INFO "DMI present.\n");
                if (dmi_walk_early(dmi_decode) == 0) {
+                       if (dmi_ver)
+                               pr_info("SMBIOS %d.%d present.\n",
+                                      dmi_ver >> 8, dmi_ver & 0xFF);
+                       else {
+                               dmi_ver = (buf[14] & 0xF0) << 4 |
+                                          (buf[14] & 0x0F);
+                               pr_info("Legacy DMI %d.%d present.\n",
+                                      dmi_ver >> 8, dmi_ver & 0xFF);
+                       }
                        dmi_dump_ids();
                        return 0;
                }
        }
+       dmi_ver = 0;
        return 1;
 }
 
+static int __init smbios_present(const char __iomem *p)
+{
+       u8 buf[32];
+       int offset = 0;
+
+       memcpy_fromio(buf, p, 32);
+       if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
+               dmi_ver = (buf[6] << 8) + buf[7];
+
+               /* Some BIOS report weird SMBIOS version, fix that up */
+               switch (dmi_ver) {
+               case 0x021F:
+               case 0x0221:
+                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
+                              dmi_ver & 0xFF, 3);
+                       dmi_ver = 0x0203;
+                       break;
+               case 0x0233:
+                       pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
+                       dmi_ver = 0x0206;
+                       break;
+               }
+               offset = 16;
+       }
+       return dmi_present(buf + offset);
+}
+
 void __init dmi_scan_machine(void)
 {
        char __iomem *p, *q;
        int rc;
 
-       if (efi_enabled) {
+       if (efi_enabled(EFI_CONFIG_TABLES)) {
                if (efi.smbios == EFI_INVALID_TABLE_ADDR)
                        goto error;
 
@@ -444,7 +483,7 @@ void __init dmi_scan_machine(void)
                if (p == NULL)
                        goto error;
 
-               rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
+               rc = smbios_present(p);
                dmi_iounmap(p, 32);
                if (!rc) {
                        dmi_available = 1;
@@ -462,7 +501,12 @@ void __init dmi_scan_machine(void)
                        goto error;
 
                for (q = p; q < p + 0x10000; q += 16) {
-                       rc = dmi_present(q);
+                       if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
+                               rc = smbios_present(q);
+                       else if (memcmp(q, "_DMI_", 5) == 0)
+                               rc = dmi_present(q);
+                       else
+                               continue;
                        if (!rc) {
                                dmi_available = 1;
                                dmi_iounmap(p, 0x10000);
index 7b1c37497c9a2683569f8a1ac9c959e8d5bc7636..f5596db0cf583dc16226bc629a42977de0f9fa05 100644 (file)
@@ -674,7 +674,7 @@ static int efi_status_to_err(efi_status_t status)
                err = -EACCES;
                break;
        case EFI_NOT_FOUND:
-               err = -ENOENT;
+               err = -EIO;
                break;
        default:
                err = -EINVAL;
@@ -793,6 +793,7 @@ static ssize_t efivarfs_file_write(struct file *file,
                spin_unlock(&efivars->lock);
                efivar_unregister(var);
                drop_nlink(inode);
+               d_delete(file->f_dentry);
                dput(file->f_dentry);
 
        } else {
@@ -994,7 +995,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
                list_del(&var->list);
                spin_unlock(&efivars->lock);
                efivar_unregister(var);
-               drop_nlink(dir);
+               drop_nlink(dentry->d_inode);
                dput(dentry);
                return 0;
        }
@@ -1782,7 +1783,7 @@ efivars_init(void)
        printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
               EFIVARS_DATE);
 
-       if (!efi_enabled)
+       if (!efi_enabled(EFI_RUNTIME_SERVICES))
                return 0;
 
        /* For now we'll register the efi directory at /sys/firmware/efi */
@@ -1822,7 +1823,7 @@ err_put:
 static void __exit
 efivars_exit(void)
 {
-       if (efi_enabled) {
+       if (efi_enabled(EFI_RUNTIME_SERVICES)) {
                unregister_efivars(&__efivars);
                kobject_put(efi_kobj);
        }
index 4da4eb9ae92604c35349ebaeb39b4a612bac3ed6..2224f1dc074b1329d7ce9c80b78bef4fffc6e98b 100644 (file)
@@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep)
        /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
         * only use ACPI for this */
 
-       if (!efi_enabled)
+       if (!efi_enabled(EFI_BOOT))
                find_ibft_in_mem();
 
        if (ibft_addr) {
index 55d83c7d9c7f1e51342a1230133f7e1d70844577..fd6dfe382f13c650170a4f0f20cf3ed6a612dba5 100644 (file)
@@ -126,7 +126,7 @@ static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
                                  DA9055_IRQ_GPI0 + offset);
 }
 
-static struct gpio_chip reference_gp __devinitdata = {
+static struct gpio_chip reference_gp = {
        .label = "da9055-gpio",
        .owner = THIS_MODULE,
        .get = da9055_gpio_get,
@@ -139,7 +139,7 @@ static struct gpio_chip reference_gp __devinitdata = {
        .base = -1,
 };
 
-static int __devinit da9055_gpio_probe(struct platform_device *pdev)
+static int da9055_gpio_probe(struct platform_device *pdev)
 {
        struct da9055_gpio *gpio;
        struct da9055_pdata *pdata;
@@ -170,7 +170,7 @@ err_mem:
        return ret;
 }
 
-static int __devexit da9055_gpio_remove(struct platform_device *pdev)
+static int da9055_gpio_remove(struct platform_device *pdev)
 {
        struct da9055_gpio *gpio = platform_get_drvdata(pdev);
 
@@ -179,7 +179,7 @@ static int __devexit da9055_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver da9055_gpio_driver = {
        .probe = da9055_gpio_probe,
-       .remove = __devexit_p(da9055_gpio_remove),
+       .remove = da9055_gpio_remove,
        .driver = {
                .name   = "da9055-gpio",
                .owner  = THIS_MODULE,
index 7d9bd94be8d2a2108b66ac9575071e5751c06c79..6819d63cb1673647e35821ce3feede298e3e56c7 100644 (file)
@@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
        if (! mvchip->membase) {
                dev_err(&pdev->dev, "Cannot ioremap\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                if (! res) {
                        dev_err(&pdev->dev, "Cannot get memory resource\n");
-                       kfree(mvchip->chip.label);
                        return -ENODEV;
                }
 
                mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
                if (! mvchip->percpu_membase) {
                        dev_err(&pdev->dev, "Cannot ioremap\n");
-                       kfree(mvchip->chip.label);
                        return -ENOMEM;
                }
        }
@@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
        if (mvchip->irqbase < 0) {
                dev_err(&pdev->dev, "no irqs\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                                    mvchip->membase, handle_level_irq);
        if (! gc) {
                dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
                                        IRQ_LEVEL | IRQ_NOPROBE);
                kfree(gc);
-               kfree(mvchip->chip.label);
                return -ENODEV;
        }
 
index 01f7fe955590c1b79a64cd088431858b7d9caea8..76be7eed79dec2683e244a0a9f60a1688241e1ab 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <mach/hardware.h>
 #include <mach/map.h>
-#include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
 #include <plat/cpu.h>
@@ -446,7 +445,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250)
 static struct samsung_gpio_cfg exynos_gpio_cfg = {
        .set_pull       = exynos_gpio_setpull,
        .get_pull       = exynos_gpio_getpull,
@@ -2446,7 +2445,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_1[] = {
        {
                .chip   = {
@@ -2614,7 +2613,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_2[] = {
        {
                .chip   = {
@@ -2675,7 +2674,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_3[] = {
        {
                .chip   = {
@@ -2711,7 +2710,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_4[] = {
        {
                .chip   = {
@@ -3010,7 +3009,7 @@ static __init int samsung_gpiolib_init(void)
        int i, nr_chips;
        int group = 0;
 
-#ifdef CONFIG_PINCTRL_SAMSUNG
+#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
        /*
        * This gpio driver includes support for device tree support and there
        * are platforms using it. In order to maintain compatibility with those
@@ -3026,6 +3025,7 @@ static __init int samsung_gpiolib_init(void)
        static const struct of_device_id exynos_pinctrl_ids[] = {
                { .compatible = "samsung,pinctrl-exynos4210", },
                { .compatible = "samsung,pinctrl-exynos4x12", },
+               { .compatible = "samsung,pinctrl-exynos5440", },
        };
        for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
                if (pctrl_np && of_device_is_available(pctrl_np))
index 0634ceea3c244765593e427f683865ed6a01903f..cc53cab8df2acb89042673347acf128056c57026 100644 (file)
@@ -319,7 +319,7 @@ static void ts5500_disable_irq(struct ts5500_priv *priv)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static int __devinit ts5500_dio_probe(struct platform_device *pdev)
+static int ts5500_dio_probe(struct platform_device *pdev)
 {
        enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
        struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data;
@@ -432,7 +432,7 @@ cleanup:
        return ret;
 }
 
-static int __devexit ts5500_dio_remove(struct platform_device *pdev)
+static int ts5500_dio_remove(struct platform_device *pdev)
 {
        struct ts5500_priv *priv = platform_get_drvdata(pdev);
 
@@ -455,7 +455,7 @@ static struct platform_driver ts5500_dio_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ts5500_dio_probe,
-       .remove = __devexit_p(ts5500_dio_remove),
+       .remove = ts5500_dio_remove,
        .id_table = ts5500_dio_ids,
 };
 
index 13772996cf2418e0ef40f60b51232f7bd624c911..59d72391de264155de8af0428d618fc354e53c50 100644 (file)
@@ -400,7 +400,7 @@ static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
 
 /* ----- end of gpio b chip ---------------------------------------------- */
 
-static int __devinit vprbrd_gpio_probe(struct platform_device *pdev)
+static int vprbrd_gpio_probe(struct platform_device *pdev)
 {
        struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
        struct vprbrd_gpio *vb_gpio;
@@ -456,7 +456,7 @@ err_gpioa:
        return ret;
 }
 
-static int __devexit vprbrd_gpio_remove(struct platform_device *pdev)
+static int vprbrd_gpio_remove(struct platform_device *pdev)
 {
        struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev);
        int ret;
@@ -472,7 +472,7 @@ static struct platform_driver vprbrd_gpio_driver = {
        .driver.name    = "viperboard-gpio",
        .driver.owner   = THIS_MODULE,
        .probe          = vprbrd_gpio_probe,
-       .remove         = __devexit_p(vprbrd_gpio_remove),
+       .remove         = vprbrd_gpio_remove,
 };
 
 static int __init vprbrd_gpio_init(void)
index 31123b6a0be5eae06ce34aa20127a1fd8d84d1ba..2d2c2f8d6dc668e29202b947461314fc4ccf71be 100644 (file)
@@ -60,8 +60,7 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
-static int __devinit
-ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        return drm_get_pci_dev(pdev, ent, &driver);
 }
index dcd1a8c029ebb8958ab617e03dd53768c8b71e2d..8ecb601152effe17019967c559e48cddfac2f7b4 100644 (file)
@@ -56,8 +56,8 @@ static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
        return 0;
 }
 
-static int __devinit
-cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int cirrus_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        int ret;
 
index 0761a03cdbb2d4f0af455097d1c09d3710c2749f..2aa331499f81da1dfbe8f5c51216ed0096f67951 100644 (file)
@@ -184,19 +184,27 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
  * -ENOSPC if no suitable free area is available. The preallocated memory node
  * must be cleared.
  */
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-                      unsigned long size, unsigned alignment)
+int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
+                              unsigned long size, unsigned alignment,
+                              unsigned long color)
 {
        struct drm_mm_node *hole_node;
 
-       hole_node = drm_mm_search_free(mm, size, alignment, false);
+       hole_node = drm_mm_search_free_generic(mm, size, alignment,
+                                              color, 0);
        if (!hole_node)
                return -ENOSPC;
 
-       drm_mm_insert_helper(hole_node, node, size, alignment, 0);
-
+       drm_mm_insert_helper(hole_node, node, size, alignment, color);
        return 0;
 }
+EXPORT_SYMBOL(drm_mm_insert_node_generic);
+
+int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
+                      unsigned long size, unsigned alignment)
+{
+       return drm_mm_insert_node_generic(mm, node, size, alignment, 0);
+}
 EXPORT_SYMBOL(drm_mm_insert_node);
 
 static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
@@ -213,11 +221,13 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
 
        BUG_ON(!hole_node->hole_follows || node->allocated);
 
-       if (mm->color_adjust)
-               mm->color_adjust(hole_node, color, &adj_start, &adj_end);
-
        if (adj_start < start)
                adj_start = start;
+       if (adj_end > end)
+               adj_end = end;
+
+       if (mm->color_adjust)
+               mm->color_adjust(hole_node, color, &adj_start, &adj_end);
 
        if (alignment) {
                unsigned tmp = adj_start % alignment;
@@ -275,22 +285,31 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic);
  * -ENOSPC if no suitable free area is available. This is for range
  * restricted allocations. The preallocated memory node must be cleared.
  */
-int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
-                               unsigned long size, unsigned alignment,
-                               unsigned long start, unsigned long end)
+int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
+                                       unsigned long size, unsigned alignment, unsigned long color,
+                                       unsigned long start, unsigned long end)
 {
        struct drm_mm_node *hole_node;
 
-       hole_node = drm_mm_search_free_in_range(mm, size, alignment,
-                                               start, end, false);
+       hole_node = drm_mm_search_free_in_range_generic(mm,
+                                                       size, alignment, color,
+                                                       start, end, 0);
        if (!hole_node)
                return -ENOSPC;
 
-       drm_mm_insert_helper_range(hole_node, node, size, alignment, 0,
+       drm_mm_insert_helper_range(hole_node, node,
+                                  size, alignment, color,
                                   start, end);
-
        return 0;
 }
+EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
+
+int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
+                               unsigned long size, unsigned alignment,
+                               unsigned long start, unsigned long end)
+{
+       return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
+}
 EXPORT_SYMBOL(drm_mm_insert_node_in_range);
 
 /**
@@ -489,7 +508,7 @@ void drm_mm_init_scan(struct drm_mm *mm,
        mm->scan_size = size;
        mm->scanned_blocks = 0;
        mm->scan_hit_start = 0;
-       mm->scan_hit_size = 0;
+       mm->scan_hit_end = 0;
        mm->scan_check_range = 0;
        mm->prev_scanned_node = NULL;
 }
@@ -516,7 +535,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm,
        mm->scan_size = size;
        mm->scanned_blocks = 0;
        mm->scan_hit_start = 0;
-       mm->scan_hit_size = 0;
+       mm->scan_hit_end = 0;
        mm->scan_start = start;
        mm->scan_end = end;
        mm->scan_check_range = 1;
@@ -535,8 +554,7 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
        struct drm_mm *mm = node->mm;
        struct drm_mm_node *prev_node;
        unsigned long hole_start, hole_end;
-       unsigned long adj_start;
-       unsigned long adj_end;
+       unsigned long adj_start, adj_end;
 
        mm->scanned_blocks++;
 
@@ -553,14 +571,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
        node->node_list.next = &mm->prev_scanned_node->node_list;
        mm->prev_scanned_node = node;
 
-       hole_start = drm_mm_hole_node_start(prev_node);
-       hole_end = drm_mm_hole_node_end(prev_node);
-
-       adj_start = hole_start;
-       adj_end = hole_end;
-
-       if (mm->color_adjust)
-               mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end);
+       adj_start = hole_start = drm_mm_hole_node_start(prev_node);
+       adj_end = hole_end = drm_mm_hole_node_end(prev_node);
 
        if (mm->scan_check_range) {
                if (adj_start < mm->scan_start)
@@ -569,11 +581,14 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
                        adj_end = mm->scan_end;
        }
 
+       if (mm->color_adjust)
+               mm->color_adjust(prev_node, mm->scan_color,
+                                &adj_start, &adj_end);
+
        if (check_free_hole(adj_start, adj_end,
                            mm->scan_size, mm->scan_alignment)) {
                mm->scan_hit_start = hole_start;
-               mm->scan_hit_size = hole_end;
-
+               mm->scan_hit_end = hole_end;
                return 1;
        }
 
@@ -609,19 +624,10 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node)
                               node_list);
 
        prev_node->hole_follows = node->scanned_preceeds_hole;
-       INIT_LIST_HEAD(&node->node_list);
        list_add(&node->node_list, &prev_node->node_list);
 
-       /* Only need to check for containement because start&size for the
-        * complete resulting free block (not just the desired part) is
-        * stored. */
-       if (node->start >= mm->scan_hit_start &&
-           node->start + node->size
-                       <= mm->scan_hit_start + mm->scan_hit_size) {
-               return 1;
-       }
-
-       return 0;
+        return (drm_mm_hole_node_end(node) > mm->scan_hit_start &&
+                node->start < mm->scan_hit_end);
 }
 EXPORT_SYMBOL(drm_mm_scan_remove_block);
 
index 1d1f1e5e33f0ff267daa1d8ed4818b0a4e00fc7e..046bcda36abe7aa0f60e53f79f9988eaef61bd17 100644 (file)
@@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF
 
 config DRM_EXYNOS_FIMD
        bool "Exynos DRM FIMD"
-       depends on DRM_EXYNOS && !FB_S3C
+       depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
        help
          Choose this option if you want to use Exynos FIMD for DRM.
 
@@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D
 
 config DRM_EXYNOS_IPP
        bool "Exynos DRM IPP"
-       depends on DRM_EXYNOS
+       depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
        help
          Choose this option if you want to use IPP feature for DRM.
 
index bef43e0342a69e82dcb7e91756158552c6ca8159..4e9b5ba8edff962bd1a5bd6720daa782e5388619 100644 (file)
@@ -66,6 +66,6 @@ struct i2c_driver ddc_driver = {
        },
        .id_table       = ddc_idtable,
        .probe          = s5p_ddc_probe,
-       .remove         = __devexit_p(s5p_ddc_remove),
+       .remove         = s5p_ddc_remove,
        .command                = NULL,
 };
index 9601bad47a2e6d5a2bd04deffec5ec5744bfbcee..57affae9568b22c1b4713fb0fe330a33ffe6ca01 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -29,6 +15,7 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
+#include "exynos_drm_iommu.h"
 
 static int lowlevel_buffer_allocate(struct drm_device *dev,
                unsigned int flags, struct exynos_drm_gem_buf *buf)
@@ -51,7 +38,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
         * region will be allocated else physically contiguous
         * as possible.
         */
-       if (flags & EXYNOS_BO_CONTIG)
+       if (!(flags & EXYNOS_BO_NONCONTIG))
                dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);
 
        /*
@@ -66,14 +53,45 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
        dma_set_attr(attr, &buf->dma_attrs);
        dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
 
-       buf->pages = dma_alloc_attrs(dev->dev, buf->size,
-                       &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
-       if (!buf->pages) {
-               DRM_ERROR("failed to allocate buffer.\n");
-               return -ENOMEM;
+       nr_pages = buf->size >> PAGE_SHIFT;
+
+       if (!is_drm_iommu_supported(dev)) {
+               dma_addr_t start_addr;
+               unsigned int i = 0;
+
+               buf->pages = kzalloc(sizeof(struct page) * nr_pages,
+                                       GFP_KERNEL);
+               if (!buf->pages) {
+                       DRM_ERROR("failed to allocate pages.\n");
+                       return -ENOMEM;
+               }
+
+               buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
+                                       &buf->dma_addr, GFP_KERNEL,
+                                       &buf->dma_attrs);
+               if (!buf->kvaddr) {
+                       DRM_ERROR("failed to allocate buffer.\n");
+                       kfree(buf->pages);
+                       return -ENOMEM;
+               }
+
+               start_addr = buf->dma_addr;
+               while (i < nr_pages) {
+                       buf->pages[i] = phys_to_page(start_addr);
+                       start_addr += PAGE_SIZE;
+                       i++;
+               }
+       } else {
+
+               buf->pages = dma_alloc_attrs(dev->dev, buf->size,
+                                       &buf->dma_addr, GFP_KERNEL,
+                                       &buf->dma_attrs);
+               if (!buf->pages) {
+                       DRM_ERROR("failed to allocate buffer.\n");
+                       return -ENOMEM;
+               }
        }
 
-       nr_pages = buf->size >> PAGE_SHIFT;
        buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
        if (!buf->sgt) {
                DRM_ERROR("failed to get sg table.\n");
@@ -92,6 +110,9 @@ err_free_attrs:
                        (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
        buf->dma_addr = (dma_addr_t)NULL;
 
+       if (!is_drm_iommu_supported(dev))
+               kfree(buf->pages);
+
        return ret;
 }
 
@@ -114,8 +135,14 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
        kfree(buf->sgt);
        buf->sgt = NULL;
 
-       dma_free_attrs(dev->dev, buf->size, buf->pages,
+       if (!is_drm_iommu_supported(dev)) {
+               dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
                                (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
+               kfree(buf->pages);
+       } else
+               dma_free_attrs(dev->dev, buf->size, buf->pages,
+                               (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
+
        buf->dma_addr = (dma_addr_t)NULL;
 }
 
index 25cf162850330457fd977779157f34b304e91a8d..a6412f19673cb3277ad17137700b006f024b8c84 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_BUF_H_
index 0f68a28726739dd6b795ad066edb645799cfc6d2..4c5b6859c9ea5cab2aa856ce43d3675f0240235e 100644 (file)
@@ -5,24 +5,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -32,7 +18,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_encoder.h"
 
-#define MAX_EDID 256
 #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
                                drm_connector)
 
@@ -110,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                                        to_exynos_connector(connector);
        struct exynos_drm_manager *manager = exynos_connector->manager;
        struct exynos_drm_display_ops *display_ops = manager->display_ops;
-       unsigned int count;
+       struct edid *edid = NULL;
+       unsigned int count = 0;
+       int ret;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -128,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
         * because lcd panel has only one mode.
         */
        if (display_ops->get_edid) {
-               int ret;
-               void *edid;
-
-               edid = kzalloc(MAX_EDID, GFP_KERNEL);
-               if (!edid) {
-                       DRM_ERROR("failed to allocate edid\n");
-                       return 0;
+               edid = display_ops->get_edid(manager->dev, connector);
+               if (IS_ERR_OR_NULL(edid)) {
+                       ret = PTR_ERR(edid);
+                       edid = NULL;
+                       DRM_ERROR("Panel operation get_edid failed %d\n", ret);
+                       goto out;
                }
 
-               ret = display_ops->get_edid(manager->dev, connector,
-                                               edid, MAX_EDID);
-               if (ret < 0) {
-                       DRM_ERROR("failed to get edid data.\n");
-                       kfree(edid);
-                       edid = NULL;
-                       return 0;
+               count = drm_add_edid_modes(connector, edid);
+               if (count < 0) {
+                       DRM_ERROR("Add edid modes failed %d\n", count);
+                       goto out;
                }
 
                drm_mode_connector_update_edid_property(connector, edid);
-               count = drm_add_edid_modes(connector, edid);
-               kfree(edid);
        } else {
                struct exynos_drm_panel_info *panel;
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
@@ -175,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                count = 1;
        }
 
+out:
+       kfree(edid);
        return count;
 }
 
index 22f6cc442c3d94e816d9302faa2cef12b25f7fa6..547c6b590357609a2c4f1e6811cb018ea75b1cff 100644 (file)
@@ -5,24 +5,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_CONNECTOR_H_
index 94026ad76a775d9cfb826fa65f9e2da74d14660f..4667c9f67acdf0a03b68a3e717b8c56cda4d127b 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
index 2efa4b031d7340d075e86f9f4136d7f8d2a2a40c..e8894bc9e6d5edf0ecf07cea5078f3961191030d 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -407,3 +393,33 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
        exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
                        exynos_drm_disable_vblank);
 }
+
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
+{
+       struct exynos_drm_private *dev_priv = dev->dev_private;
+       struct drm_pending_vblank_event *e, *t;
+       struct timeval now;
+       unsigned long flags;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+
+       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
+                       base.link) {
+               /* if event's pipe isn't same as crtc then ignore it. */
+               if (crtc != e->pipe)
+                       continue;
+
+               do_gettimeofday(&now);
+               e->event.sequence = 0;
+               e->event.tv_sec = now.tv_sec;
+               e->event.tv_usec = now.tv_usec;
+
+               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+               wake_up_interruptible(&e->base.file_priv->event_wait);
+               drm_vblank_put(dev, crtc);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+}
index 6bae8d8c250ec7d6cd84c85268d99cf5f40669b6..3e197e6ae7d938f23c98a88c66a09478aa97f60b 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_CRTC_H_
@@ -32,5 +18,6 @@
 int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc);
 
 #endif
index 61d5a8402eb8be71857a4b119f3647dfa5975807..ba0a3aa785474f27ca0ba23b181e71d7d5bf82a9 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -33,6 +19,7 @@
 struct exynos_drm_dmabuf_attachment {
        struct sg_table sgt;
        enum dma_data_direction dir;
+       bool is_mapped;
 };
 
 static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
@@ -86,17 +73,10 @@ static struct sg_table *
 
        DRM_DEBUG_PRIME("%s\n", __FILE__);
 
-       if (WARN_ON(dir == DMA_NONE))
-               return ERR_PTR(-EINVAL);
-
        /* just return current sgt if already requested. */
-       if (exynos_attach->dir == dir)
+       if (exynos_attach->dir == dir && exynos_attach->is_mapped)
                return &exynos_attach->sgt;
 
-       /* reattaching is not allowed. */
-       if (WARN_ON(exynos_attach->dir != DMA_NONE))
-               return ERR_PTR(-EBUSY);
-
        buf = gem_obj->buffer;
        if (!buf) {
                DRM_ERROR("buffer is null.\n");
@@ -121,13 +101,17 @@ static struct sg_table *
                wr = sg_next(wr);
        }
 
-       nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
-       if (!nents) {
-               DRM_ERROR("failed to map sgl with iommu.\n");
-               sgt = ERR_PTR(-EIO);
-               goto err_unlock;
+       if (dir != DMA_NONE) {
+               nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
+               if (!nents) {
+                       DRM_ERROR("failed to map sgl with iommu.\n");
+                       sg_free_table(sgt);
+                       sgt = ERR_PTR(-EIO);
+                       goto err_unlock;
+               }
        }
 
+       exynos_attach->is_mapped = true;
        exynos_attach->dir = dir;
        attach->priv = exynos_attach;
 
@@ -222,7 +206,7 @@ struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
 
        return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops,
-                               exynos_gem_obj->base.size, 0600);
+                               exynos_gem_obj->base.size, flags);
 }
 
 struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
@@ -246,7 +230,12 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 
                /* is it from our device? */
                if (obj->dev == drm_dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(obj);
+                       dma_buf_put(dma_buf);
                        return obj;
                }
        }
index 662a8f98ccdbebc82cc7bfcdddd90beade422fc3..49acfafb4fdb60852139fc5745fdbad867193ad4 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_DMABUF_H_
index e0a8e8024b010683a32a6ef8a9754e6ade1adcce..3da5c2d214d88777b2dd550295c8e939673289dd 100644 (file)
@@ -5,24 +5,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -325,7 +311,7 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
 
 static struct platform_driver exynos_drm_platform_driver = {
        .probe          = exynos_drm_platform_probe,
-       .remove         = __devexit_p(exynos_drm_platform_remove),
+       .remove         = exynos_drm_platform_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "exynos-drm",
index f5a97745bf93b44a6872f8daaca88642d2912c54..4606fac7241a0f2762dd0f10e8674efda02ac7d3 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_DRV_H_
@@ -162,8 +148,8 @@ struct exynos_drm_overlay {
 struct exynos_drm_display_ops {
        enum exynos_drm_output_type type;
        bool (*is_connected)(struct device *dev);
-       int (*get_edid)(struct device *dev, struct drm_connector *connector,
-                               u8 *edid, int len);
+       struct edid *(*get_edid)(struct device *dev,
+                       struct drm_connector *connector);
        void *(*get_panel)(struct device *dev);
        int (*check_timing)(struct device *dev, void *timing);
        int (*power_on)(struct device *dev, int mode);
index 301485215a70d782aa28e182633ca0f1b1592afc..c63721f64aecd15518392d254b9857cfc6c2ab54 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
index 88bb25a2a917119d102104aa613ea9745fadfbbd..89e2fb0770af12ba7405ba8b116edb831b67c4fd 100644 (file)
@@ -5,24 +5,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_ENCODER_H_
index 5426cc5a5e8d53b30409a980aa5e8878a30e7c83..294c0513f587901a15fdd9e57de8c3c48fdf3d34 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
index 96262e54f76dc212183702fe4ab2027ff4e97820..517471b37566cd8b5224720954113865549cf12d 100644 (file)
@@ -5,24 +5,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_FB_H_
index f433eb7533a97e9550f86f2f94c4f5fa173d0427..71f867340a88b43a98572c1b84c6776528e919fc 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
@@ -34,6 +20,7 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
+#include "exynos_drm_iommu.h"
 
 #define MAX_CONNECTOR          4
 #define PREFERRED_BPP          32
@@ -111,9 +98,18 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 
        /* map pages with kernel virtual space. */
        if (!buffer->kvaddr) {
-               unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
-               buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
+               if (is_drm_iommu_supported(dev)) {
+                       unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
+
+                       buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
                                        pgprot_writecombine(PAGE_KERNEL));
+               } else {
+                       phys_addr_t dma_addr = buffer->dma_addr;
+                       if (dma_addr)
+                               buffer->kvaddr = phys_to_virt(dma_addr);
+                       else
+                               buffer->kvaddr = (void __iomem *)NULL;
+               }
                if (!buffer->kvaddr) {
                        DRM_ERROR("failed to map pages to kernel space.\n");
                        return -EIO;
@@ -128,8 +124,12 @@ 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)
+       if (is_drm_iommu_supported(dev))
+               fbi->fix.smem_start = (unsigned long)
                        (page_to_phys(sg_page(buffer->sgt->sgl)) + offset);
+       else
+               fbi->fix.smem_start = (unsigned long)buffer->dma_addr;
+
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
 
@@ -320,7 +320,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
        struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
        struct drm_framebuffer *fb;
 
-       if (exynos_gem_obj->buffer->kvaddr)
+       if (is_drm_iommu_supported(dev) && exynos_gem_obj->buffer->kvaddr)
                vunmap(exynos_gem_obj->buffer->kvaddr);
 
        /* release drm framebuffer and real buffer */
index ccfce8a1a4519c9bdd142eb1d5c3200b7314fcc6..e16d7f0ae1920eb944364747b3f009e7976654f4 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_FBDEV_H_
index 61ea24296b526f4c00d76dc77a0002bd94401da7..67a83e69544bb4e285088be9227c3ed2176ebcb6 100644 (file)
@@ -25,7 +25,7 @@
 #include "exynos_drm_fimc.h"
 
 /*
- * FIMC is stand for Fully Interactive Mobile Camera and
+ * FIMC stands for Fully Interactive Mobile Camera and
  * supports image scaler/rotator and input/output DMA operations.
  * input DMA reads image data from the memory.
  * output DMA writes image data to memory.
@@ -163,19 +163,29 @@ struct fimc_context {
        bool    suspended;
 };
 
-static void fimc_sw_reset(struct fimc_context *ctx, bool pattern)
+static void fimc_sw_reset(struct fimc_context *ctx)
 {
        u32 cfg;
 
-       DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern);
+       DRM_DEBUG_KMS("%s\n", __func__);
+
+       /* stop dma operation */
+       cfg = fimc_read(EXYNOS_CISTATUS);
+       if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
+               cfg = fimc_read(EXYNOS_MSCTRL);
+               cfg &= ~EXYNOS_MSCTRL_ENVID;
+               fimc_write(cfg, EXYNOS_MSCTRL);
+       }
 
        cfg = fimc_read(EXYNOS_CISRCFMT);
        cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
-       if (pattern)
-               cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR;
-
        fimc_write(cfg, EXYNOS_CISRCFMT);
 
+       /* disable image capture */
+       cfg = fimc_read(EXYNOS_CIIMGCPT);
+       cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
+       fimc_write(cfg, EXYNOS_CIIMGCPT);
+
        /* s/w reset */
        cfg = fimc_read(EXYNOS_CIGCTRL);
        cfg |= (EXYNOS_CIGCTRL_SWRST);
@@ -695,7 +705,7 @@ static int fimc_src_set_addr(struct device *dev,
 {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
 
@@ -705,10 +715,6 @@ static int fimc_src_set_addr(struct device *dev,
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
 
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@ -1206,7 +1212,7 @@ static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
        }
 
        /* sequence id */
-       cfg &= (~mask);
+       cfg &= ~mask;
        cfg |= (enable << buf_id);
        fimc_write(cfg, EXYNOS_CIFCNTSEQ);
 
@@ -1231,7 +1237,7 @@ static int fimc_dst_set_addr(struct device *dev,
 {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
 
@@ -1241,10 +1247,6 @@ static int fimc_dst_set_addr(struct device *dev,
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
 
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@ -1317,7 +1319,7 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
 {
        struct fimc_context *ctx = dev_id;
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work =
                c_node->event_work;
        int buf_id;
@@ -1395,6 +1397,7 @@ static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@ -1543,7 +1546,7 @@ static int fimc_ippdrv_reset(struct device *dev)
        DRM_DEBUG_KMS("%s\n", __func__);
 
        /* reset h/w block */
-       fimc_sw_reset(ctx, false);
+       fimc_sw_reset(ctx);
 
        /* reset scaler capability */
        memset(&ctx->sc, 0x0, sizeof(ctx->sc));
@@ -1557,7 +1560,7 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
        struct drm_exynos_pos   img_pos[EXYNOS_DRM_OPS_MAX];
@@ -1573,10 +1576,6 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
 
        fimc_handle_irq(ctx, true, false, true);
 
@@ -1714,7 +1713,7 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
        fimc_write(cfg, EXYNOS_CIGCTRL);
 }
 
-static int __devinit fimc_probe(struct platform_device *pdev)
+static int fimc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimc_context *ctx;
@@ -1739,93 +1738,64 @@ static int __devinit fimc_probe(struct platform_device *pdev)
                platform_get_device_id(pdev)->driver_data;
 
        /* clock control */
-       ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
+       ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
        if (IS_ERR(ctx->sclk_fimc_clk)) {
                dev_err(dev, "failed to get src fimc clock.\n");
-               ret = PTR_ERR(ctx->sclk_fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->sclk_fimc_clk);
        }
        clk_enable(ctx->sclk_fimc_clk);
 
-       ctx->fimc_clk = clk_get(dev, "fimc");
+       ctx->fimc_clk = devm_clk_get(dev, "fimc");
        if (IS_ERR(ctx->fimc_clk)) {
                dev_err(dev, "failed to get fimc clock.\n");
-               ret = PTR_ERR(ctx->fimc_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->fimc_clk);
        }
 
-       ctx->wb_clk = clk_get(dev, "pxl_async0");
+       ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
        if (IS_ERR(ctx->wb_clk)) {
                dev_err(dev, "failed to get writeback a clock.\n");
-               ret = PTR_ERR(ctx->wb_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->wb_clk);
        }
 
-       ctx->wb_b_clk = clk_get(dev, "pxl_async1");
+       ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
        if (IS_ERR(ctx->wb_b_clk)) {
                dev_err(dev, "failed to get writeback b clock.\n");
-               ret = PTR_ERR(ctx->wb_b_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->wb_b_clk);
        }
 
-       parent_clk = clk_get(dev, ddata->parent_clk);
+       parent_clk = devm_clk_get(dev, ddata->parent_clk);
 
        if (IS_ERR(parent_clk)) {
                dev_err(dev, "failed to get parent clock.\n");
-               ret = PTR_ERR(parent_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               clk_put(ctx->wb_b_clk);
-               goto err_ctx;
+               return PTR_ERR(parent_clk);
        }
 
        if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
                dev_err(dev, "failed to set parent.\n");
-               ret = -EINVAL;
-               clk_put(parent_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               clk_put(ctx->wb_b_clk);
-               goto err_ctx;
+               return -EINVAL;
        }
 
-       clk_put(parent_clk);
+       devm_clk_put(dev, parent_clk);
        clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
 
        /* resource memory */
        ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!ctx->regs_res) {
-               dev_err(dev, "failed to find registers.\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
-
        ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
        if (!ctx->regs) {
                dev_err(dev, "failed to map registers.\n");
-               ret = -ENXIO;
-               goto err_clk;
+               return -ENXIO;
        }
 
        /* resource irq */
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
                dev_err(dev, "failed to request irq resource.\n");
-               ret = -ENOENT;
-               goto err_get_regs;
+               return -ENOENT;
        }
 
        ctx->irq = res->start;
@@ -1833,7 +1803,7 @@ static int __devinit fimc_probe(struct platform_device *pdev)
                IRQF_ONESHOT, "drm_fimc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
-               goto err_get_regs;
+               return ret;
        }
 
        /* context initailization */
@@ -1879,19 +1849,11 @@ err_ippdrv_register:
        pm_runtime_disable(dev);
 err_get_irq:
        free_irq(ctx->irq, ctx);
-err_get_regs:
-       devm_iounmap(dev, ctx->regs);
-err_clk:
-       clk_put(ctx->sclk_fimc_clk);
-       clk_put(ctx->fimc_clk);
-       clk_put(ctx->wb_clk);
-       clk_put(ctx->wb_b_clk);
-err_ctx:
-       devm_kfree(dev, ctx);
+
        return ret;
 }
 
-static int __devexit fimc_remove(struct platform_device *pdev)
+static int fimc_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimc_context *ctx = get_fimc_context(dev);
@@ -1905,14 +1867,6 @@ static int __devexit fimc_remove(struct platform_device *pdev)
        pm_runtime_disable(dev);
 
        free_irq(ctx->irq, ctx);
-       devm_iounmap(dev, ctx->regs);
-
-       clk_put(ctx->sclk_fimc_clk);
-       clk_put(ctx->fimc_clk);
-       clk_put(ctx->wb_clk);
-       clk_put(ctx->wb_b_clk);
-
-       devm_kfree(dev, ctx);
 
        return 0;
 }
@@ -1990,7 +1944,7 @@ static const struct dev_pm_ops fimc_pm_ops = {
 
 struct platform_driver fimc_driver = {
        .probe          = fimc_probe,
-       .remove         = __devexit_p(fimc_remove),
+       .remove         = fimc_remove,
        .id_table       = fimc_driver_ids,
        .driver         = {
                .name   = "exynos-drm-fimc",
index dc970fa0d8886f228edac1ba00ad46338d4fad80..127a424c5fdfb9e5ca7948bdeba607e452f50b1d 100644 (file)
@@ -6,24 +6,10 @@
  *     Jinyoung Jeon <jy0.jeon@samsung.com>
  *     Sangmin Lee <lsmin.lee@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_FIMC_H_
index bf0d9baca2bc2436c077cf62391da74fe2288e83..9537761931ee297fb33c8cf8888a2842b1e4fc1a 100644 (file)
@@ -663,34 +663,6 @@ static struct exynos_drm_manager fimd_manager = {
        .display_ops    = &fimd_display_ops,
 };
 
-static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
-       struct exynos_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 {
        struct fimd_context *ctx = (struct fimd_context *)dev_id;
@@ -710,7 +682,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
                goto out;
 
        drm_handle_vblank(drm_dev, manager->pipe);
-       fimd_finish_pageflip(drm_dev, manager->pipe);
+       exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
 
        /* set wait vsync event to zero and wake up queue. */
        if (atomic_read(&ctx->wait_vsync_event)) {
@@ -898,7 +870,7 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
        return 0;
 }
 
-static int __devinit fimd_probe(struct platform_device *pdev)
+static int fimd_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimd_context *ctx;
@@ -997,7 +969,7 @@ static int __devinit fimd_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit fimd_remove(struct platform_device *pdev)
+static int fimd_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimd_context *ctx = platform_get_drvdata(pdev);
@@ -1046,7 +1018,7 @@ static int fimd_resume(struct device *dev)
         * of pm runtime would still be 1 so in this case, fimd driver
         * should be on directly not drawing on pm runtime interface.
         */
-       if (pm_runtime_suspended(dev)) {
+       if (!pm_runtime_suspended(dev)) {
                int ret;
 
                ret = fimd_activate(ctx, true);
@@ -1105,7 +1077,7 @@ static const struct dev_pm_ops fimd_pm_ops = {
 
 struct platform_driver fimd_driver = {
        .probe          = fimd_probe,
-       .remove         = __devexit_p(fimd_remove),
+       .remove         = fimd_remove,
        .id_table       = fimd_driver_ids,
        .driver         = {
                .name   = "exynos4-fb",
index 6ffa0763c0789e2f36cf0cf9076f4583a0ed03f3..9a4c08e7453c35b2566c2c76b3bc7fa4406d7696 100644 (file)
@@ -324,7 +324,7 @@ out:
        g2d_userptr = NULL;
 }
 
-dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
+static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
                                        unsigned long userptr,
                                        unsigned long size,
                                        struct drm_file *filp,
@@ -1090,7 +1090,7 @@ static void g2d_close(struct drm_device *drm_dev, struct device *dev,
        kfree(file_priv->g2d_priv);
 }
 
-static int __devinit g2d_probe(struct platform_device *pdev)
+static int g2d_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct resource *res;
@@ -1188,7 +1188,7 @@ err_destroy_slab:
        return ret;
 }
 
-static int __devexit g2d_remove(struct platform_device *pdev)
+static int g2d_remove(struct platform_device *pdev)
 {
        struct g2d_data *g2d = platform_get_drvdata(pdev);
 
@@ -1242,7 +1242,7 @@ static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
 
 struct platform_driver g2d_driver = {
        .probe          = g2d_probe,
-       .remove         = __devexit_p(g2d_remove),
+       .remove         = g2d_remove,
        .driver         = {
                .name   = "s5p-g2d",
                .owner  = THIS_MODULE,
index d48183e7e056d56a8932ae06baf1bc172ce02893..4731807765287a35ce2bb5ea087fc6bc3844eac8 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drm/drmP.h>
index f11f2afd5bfc58254eb0b064535ae4b8131b91c3..35ebac47dc2bacfec928d54001b6065aa9e75564 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  * Authoer: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_GEM_H_
index 5639353d47b98467c803b36c0b4ca8d0a53c5eec..8140753ec9c824202173e631bfc1f4ba711c9ef7 100644 (file)
@@ -25,7 +25,7 @@
 #include "exynos_drm_gsc.h"
 
 /*
- * GSC is stand for General SCaler and
+ * GSC stands for General SCaler and
  * supports image scaler/rotator and input/output DMA operations.
  * input DMA reads image data from the memory.
  * output DMA writes image data to memory.
@@ -711,7 +711,7 @@ static int gsc_src_set_addr(struct device *dev,
 {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
 
        if (!c_node) {
@@ -720,10 +720,6 @@ static int gsc_src_set_addr(struct device *dev,
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EFAULT;
-       }
 
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@ -1171,7 +1167,7 @@ static int gsc_dst_set_addr(struct device *dev,
 {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
 
        if (!c_node) {
@@ -1180,10 +1176,6 @@ static int gsc_dst_set_addr(struct device *dev,
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EFAULT;
-       }
 
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@ -1312,7 +1304,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
 {
        struct gsc_context *ctx = dev_id;
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work =
                c_node->event_work;
        u32 status;
@@ -1399,7 +1391,7 @@ static inline bool gsc_check_drm_flip(enum drm_exynos_flip flip)
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
-       case EXYNOS_DRM_FLIP_VERTICAL | EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@ -1549,7 +1541,7 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
        struct drm_exynos_pos   img_pos[EXYNOS_DRM_OPS_MAX];
@@ -1565,10 +1557,6 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
        }
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
 
        gsc_handle_irq(ctx, true, false, true);
 
@@ -1604,7 +1592,7 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
                exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
 
                /* src local path */
-               cfg = readl(GSC_IN_CON);
+               cfg = gsc_read(GSC_IN_CON);
                cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
                cfg |= (GSC_IN_PATH_LOCAL | GSC_IN_LOCAL_FIMD_WB);
                gsc_write(cfg, GSC_IN_CON);
@@ -1683,7 +1671,7 @@ static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
        gsc_write(cfg, GSC_ENABLE);
 }
 
-static int __devinit gsc_probe(struct platform_device *pdev)
+static int gsc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct gsc_context *ctx;
@@ -1696,34 +1684,25 @@ static int __devinit gsc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        /* clock control */
-       ctx->gsc_clk = clk_get(dev, "gscl");
+       ctx->gsc_clk = devm_clk_get(dev, "gscl");
        if (IS_ERR(ctx->gsc_clk)) {
                dev_err(dev, "failed to get gsc clock.\n");
-               ret = PTR_ERR(ctx->gsc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->gsc_clk);
        }
 
        /* resource memory */
        ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!ctx->regs_res) {
-               dev_err(dev, "failed to find registers.\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
-
        ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
        if (!ctx->regs) {
                dev_err(dev, "failed to map registers.\n");
-               ret = -ENXIO;
-               goto err_clk;
+               return -ENXIO;
        }
 
        /* resource irq */
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
                dev_err(dev, "failed to request irq resource.\n");
-               ret = -ENOENT;
-               goto err_get_regs;
+               return -ENOENT;
        }
 
        ctx->irq = res->start;
@@ -1731,7 +1710,7 @@ static int __devinit gsc_probe(struct platform_device *pdev)
                IRQF_ONESHOT, "drm_gsc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
-               goto err_get_regs;
+               return ret;
        }
 
        /* context initailization */
@@ -1775,16 +1754,10 @@ err_ippdrv_register:
        pm_runtime_disable(dev);
 err_get_irq:
        free_irq(ctx->irq, ctx);
-err_get_regs:
-       devm_iounmap(dev, ctx->regs);
-err_clk:
-       clk_put(ctx->gsc_clk);
-err_ctx:
-       devm_kfree(dev, ctx);
        return ret;
 }
 
-static int __devexit gsc_remove(struct platform_device *pdev)
+static int gsc_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct gsc_context *ctx = get_gsc_context(dev);
@@ -1798,11 +1771,6 @@ static int __devexit gsc_remove(struct platform_device *pdev)
        pm_runtime_disable(dev);
 
        free_irq(ctx->irq, ctx);
-       devm_iounmap(dev, ctx->regs);
-
-       clk_put(ctx->gsc_clk);
-
-       devm_kfree(dev, ctx);
 
        return 0;
 }
@@ -1860,7 +1828,7 @@ static const struct dev_pm_ops gsc_pm_ops = {
 
 struct platform_driver gsc_driver = {
        .probe          = gsc_probe,
-       .remove         = __devexit_p(gsc_remove),
+       .remove         = gsc_remove,
        .driver         = {
                .name   = "exynos-drm-gsc",
                .owner  = THIS_MODULE,
index b3c3bc618c0f24d7ca21315ecb7b97477e800477..29ec1c5efcf2913cbb44e1fda3e9a830be0d2192 100644 (file)
@@ -6,24 +6,10 @@
  *     Jinyoung Jeon <jy0.jeon@samsung.com>
  *     Sangmin Lee <lsmin.lee@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_GSC_H_
index 55793c46e3c21c3c0e86125aa51a29f77382b14e..28644539b3056620912df744aaac7cccad6fa9a4 100644 (file)
@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev)
        return false;
 }
 
-static int drm_hdmi_get_edid(struct device *dev,
-               struct drm_connector *connector, u8 *edid, int len)
+static struct edid *drm_hdmi_get_edid(struct device *dev,
+                       struct drm_connector *connector)
 {
        struct drm_hdmi_context *ctx = to_context(dev);
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (hdmi_ops && hdmi_ops->get_edid)
-               return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
-                                         len);
+               return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
 
-       return 0;
+       return NULL;
 }
 
 static int drm_hdmi_check_timing(struct device *dev, void *timing)
@@ -385,7 +384,7 @@ static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
                mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
 }
 
-static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
+static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_drm_subdrv *subdrv;
@@ -413,7 +412,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
+static int exynos_drm_hdmi_remove(struct platform_device *pdev)
 {
        struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
 
@@ -426,7 +425,7 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
 
 struct platform_driver exynos_drm_common_hdmi_driver = {
        .probe          = exynos_drm_hdmi_probe,
-       .remove         = __devexit_p(exynos_drm_hdmi_remove),
+       .remove         = exynos_drm_hdmi_remove,
        .driver         = {
                .name   = "exynos-drm-hdmi",
                .owner  = THIS_MODULE,
index fcc3093ec8fe3f488379e8880e194037784c56b3..d80516fc9ed7efd4675dd582ba3601118a4ffbad 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  * Authoer: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_HDMI_H_
@@ -44,8 +30,8 @@ struct exynos_drm_hdmi_context {
 struct exynos_hdmi_ops {
        /* display */
        bool (*is_connected)(void *ctx);
-       int (*get_edid)(void *ctx, struct drm_connector *connector,
-                       u8 *edid, int len);
+       struct edid *(*get_edid)(void *ctx,
+                       struct drm_connector *connector);
        int (*check_timing)(void *ctx, void *timing);
        int (*power_on)(void *ctx, int mode);
 
index 2482b7f96341ac196c98e10eeed359dcdc0d70ea..3799d5c2b5df746590b2952ed1a93fce2910e085 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 <drmP.h>
index 18a0ca190b98426e7922777fecc1ab6c270ef51a..53b7deea8ab768e5b351124bf9b5968eef1e09ec 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * Authoer: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_IOMMU_H_
index 49eebe948ed2d3f2c4759e23bfc897257dfd57c7..1a556354e92fa15ee5b051600662a9f0d98a868b 100644 (file)
@@ -27,7 +27,7 @@
 #include "exynos_drm_iommu.h"
 
 /*
- * IPP is stand for Image Post Processing and
+ * IPP stands for Image Post Processing and
  * supports image scaler/rotator and input/output DMA operations.
  * using FIMC, GSC, Rotator, so on.
  * IPP is integration device driver of same attribute h/w
@@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
        }
 }
 
-void ipp_handle_cmd_work(struct device *dev,
+static void ipp_handle_cmd_work(struct device *dev,
                struct exynos_drm_ippdrv *ippdrv,
                struct drm_exynos_ipp_cmd_work *cmd_work,
                struct drm_exynos_ipp_cmd_node *c_node)
@@ -1292,7 +1292,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
        DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
 
        /* store command info in ippdrv */
-       ippdrv->cmd = c_node;
+       ippdrv->c_node = c_node;
 
        if (!ipp_check_mem_list(c_node)) {
                DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
@@ -1303,7 +1303,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
        ret = ipp_set_property(ippdrv, property);
        if (ret) {
                DRM_ERROR("failed to set property.\n");
-               ippdrv->cmd = NULL;
+               ippdrv->c_node = NULL;
                return ret;
        }
 
@@ -1487,11 +1487,6 @@ void ipp_sched_cmd(struct work_struct *work)
        mutex_lock(&c_node->cmd_lock);
 
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property:prop_id[%d]\n",
-                       c_node->property.prop_id);
-               goto err_unlock;
-       }
 
        switch (cmd_work->ctrl) {
        case IPP_CTRL_PLAY:
@@ -1704,7 +1699,7 @@ void ipp_sched_event(struct work_struct *work)
                return;
        }
 
-       c_node = ippdrv->cmd;
+       c_node = ippdrv->c_node;
        if (!c_node) {
                DRM_ERROR("failed to get command node.\n");
                return;
@@ -1888,14 +1883,14 @@ err_clear:
        return;
 }
 
-static int __devinit ipp_probe(struct platform_device *pdev)
+static int ipp_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ipp_context *ctx;
        struct exynos_drm_subdrv *subdrv;
        int ret;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -1916,8 +1911,7 @@ static int __devinit ipp_probe(struct platform_device *pdev)
        ctx->event_workq = create_singlethread_workqueue("ipp_event");
        if (!ctx->event_workq) {
                dev_err(dev, "failed to create event workqueue\n");
-               ret = -EINVAL;
-               goto err_clear;
+               return -EINVAL;
        }
 
        /*
@@ -1958,12 +1952,10 @@ err_cmd_workq:
        destroy_workqueue(ctx->cmd_workq);
 err_event_workq:
        destroy_workqueue(ctx->event_workq);
-err_clear:
-       kfree(ctx);
        return ret;
 }
 
-static int __devexit ipp_remove(struct platform_device *pdev)
+static int ipp_remove(struct platform_device *pdev)
 {
        struct ipp_context *ctx = platform_get_drvdata(pdev);
 
@@ -1985,8 +1977,6 @@ static int __devexit ipp_remove(struct platform_device *pdev)
        destroy_workqueue(ctx->cmd_workq);
        destroy_workqueue(ctx->event_workq);
 
-       kfree(ctx);
-
        return 0;
 }
 
@@ -2050,7 +2040,7 @@ static const struct dev_pm_ops ipp_pm_ops = {
 
 struct platform_driver ipp_driver = {
        .probe          = ipp_probe,
-       .remove         = __devexit_p(ipp_remove),
+       .remove         = ipp_remove,
        .driver         = {
                .name   = "exynos-drm-ipp",
                .owner  = THIS_MODULE,
index 28ffac95386cf0f8624987d57f99943232e4d335..4cadbea7dbde9d71b2011ae012b0e4c9b0b11ce3 100644 (file)
@@ -6,24 +6,10 @@
  *     Jinyoung Jeon <jy0.jeon@samsung.com>
  *     Sangmin Lee <lsmin.lee@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_IPP_H_
@@ -160,7 +146,7 @@ struct exynos_drm_ipp_ops {
  * @dedicated: dedicated ipp device.
  * @ops: source, destination operations.
  * @event_workq: event work queue.
- * @cmd: current command information.
+ * @c_node: current command information.
  * @cmd_list: list head for command information.
  * @prop_list: property informations of current ipp driver.
  * @check_property: check property about format, size, buffer.
@@ -178,7 +164,7 @@ struct exynos_drm_ippdrv {
        bool    dedicated;
        struct exynos_drm_ipp_ops       *ops[EXYNOS_DRM_OPS_MAX];
        struct workqueue_struct *event_workq;
-       struct drm_exynos_ipp_cmd_node *cmd;
+       struct drm_exynos_ipp_cmd_node *c_node;
        struct list_head        cmd_list;
        struct drm_exynos_ipp_prop_list *prop_list;
 
index 1c2366083c70e738a95b9ef0bd4369f2d4148fda..f976e29def6effa8adc973e92b28ba9f9add4443 100644 (file)
@@ -139,7 +139,7 @@ static irqreturn_t rotator_irq_handler(int irq, void *arg)
 {
        struct rot_context *rot = arg;
        struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work = c_node->event_work;
        enum rot_irq_status irq_status;
        u32 val;
@@ -513,6 +513,7 @@ static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@ -638,7 +639,7 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
        return 0;
 }
 
-static int __devinit rotator_probe(struct platform_device *pdev)
+static int rotator_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct rot_context *rot;
@@ -655,34 +656,26 @@ static int __devinit rotator_probe(struct platform_device *pdev)
                                platform_get_device_id(pdev)->driver_data;
 
        rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!rot->regs_res) {
-               dev_err(dev, "failed to find registers\n");
-               ret = -ENOENT;
-               goto err_get_resource;
-       }
-
        rot->regs = devm_request_and_ioremap(dev, rot->regs_res);
        if (!rot->regs) {
                dev_err(dev, "failed to map register\n");
-               ret = -ENXIO;
-               goto err_get_resource;
+               return -ENXIO;
        }
 
        rot->irq = platform_get_irq(pdev, 0);
        if (rot->irq < 0) {
                dev_err(dev, "failed to get irq\n");
-               ret = rot->irq;
-               goto err_get_irq;
+               return rot->irq;
        }
 
        ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
                        IRQF_ONESHOT, "drm_rotator", rot);
        if (ret < 0) {
                dev_err(dev, "failed to request irq\n");
-               goto err_get_irq;
+               return ret;
        }
 
-       rot->clock = clk_get(dev, "rotator");
+       rot->clock = devm_clk_get(dev, "rotator");
        if (IS_ERR_OR_NULL(rot->clock)) {
                dev_err(dev, "failed to get clock\n");
                ret = PTR_ERR(rot->clock);
@@ -720,17 +713,12 @@ static int __devinit rotator_probe(struct platform_device *pdev)
 err_ippdrv_register:
        devm_kfree(dev, ippdrv->prop_list);
        pm_runtime_disable(dev);
-       clk_put(rot->clock);
 err_clk_get:
        free_irq(rot->irq, rot);
-err_get_irq:
-       devm_iounmap(dev, rot->regs);
-err_get_resource:
-       devm_kfree(dev, rot);
        return ret;
 }
 
-static int __devexit rotator_remove(struct platform_device *pdev)
+static int rotator_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct rot_context *rot = dev_get_drvdata(dev);
@@ -740,17 +728,13 @@ static int __devexit rotator_remove(struct platform_device *pdev)
        exynos_drm_ippdrv_unregister(ippdrv);
 
        pm_runtime_disable(dev);
-       clk_put(rot->clock);
 
        free_irq(rot->irq, rot);
-       devm_iounmap(dev, rot->regs);
-
-       devm_kfree(dev, rot);
 
        return 0;
 }
 
-struct rot_limit_table rot_limit_tbl = {
+static struct rot_limit_table rot_limit_tbl = {
        .ycbcr420_2p = {
                .min_w = 32,
                .min_h = 32,
@@ -767,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = {
        },
 };
 
-struct platform_device_id rotator_driver_ids[] = {
+static struct platform_device_id rotator_driver_ids[] = {
        {
                .name           = "exynos-rot",
                .driver_data    = (unsigned long)&rot_limit_tbl,
@@ -845,7 +829,7 @@ static const struct dev_pm_ops rotator_pm_ops = {
 
 struct platform_driver rotator_driver = {
        .probe          = rotator_probe,
-       .remove         = __devexit_p(rotator_remove),
+       .remove         = rotator_remove,
        .id_table       = rotator_driver_ids,
        .driver         = {
                .name   = "exynos-rot",
index a2d7a14a52b60dd96f4210e98346d402e00d9460..71a0b4c0c1e897ea1191a4ee06caef787f175eb1 100644 (file)
@@ -5,24 +5,10 @@
  *     YoungJun Cho <yj44.cho@samsung.com>
  *     Eunchul Kim <chulspro.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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        _EXYNOS_DRM_ROTATOR_H_
index 99bfc38dfaa2944b849517f24463d6340ae1d9e5..13ccbd4bcfaa8c863f27d24870101c32166ecb47 100644 (file)
@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev)
        return ctx->connected ? true : false;
 }
 
-static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
-                               u8 *edid, int len)
+static struct edid *vidi_get_edid(struct device *dev,
+                       struct drm_connector *connector)
 {
        struct vidi_context *ctx = get_vidi_context(dev);
+       struct edid *edid;
+       int edid_len;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
         */
        if (!ctx->raw_edid) {
                DRM_DEBUG_KMS("raw_edid is null.\n");
-               return -EFAULT;
+               return ERR_PTR(-EFAULT);
        }
 
-       memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
-                                       * EDID_LENGTH, len));
+       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+       edid = kzalloc(edid_len, GFP_KERNEL);
+       if (!edid) {
+               DRM_DEBUG_KMS("failed to allocate edid\n");
+               return ERR_PTR(-ENOMEM);
+       }
 
-       return 0;
+       memcpy(edid, ctx->raw_edid, edid_len);
+       return edid;
 }
 
 static void *vidi_get_panel(struct device *dev)
@@ -372,34 +379,6 @@ static struct exynos_drm_manager vidi_manager = {
        .display_ops    = &vidi_display_ops,
 };
 
-static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
-       struct exynos_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
 static void vidi_fake_vblank_handler(struct work_struct *work)
 {
        struct vidi_context *ctx = container_of(work, struct vidi_context,
@@ -424,7 +403,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
 
        mutex_unlock(&ctx->lock);
 
-       vidi_finish_pageflip(subdrv->drm_dev, manager->pipe);
+       exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe);
 }
 
 static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
@@ -542,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
        struct exynos_drm_manager *manager;
        struct exynos_drm_display_ops *display_ops;
        struct drm_exynos_vidi_connection *vidi = data;
-       struct edid *raw_edid;
        int edid_len;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -579,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
        }
 
        if (vidi->connection) {
-               if (!vidi->edid) {
-                       DRM_DEBUG_KMS("edid data is null.\n");
+               struct edid *raw_edid  = (struct edid *)(uint32_t)vidi->edid;
+               if (!drm_edid_is_valid(raw_edid)) {
+                       DRM_DEBUG_KMS("edid data is invalid.\n");
                        return -EINVAL;
                }
-               raw_edid = (struct edid *)(uint32_t)vidi->edid;
                edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
                ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
                if (!ctx->raw_edid) {
@@ -609,7 +587,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
        return 0;
 }
 
-static int __devinit vidi_probe(struct platform_device *pdev)
+static int vidi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct vidi_context *ctx;
@@ -645,7 +623,7 @@ static int __devinit vidi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit vidi_remove(struct platform_device *pdev)
+static int vidi_remove(struct platform_device *pdev)
 {
        struct vidi_context *ctx = platform_get_drvdata(pdev);
 
@@ -683,7 +661,7 @@ static const struct dev_pm_ops vidi_pm_ops = {
 
 struct platform_driver vidi_driver = {
        .probe          = vidi_probe,
-       .remove         = __devexit_p(vidi_remove),
+       .remove         = vidi_remove,
        .driver         = {
                .name   = "exynos-drm-vidi",
                .owner  = THIS_MODULE,
index a4babe4e65d701f8dab8b71a2562b6bbdb6fe104..1e5fdaa36ccc203e4b91daa588895283ea1468bb 100644 (file)
@@ -3,24 +3,10 @@
  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  * Author: Inki Dae <inki.dae@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_VIDI_H_
index 2c46b6c0b82cf991e1a489c98389566ea5ae6f8a..fbab3c4686031ce9c07a1b19546ab73ddb4f92e7 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
 #include <linux/of_gpio.h>
-#include <plat/gpio-cfg.h>
 
 #include <drm/exynos_drm.h>
 
@@ -98,8 +97,7 @@ struct hdmi_context {
 
        void __iomem                    *regs;
        void                            *parent_ctx;
-       int                             external_irq;
-       int                             internal_irq;
+       int                             irq;
 
        struct i2c_client               *ddc_port;
        struct i2c_client               *hdmiphy_port;
@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx)
        return hdata->hpd;
 }
 
-static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
-                               u8 *edid, int len)
+static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
 {
        struct edid *raw_edid;
        struct hdmi_context *hdata = ctx;
@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
        if (!hdata->ddc_port)
-               return -ENODEV;
+               return ERR_PTR(-ENODEV);
 
        raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
-       if (raw_edid) {
-               hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
-               memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
-                                       * EDID_LENGTH, len));
-               DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
-                       (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
-                       raw_edid->width_cm, raw_edid->height_cm);
-               kfree(raw_edid);
-       } else {
-               return -ENODEV;
-       }
+       if (!raw_edid)
+               return ERR_PTR(-ENODEV);
 
-       return 0;
+       hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
+       DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
+               (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
+               raw_edid->width_cm, raw_edid->height_cm);
+
+       return raw_edid;
 }
 
 static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
 
        /* resetting HDMI core */
        hdmi_reg_writemask(hdata, reg,  0, HDMI_CORE_SW_RSTOUT);
-       mdelay(10);
+       usleep_range(10000, 12000);
        hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
-       mdelay(10);
+       usleep_range(10000, 12000);
 }
 
 static void hdmi_conf_init(struct hdmi_context *hdata)
 {
        struct hdmi_infoframe infoframe;
 
-       /* disable HPD interrupts */
+       /* disable HPD interrupts from HDMI IP block, use GPIO instead */
        hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
                HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
 
@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
                u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
                if (val & HDMI_PHY_STATUS_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
        /* steady state not achieved */
        if (tries == 0) {
@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
                u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
                if (val & HDMI_PHY_STATUS_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
        /* steady state not achieved */
        if (tries == 0) {
@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 
        /* reset hdmiphy */
        hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
-       mdelay(10);
+       usleep_range(10000, 12000);
        hdmi_reg_writemask(hdata, reg,  0, HDMI_PHY_SW_RSTOUT);
-       mdelay(10);
+       usleep_range(10000, 12000);
 }
 
 static void hdmiphy_poweron(struct hdmi_context *hdata)
@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
                return;
        }
 
-       mdelay(10);
+       usleep_range(10000, 12000);
 
        /* operation mode */
        operation[0] = 0x1f;
@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx)
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
+       mutex_lock(&hdata->hdmi_mutex);
+       if (!hdata->powered) {
+               mutex_unlock(&hdata->hdmi_mutex);
+               return;
+       }
+       mutex_unlock(&hdata->hdmi_mutex);
+
        hdmi_conf_apply(hdata);
 }
 
@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
        .dpms           = hdmi_dpms,
 };
 
-static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
+static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 {
        struct exynos_drm_hdmi_context *ctx = arg;
        struct hdmi_context *hdata = ctx->ctx;
@@ -2280,32 +2280,7 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
-{
-       struct exynos_drm_hdmi_context *ctx = arg;
-       struct hdmi_context *hdata = ctx->ctx;
-       u32 intc_flag;
-
-       intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
-       /* clearing flags for HPD plug/unplug */
-       if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
-               DRM_DEBUG_KMS("unplugged\n");
-               hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
-                       HDMI_INTC_FLAG_HPD_UNPLUG);
-       }
-       if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
-               DRM_DEBUG_KMS("plugged\n");
-               hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
-                       HDMI_INTC_FLAG_HPD_PLUG);
-       }
-
-       if (ctx->drm_dev)
-               drm_helper_hpd_irq_event(ctx->drm_dev);
-
-       return IRQ_HANDLED;
-}
-
-static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
+static int hdmi_resources_init(struct hdmi_context *hdata)
 {
        struct device *dev = hdata->dev;
        struct hdmi_resources *res = &hdata->res;
@@ -2451,7 +2426,7 @@ static struct of_device_id hdmi_match_types[] = {
 };
 #endif
 
-static int __devinit hdmi_probe(struct platform_device *pdev)
+static int hdmi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_drm_hdmi_context *drm_hdmi_ctx;
@@ -2555,39 +2530,24 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
 
        hdata->hdmiphy_port = hdmi_hdmiphy;
 
-       hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
-       if (hdata->external_irq < 0) {
-               DRM_ERROR("failed to get GPIO external irq\n");
-               ret = hdata->external_irq;
-               goto err_hdmiphy;
-       }
-
-       hdata->internal_irq = platform_get_irq(pdev, 0);
-       if (hdata->internal_irq < 0) {
-               DRM_ERROR("failed to get platform internal irq\n");
-               ret = hdata->internal_irq;
+       hdata->irq = gpio_to_irq(hdata->hpd_gpio);
+       if (hdata->irq < 0) {
+               DRM_ERROR("failed to get GPIO irq\n");
+               ret = hdata->irq;
                goto err_hdmiphy;
        }
 
        hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
-       ret = request_threaded_irq(hdata->external_irq, NULL,
-                       hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
+       ret = request_threaded_irq(hdata->irq, NULL,
+                       hdmi_irq_thread, IRQF_TRIGGER_RISING |
                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                       "hdmi_external", drm_hdmi_ctx);
+                       "hdmi", drm_hdmi_ctx);
        if (ret) {
-               DRM_ERROR("failed to register hdmi external interrupt\n");
+               DRM_ERROR("failed to register hdmi interrupt\n");
                goto err_hdmiphy;
        }
 
-       ret = request_threaded_irq(hdata->internal_irq, NULL,
-                       hdmi_internal_irq_thread, IRQF_ONESHOT,
-                       "hdmi_internal", drm_hdmi_ctx);
-       if (ret) {
-               DRM_ERROR("failed to register hdmi internal interrupt\n");
-               goto err_free_irq;
-       }
-
        /* Attach HDMI Driver to common hdmi. */
        exynos_hdmi_drv_attach(drm_hdmi_ctx);
 
@@ -2598,8 +2558,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
 
        return 0;
 
-err_free_irq:
-       free_irq(hdata->external_irq, drm_hdmi_ctx);
 err_hdmiphy:
        i2c_del_driver(&hdmiphy_driver);
 err_ddc:
@@ -2607,7 +2565,7 @@ err_ddc:
        return ret;
 }
 
-static int __devexit hdmi_remove(struct platform_device *pdev)
+static int hdmi_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
@@ -2617,8 +2575,7 @@ static int __devexit hdmi_remove(struct platform_device *pdev)
 
        pm_runtime_disable(dev);
 
-       free_irq(hdata->internal_irq, hdata);
-       free_irq(hdata->external_irq, hdata);
+       free_irq(hdata->irq, hdata);
 
 
        /* hdmiphy i2c driver */
@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev)
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
-       disable_irq(hdata->internal_irq);
-       disable_irq(hdata->external_irq);
+       disable_irq(hdata->irq);
 
        hdata->hpd = false;
        if (ctx->drm_dev)
@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev)
 
        hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
-       enable_irq(hdata->external_irq);
-       enable_irq(hdata->internal_irq);
+       enable_irq(hdata->irq);
 
        if (!pm_runtime_suspended(dev)) {
                DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
@@ -2708,7 +2663,7 @@ static const struct dev_pm_ops hdmi_pm_ops = {
 
 struct platform_driver hdmi_driver = {
        .probe          = hdmi_probe,
-       .remove         = __devexit_p(hdmi_remove),
+       .remove         = hdmi_remove,
        .id_table = hdmi_driver_types,
        .driver         = {
                .name   = "exynos-hdmi",
index 1c3b6d8f1fe796fac9d9b37bd341f703e740861f..0ddf3957de15943855b8bc4b2fa56c415f22520a 100644 (file)
@@ -5,24 +5,10 @@
  *     Inki Dae <inki.dae@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_HDMI_H_
index 6206056f4a3328b7b4e5e58b78e64140a0b32bcc..ea49d132ecf66f2696d3673f3df1dfa09d2cfbaa 100644 (file)
@@ -64,7 +64,7 @@ struct i2c_driver hdmiphy_driver = {
        },
        .id_table = hdmiphy_id,
        .probe          = hdmiphy_probe,
-       .remove         = __devexit_p(hdmiphy_remove),
+       .remove         = hdmiphy_remove,
        .command                = NULL,
 };
 EXPORT_SYMBOL(hdmiphy_driver);
index 21db89530fc77b603ed45fe6109b6b67059f3430..c414584bfbaecf36d285be933e9e212fbea7784d 100644 (file)
@@ -35,6 +35,7 @@
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_hdmi.h"
 #include "exynos_drm_iommu.h"
 
@@ -599,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx)
                /* waiting until VP_SRESET_PROCESSING is 0 */
                if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
                        break;
-               mdelay(10);
+               usleep_range(10000, 12000);
        }
        WARN(tries == 0, "failed to reset Video Processor\n");
 }
@@ -775,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win)
 
        DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
 
+       mutex_lock(&mixer_ctx->mixer_mutex);
+       if (!mixer_ctx->powered) {
+               mutex_unlock(&mixer_ctx->mixer_mutex);
+               return;
+       }
+       mutex_unlock(&mixer_ctx->mixer_mutex);
+
        if (win > 1 && mixer_ctx->vp_enabled)
                vp_video_buffer(mixer_ctx, win);
        else
@@ -949,35 +957,6 @@ static struct exynos_mixer_ops mixer_ops = {
        .win_disable            = mixer_win_disable,
 };
 
-/* for pageflip event */
-static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
-{
-       struct exynos_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-}
-
 static irqreturn_t mixer_irq_handler(int irq, void *arg)
 {
        struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
@@ -1006,7 +985,8 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                }
 
                drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
-               mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
+               exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
+                               ctx->pipe);
 
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
@@ -1029,8 +1009,8 @@ out:
        return IRQ_HANDLED;
 }
 
-static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
-                                struct platform_device *pdev)
+static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
+                               struct platform_device *pdev)
 {
        struct mixer_context *mixer_ctx = ctx->ctx;
        struct device *dev = &pdev->dev;
@@ -1081,8 +1061,8 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
        return 0;
 }
 
-static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
-                                struct platform_device *pdev)
+static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
+                            struct platform_device *pdev)
 {
        struct mixer_context *mixer_ctx = ctx->ctx;
        struct device *dev = &pdev->dev;
@@ -1155,7 +1135,7 @@ static struct of_device_id mixer_match_types[] = {
        }
 };
 
-static int __devinit mixer_probe(struct platform_device *pdev)
+static int mixer_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_drm_hdmi_context *drm_hdmi_ctx;
@@ -1316,6 +1296,6 @@ struct platform_driver mixer_driver = {
                .of_match_table = mixer_match_types,
        },
        .probe = mixer_probe,
-       .remove = __devexit_p(mixer_remove),
+       .remove = mixer_remove,
        .id_table       = mixer_driver_types,
 };
index 4a07ab5961745f1af3bd7d2cfd8c1f70a1d7d4f0..771ff66711af78efd79f8b41c2e2a28be2f26cdf 100644 (file)
@@ -700,7 +700,7 @@ static struct i2c_driver tc35876x_bridge_i2c_driver = {
        },
        .id_table = tc35876x_bridge_id,
        .probe = tc35876x_bridge_probe,
-       .remove = __devexit_p(tc35876x_bridge_remove),
+       .remove = tc35876x_bridge_remove,
 };
 
 /* LCD panel I2C */
@@ -741,7 +741,7 @@ static struct i2c_driver cmi_lcd_i2c_driver = {
        },
        .id_table = cmi_lcd_i2c_id,
        .probe = cmi_lcd_i2c_probe,
-       .remove = __devexit_p(cmi_lcd_i2c_remove),
+       .remove = cmi_lcd_i2c_remove,
 };
 
 /* HACK to create I2C device while it's not created by platform code */
index e6a11ca85eafa913f97d315493abd995fd0a764c..9d4a2c2adf0e0883d76d13070fa09f7aa32e1526 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <generated/utsrelease.h>
 #include <drm/drmP.h>
 #include "intel_drv.h"
 #include "intel_ringbuffer.h"
@@ -641,6 +642,7 @@ static void i915_ring_error_state(struct seq_file *m,
        seq_printf(m, "%s command stream:\n", ring_str(ring));
        seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
        seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
+       seq_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
        seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
        seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
        seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
@@ -689,10 +691,13 @@ static int i915_error_state(struct seq_file *m, void *unused)
 
        seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
                   error->time.tv_usec);
+       seq_printf(m, "Kernel: " UTS_RELEASE);
        seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
        seq_printf(m, "EIR: 0x%08x\n", error->eir);
        seq_printf(m, "IER: 0x%08x\n", error->ier);
        seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+       seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+       seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
        seq_printf(m, "CCID: 0x%08x\n", error->ccid);
 
        for (i = 0; i < dev_priv->num_fence_regs; i++)
index 8f63cd5de4b445cd247dddf078af7dc8686d49a5..99daa896105d0b221d084ab1ed4b0c839983dcdd 100644 (file)
@@ -989,6 +989,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_SECURE_BATCHES:
                value = capable(CAP_SYS_ADMIN);
                break;
+       case I915_PARAM_HAS_PINNED_BATCHES:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
index 530db83ef32018ac3807dcb89fa88bfe1fac665f..117265840b1ff2fcbd845c618acf8d3b592cd4a5 100644 (file)
@@ -877,8 +877,7 @@ int i915_reset(struct drm_device *dev)
        return 0;
 }
 
-static int __devinit
-i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int 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;
index 557843dd4b2eeedcf1225999b40917a7011fb20a..12ab3bdea54dca227e8bd5f3f62cf00a31ce85ba 100644 (file)
@@ -188,10 +188,13 @@ struct drm_i915_error_state {
        u32 pgtbl_er;
        u32 ier;
        u32 ccid;
+       u32 derrmr;
+       u32 forcewake;
        bool waiting[I915_NUM_RINGS];
        u32 pipestat[I915_MAX_PIPES];
        u32 tail[I915_NUM_RINGS];
        u32 head[I915_NUM_RINGS];
+       u32 ctl[I915_NUM_RINGS];
        u32 ipeir[I915_NUM_RINGS];
        u32 ipehr[I915_NUM_RINGS];
        u32 instdone[I915_NUM_RINGS];
@@ -780,6 +783,7 @@ typedef struct drm_i915_private {
                struct i915_hw_ppgtt *aliasing_ppgtt;
 
                struct shrinker inactive_shrinker;
+               bool shrinker_no_lock_stealing;
 
                /**
                 * List of objects currently involved in rendering.
@@ -1100,6 +1104,7 @@ struct drm_i915_gem_object {
         */
        atomic_t pending_flip;
 };
+#define to_gem_object(obj) (&((struct drm_i915_gem_object *)(obj))->base)
 
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
@@ -1166,6 +1171,9 @@ struct drm_i915_file_private {
 #define IS_IVB_GT1(dev)                ((dev)->pci_device == 0x0156 || \
                                 (dev)->pci_device == 0x0152 || \
                                 (dev)->pci_device == 0x015a)
+#define IS_SNB_GT1(dev)                ((dev)->pci_device == 0x0102 || \
+                                (dev)->pci_device == 0x0106 || \
+                                (dev)->pci_device == 0x010A)
 #define IS_VALLEYVIEW(dev)     (INTEL_INFO(dev)->is_valleyview)
 #define IS_HASWELL(dev)        (INTEL_INFO(dev)->is_haswell)
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
@@ -1196,6 +1204,9 @@ struct drm_i915_file_private {
 #define HAS_OVERLAY(dev)               (INTEL_INFO(dev)->has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev)    (INTEL_INFO(dev)->overlay_needs_physical)
 
+/* Early gen2 have a totally busted CS tlb and require pinned batches. */
+#define HAS_BROKEN_CS_TLB(dev)         (IS_I830(dev) || IS_845G(dev))
+
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
index 742206e45103c508bd9c2d9ebac2281e704d5ff2..8febea6daa0840b08f8aae13418b859204b7bc2d 100644 (file)
@@ -1517,9 +1517,11 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
        if (obj->base.map_list.map)
                return 0;
 
+       dev_priv->mm.shrinker_no_lock_stealing = true;
+
        ret = drm_gem_create_mmap_offset(&obj->base);
        if (ret != -ENOSPC)
-               return ret;
+               goto out;
 
        /* Badly fragmented mmap space? The only way we can recover
         * space is by destroying unwanted objects. We can't randomly release
@@ -1531,10 +1533,14 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
        i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT);
        ret = drm_gem_create_mmap_offset(&obj->base);
        if (ret != -ENOSPC)
-               return ret;
+               goto out;
 
        i915_gem_shrink_all(dev_priv);
-       return drm_gem_create_mmap_offset(&obj->base);
+       ret = drm_gem_create_mmap_offset(&obj->base);
+out:
+       dev_priv->mm.shrinker_no_lock_stealing = false;
+
+       return ret;
 }
 
 static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
@@ -1711,7 +1717,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
 }
 
 static long
-i915_gem_purge(struct drm_i915_private *dev_priv, long target)
+__i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
+                 bool purgeable_only)
 {
        struct drm_i915_gem_object *obj, *next;
        long count = 0;
@@ -1719,7 +1726,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target)
        list_for_each_entry_safe(obj, next,
                                 &dev_priv->mm.unbound_list,
                                 gtt_list) {
-               if (i915_gem_object_is_purgeable(obj) &&
+               if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
                    i915_gem_object_put_pages(obj) == 0) {
                        count += obj->base.size >> PAGE_SHIFT;
                        if (count >= target)
@@ -1730,7 +1737,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target)
        list_for_each_entry_safe(obj, next,
                                 &dev_priv->mm.inactive_list,
                                 mm_list) {
-               if (i915_gem_object_is_purgeable(obj) &&
+               if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
                    i915_gem_object_unbind(obj) == 0 &&
                    i915_gem_object_put_pages(obj) == 0) {
                        count += obj->base.size >> PAGE_SHIFT;
@@ -1742,6 +1749,12 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target)
        return count;
 }
 
+static long
+i915_gem_purge(struct drm_i915_private *dev_priv, long target)
+{
+       return __i915_gem_shrink(dev_priv, target, true);
+}
+
 static void
 i915_gem_shrink_all(struct drm_i915_private *dev_priv)
 {
@@ -2890,7 +2903,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 {
        struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_mm_node *free_space;
+       struct drm_mm_node *node;
        u32 size, fence_size, fence_alignment, unfenced_alignment;
        bool mappable, fenceable;
        int ret;
@@ -2936,66 +2949,54 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 
        i915_gem_object_pin_pages(obj);
 
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (node == NULL) {
+               i915_gem_object_unpin_pages(obj);
+               return -ENOMEM;
+       }
+
  search_free:
        if (map_and_fenceable)
-               free_space = drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
-                                                              size, alignment, obj->cache_level,
-                                                              0, dev_priv->mm.gtt_mappable_end,
-                                                              false);
+               ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
+                                                         size, alignment, obj->cache_level,
+                                                         0, dev_priv->mm.gtt_mappable_end);
        else
-               free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
-                                                     size, alignment, obj->cache_level,
-                                                     false);
-
-       if (free_space != NULL) {
-               if (map_and_fenceable)
-                       free_space =
-                               drm_mm_get_block_range_generic(free_space,
-                                                              size, alignment, obj->cache_level,
-                                                              0, dev_priv->mm.gtt_mappable_end,
-                                                              false);
-               else
-                       free_space =
-                               drm_mm_get_block_generic(free_space,
-                                                        size, alignment, obj->cache_level,
-                                                        false);
-       }
-       if (free_space == NULL) {
+               ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
+                                                size, alignment, obj->cache_level);
+       if (ret) {
                ret = i915_gem_evict_something(dev, size, alignment,
                                               obj->cache_level,
                                               map_and_fenceable,
                                               nonblocking);
-               if (ret) {
-                       i915_gem_object_unpin_pages(obj);
-                       return ret;
-               }
+               if (ret == 0)
+                       goto search_free;
 
-               goto search_free;
+               i915_gem_object_unpin_pages(obj);
+               kfree(node);
+               return ret;
        }
-       if (WARN_ON(!i915_gem_valid_gtt_space(dev,
-                                             free_space,
-                                             obj->cache_level))) {
+       if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
                i915_gem_object_unpin_pages(obj);
-               drm_mm_put_block(free_space);
+               drm_mm_put_block(node);
                return -EINVAL;
        }
 
        ret = i915_gem_gtt_prepare_object(obj);
        if (ret) {
                i915_gem_object_unpin_pages(obj);
-               drm_mm_put_block(free_space);
+               drm_mm_put_block(node);
                return ret;
        }
 
        list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
        list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
-       obj->gtt_space = free_space;
-       obj->gtt_offset = free_space->start;
+       obj->gtt_space = node;
+       obj->gtt_offset = node->start;
 
        fenceable =
-               free_space->size == fence_size &&
-               (free_space->start & (fence_alignment - 1)) == 0;
+               node->size == fence_size &&
+               (node->start & (fence_alignment - 1)) == 0;
 
        mappable =
                obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
@@ -3528,14 +3529,15 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
                goto out;
        }
 
-       obj->user_pin_count++;
-       obj->pin_filp = file;
-       if (obj->user_pin_count == 1) {
+       if (obj->user_pin_count == 0) {
                ret = i915_gem_object_pin(obj, args->alignment, true, false);
                if (ret)
                        goto out;
        }
 
+       obj->user_pin_count++;
+       obj->pin_filp = file;
+
        /* XXX - flush the CPU caches for pinned objects
         * as the X server doesn't manage domains yet
         */
@@ -4392,11 +4394,17 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
                if (!mutex_is_locked_by(&dev->struct_mutex, current))
                        return 0;
 
+               if (dev_priv->mm.shrinker_no_lock_stealing)
+                       return 0;
+
                unlock = false;
        }
 
        if (nr_to_scan) {
                nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
+               if (nr_to_scan > 0)
+                       nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan,
+                                                       false);
                if (nr_to_scan > 0)
                        i915_gem_shrink_all(dev_priv);
        }
@@ -4405,7 +4413,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
        list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
                if (obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
-       list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
+       list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
                if (obj->pin_count == 0 && obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
 
index 773ef77b6c22cc047af54ba70dd491039d7473c0..abeaafef6d7ef9986313be7ab8e0c2c5a992c065 100644 (file)
@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
 {
        struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 
-       return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600);
+       return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags);
 }
 
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
                obj = dma_buf->priv;
                /* is it from our device? */
                if (obj->base.dev == dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(&obj->base);
+                       dma_buf_put(dma_buf);
                        return &obj->base;
                }
        }
index ee8f97f0539ec6fb8a8392378219ebaa1f91d3bb..26d08bb5821894daad6cdd1fa79b58f86cf226e2 100644 (file)
@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
        total = 0;
        for (i = 0; i < count; i++) {
                struct drm_i915_gem_relocation_entry __user *user_relocs;
+               u64 invalid_offset = (u64)-1;
+               int j;
 
                user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
 
@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                        goto err;
                }
 
+               /* As we do not update the known relocation offsets after
+                * relocating (due to the complexities in lock handling),
+                * we need to mark them as invalid now so that we force the
+                * relocation processing next time. Just in case the target
+                * object is evicted and then rebound into its old
+                * presumed_offset before the next execbuffer - if that
+                * happened we would make the mistake of assuming that the
+                * relocations were valid.
+                */
+               for (j = 0; j < exec[i].relocation_count; j++) {
+                       if (copy_to_user(&user_relocs[j].presumed_offset,
+                                        &invalid_offset,
+                                        sizeof(invalid_offset))) {
+                               ret = -EFAULT;
+                               mutex_lock(&dev->struct_mutex);
+                               goto err;
+                       }
+               }
+
                reloc_offset[i] = total;
                total += exec[i].relocation_count;
        }
@@ -808,6 +829,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
                flags |= I915_DISPATCH_SECURE;
        }
+       if (args->flags & I915_EXEC_IS_PINNED)
+               flags |= I915_DISPATCH_PINNED;
 
        switch (args->flags & I915_EXEC_RING_MASK) {
        case I915_EXEC_DEFAULT:
index a4dc97f8b9f0f7d08fd0c2525e039d9893d76735..fe843389c7b473e2035124c38330c3a965450773 100644 (file)
@@ -1087,6 +1087,18 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
        if (!ring->get_seqno)
                return NULL;
 
+       if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
+               u32 acthd = I915_READ(ACTHD);
+
+               if (WARN_ON(ring->id != RCS))
+                       return NULL;
+
+               obj = ring->private;
+               if (acthd >= obj->gtt_offset &&
+                   acthd < obj->gtt_offset + obj->base.size)
+                       return i915_error_object_create(dev_priv, obj);
+       }
+
        seqno = ring->get_seqno(ring, false);
        list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
                if (obj->ring != ring)
@@ -1145,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev,
        error->acthd[ring->id] = intel_ring_get_active_head(ring);
        error->head[ring->id] = I915_READ_HEAD(ring);
        error->tail[ring->id] = I915_READ_TAIL(ring);
+       error->ctl[ring->id] = I915_READ_CTL(ring);
 
        error->cpu_ring_head[ring->id] = ring->head;
        error->cpu_ring_tail[ring->id] = ring->tail;
@@ -1239,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev)
        else
                error->ier = I915_READ(IER);
 
+       if (INTEL_INFO(dev)->gen >= 6)
+               error->derrmr = I915_READ(DERRMR);
+
+       if (IS_VALLEYVIEW(dev))
+               error->forcewake = I915_READ(FORCEWAKE_VLV);
+       else if (INTEL_INFO(dev)->gen >= 7)
+               error->forcewake = I915_READ(FORCEWAKE_MT);
+       else if (INTEL_INFO(dev)->gen == 6)
+               error->forcewake = I915_READ(FORCEWAKE);
+
        for_each_pipe(pipe)
                error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 
index 3f75cfaf1c3f2df48e9955e95445fb8b4ab78f62..59afb7eb6db635cf2f9bbe5477ffc8bd75fddd30 100644 (file)
 #define GEN7_ERR_INT   0x44040
 #define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 
+#define DERRMR         0x44050
+
 /* GM45+ chicken bits -- debug workaround bits that may be required
  * for various sorts of correct behavior.  The top 16 bits of each are
  * the enables for writing to the corresponding low bit.
  */
 #define _3D_CHICKEN    0x02084
+#define  _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB     (1 << 10)
 #define _3D_CHICKEN2   0x0208c
 /* Disables pipelining of read flushes past the SF-WIZ interface.
  * Required on all Ironlake steppings according to the B-Spec, but the
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
 # define MI_FLUSH_ENABLE                               (1 << 12)
+# define ASYNC_FLIP_PERF_DISABLE                       (1 << 14)
 
 #define GEN6_GT_MODE   0x20d0
-#define   GEN6_GT_MODE_HI      (1 << 9)
+#define   GEN6_GT_MODE_HI                              (1 << 9)
+#define   GEN6_TD_FOUR_ROW_DISPATCH_DISABLE            (1 << 5)
 
 #define GFX_MODE       0x02520
 #define GFX_MODE_GEN7  0x0229c
index 5d127e0689501e225316424a242b726c20ca6376..da1ad9c80bb53722e7afd423b27a819f31ff6927 100644 (file)
@@ -8144,10 +8144,6 @@ intel_modeset_stage_output_state(struct drm_device *dev,
                        DRM_DEBUG_KMS("encoder changed, full mode switch\n");
                        config->mode_changed = true;
                }
-
-               /* Disable all disconnected encoders. */
-               if (connector->base.status == connector_status_disconnected)
-                       connector->new_encoder = NULL;
        }
        /* connector->new_encoder is now updated for all connectors. */
 
@@ -8602,19 +8598,30 @@ int intel_framebuffer_init(struct drm_device *dev,
 {
        int ret;
 
-       if (obj->tiling_mode == I915_TILING_Y)
+       if (obj->tiling_mode == I915_TILING_Y) {
+               DRM_DEBUG("hardware does not support tiling Y\n");
                return -EINVAL;
+       }
 
-       if (mode_cmd->pitches[0] & 63)
+       if (mode_cmd->pitches[0] & 63) {
+               DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
+                         mode_cmd->pitches[0]);
                return -EINVAL;
+       }
 
        /* FIXME <= Gen4 stride limits are bit unclear */
-       if (mode_cmd->pitches[0] > 32768)
+       if (mode_cmd->pitches[0] > 32768) {
+               DRM_DEBUG("pitch (%d) must be at less than 32768\n",
+                         mode_cmd->pitches[0]);
                return -EINVAL;
+       }
 
        if (obj->tiling_mode != I915_TILING_NONE &&
-           mode_cmd->pitches[0] != obj->stride)
+           mode_cmd->pitches[0] != obj->stride) {
+               DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
+                         mode_cmd->pitches[0], obj->stride);
                return -EINVAL;
+       }
 
        /* Reject formats not supported by any plane early. */
        switch (mode_cmd->pixel_format) {
@@ -8625,8 +8632,10 @@ int intel_framebuffer_init(struct drm_device *dev,
                break;
        case DRM_FORMAT_XRGB1555:
        case DRM_FORMAT_ARGB1555:
-               if (INTEL_INFO(dev)->gen > 3)
+               if (INTEL_INFO(dev)->gen > 3) {
+                       DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
                        return -EINVAL;
+               }
                break;
        case DRM_FORMAT_XBGR8888:
        case DRM_FORMAT_ABGR8888:
@@ -8634,18 +8643,22 @@ int intel_framebuffer_init(struct drm_device *dev,
        case DRM_FORMAT_ARGB2101010:
        case DRM_FORMAT_XBGR2101010:
        case DRM_FORMAT_ABGR2101010:
-               if (INTEL_INFO(dev)->gen < 4)
+               if (INTEL_INFO(dev)->gen < 4) {
+                       DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
                        return -EINVAL;
+               }
                break;
        case DRM_FORMAT_YUYV:
        case DRM_FORMAT_UYVY:
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_VYUY:
-               if (INTEL_INFO(dev)->gen < 6)
+               if (INTEL_INFO(dev)->gen < 5) {
+                       DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
                        return -EINVAL;
+               }
                break;
        default:
-               DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
+               DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
                return -EINVAL;
        }
 
@@ -9167,6 +9180,23 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
         * the crtc fixup. */
 }
 
+static void i915_redisable_vga(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 vga_reg;
+
+       if (HAS_PCH_SPLIT(dev))
+               vga_reg = CPU_VGACNTRL;
+       else
+               vga_reg = VGACNTRL;
+
+       if (I915_READ(vga_reg) != VGA_DISP_DISABLE) {
+               DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
+               I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+               POSTING_READ(vga_reg);
+       }
+}
+
 /* Scan out the current hw modeset state, sanitizes it and maps it into the drm
  * and i915 state tracking structures. */
 void intel_modeset_setup_hw_state(struct drm_device *dev,
@@ -9275,6 +9305,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                        intel_set_mode(&crtc->base, &crtc->base.mode,
                                       crtc->base.x, crtc->base.y, crtc->base.fb);
                }
+
+               i915_redisable_vga(dev);
        } else {
                intel_modeset_update_staged_output_state(dev);
        }
index 1b63d55318a0b466cdd45f6fcfb9af9259473557..fb3715b4b09d26d1357fdfe16320d6680f5ee92a 100644 (file)
@@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 
 static void
 intel_dp_init_panel_power_sequencer(struct drm_device *dev,
-                                   struct intel_dp *intel_dp)
+                                   struct intel_dp *intel_dp,
+                                   struct edp_power_seq *out)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct edp_power_seq cur, vbt, spec, final;
@@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
 #undef get_delay
 
+       DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+                     intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+                     intel_dp->panel_power_cycle_delay);
+
+       DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+                     intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+       if (out)
+               *out = final;
+}
+
+static void
+intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
+                                             struct intel_dp *intel_dp,
+                                             struct edp_power_seq *seq)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_on, pp_off, pp_div;
+
        /* And finally store the new values in the power sequencer. */
-       pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
-               (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
-       pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
-                (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
+       pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
+               (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
+       pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+                (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
        /* Compute the divisor for the pp clock, simply match the Bspec
         * formula. */
        pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
                        << PP_REFERENCE_DIVIDER_SHIFT;
-       pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
+       pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
                        << PANEL_POWER_CYCLE_DELAY_SHIFT);
 
        /* Haswell doesn't have any port selection bits for the panel
@@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
        I915_WRITE(PCH_PP_DIVISOR, pp_div);
 
-
-       DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
-                     intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
-                     intel_dp->panel_power_cycle_delay);
-
-       DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
-                     intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
-
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
                      I915_READ(PCH_PP_ON_DELAYS),
                      I915_READ(PCH_PP_OFF_DELAYS),
@@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *fixed_mode = NULL;
+       struct edp_power_seq power_seq = { 0 };
        enum port port = intel_dig_port->port;
        const char *name = NULL;
        int type;
@@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        }
 
        if (is_edp(intel_dp))
-               intel_dp_init_panel_power_sequencer(dev, intel_dp);
+               intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 
        intel_dp_i2c_init(intel_dp, intel_connector, name);
 
@@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                        return;
                }
 
+               /* We now know it's not a ghost, init power sequence regs. */
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+                                                             &power_seq);
+
                ironlake_edp_panel_vdd_on(intel_dp);
                edid = drm_get_edid(connector, &intel_dp->adapter);
                if (edid) {
index b9a660a536772fd6728255b6173c047d8607222e..17aee74258ad4dfa43083e431fc3f0b224aa4ec4 100644 (file)
@@ -774,14 +774,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
                },
        },
-       {
-               .callback = intel_no_lvds_dmi_callback,
-               .ident = "ZOTAC ZBOXSD-ID12/ID13",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"),
-                       DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
-               },
-       },
        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Gigabyte GA-D525TUD",
index 496caa73eb705ed0c99415c1d42a5bf6aa17b3dc..3280cffe50f4486a4812d809d51ea904f79f04a9 100644 (file)
  * i915.i915_enable_fbc parameter
  */
 
+static bool intel_crtc_active(struct drm_crtc *crtc)
+{
+       /* Be paranoid as we can arrive here with only partial
+        * state retrieved from the hardware during setup.
+        */
+       return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock;
+}
+
 static void i8xx_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device *dev)
         *   - going to an unsupported config (interlace, pixel multiply, etc.)
         */
        list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-               if (tmp_crtc->enabled &&
-                   !to_intel_crtc(tmp_crtc)->primary_disabled &&
-                   tmp_crtc->fb) {
+               if (intel_crtc_active(tmp_crtc) &&
+                   !to_intel_crtc(tmp_crtc)->primary_disabled) {
                        if (crtc) {
                                DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
                                dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
        struct drm_crtc *crtc, *enabled = NULL;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->enabled && crtc->fb) {
+               if (intel_crtc_active(crtc)) {
                        if (enabled)
                                return NULL;
                        enabled = crtc;
@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        int entries, tlb_miss;
 
        crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled) {
+       if (!intel_crtc_active(crtc)) {
                *cursor_wm = cursor->guard_size;
                *plane_wm = display->guard_size;
                return false;
@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
        int entries;
 
        crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled)
+       if (!intel_crtc_active(crtc))
                return false;
 
        clock = crtc->mode.clock;       /* VESA DOT Clock */
@@ -1286,6 +1293,7 @@ static void valleyview_update_wm(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
        int plane_sr, cursor_sr;
+       int ignore_plane_sr, ignore_cursor_sr;
        unsigned int enabled = 0;
 
        vlv_update_drain_latency(dev);
@@ -1302,17 +1310,23 @@ static void valleyview_update_wm(struct drm_device *dev)
                            &planeb_wm, &cursorb_wm))
                enabled |= 2;
 
-       plane_sr = cursor_sr = 0;
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
                             sr_latency_ns,
                             &valleyview_wm_info,
                             &valleyview_cursor_wm_info,
-                            &plane_sr, &cursor_sr))
+                            &plane_sr, &ignore_cursor_sr) &&
+           g4x_compute_srwm(dev, ffs(enabled) - 1,
+                            2*sr_latency_ns,
+                            &valleyview_wm_info,
+                            &valleyview_cursor_wm_info,
+                            &ignore_plane_sr, &cursor_sr)) {
                I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN);
-       else
+       } else {
                I915_WRITE(FW_BLC_SELF_VLV,
                           I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN);
+               plane_sr = cursor_sr = 0;
+       }
 
        DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
                      planea_wm, cursora_wm,
@@ -1352,17 +1366,18 @@ static void g4x_update_wm(struct drm_device *dev)
                            &planeb_wm, &cursorb_wm))
                enabled |= 2;
 
-       plane_sr = cursor_sr = 0;
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
                             sr_latency_ns,
                             &g4x_wm_info,
                             &g4x_cursor_wm_info,
-                            &plane_sr, &cursor_sr))
+                            &plane_sr, &cursor_sr)) {
                I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
-       else
+       } else {
                I915_WRITE(FW_BLC_SELF,
                           I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
+               plane_sr = cursor_sr = 0;
+       }
 
        DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
                      planea_wm, cursora_wm,
@@ -1468,7 +1483,7 @@ static void i9xx_update_wm(struct drm_device *dev)
 
        fifo_size = dev_priv->display.get_fifo_size(dev, 0);
        crtc = intel_get_crtc_for_plane(dev, 0);
-       if (crtc->enabled && crtc->fb) {
+       if (intel_crtc_active(crtc)) {
                int cpp = crtc->fb->bits_per_pixel / 8;
                if (IS_GEN2(dev))
                        cpp = 4;
@@ -1482,7 +1497,7 @@ static void i9xx_update_wm(struct drm_device *dev)
 
        fifo_size = dev_priv->display.get_fifo_size(dev, 1);
        crtc = intel_get_crtc_for_plane(dev, 1);
-       if (crtc->enabled && crtc->fb) {
+       if (intel_crtc_active(crtc)) {
                int cpp = crtc->fb->bits_per_pixel / 8;
                if (IS_GEN2(dev))
                        cpp = 4;
@@ -1811,8 +1826,110 @@ static void sandybridge_update_wm(struct drm_device *dev)
                enabled |= 2;
        }
 
-       if ((dev_priv->num_pipe == 3) &&
-           g4x_compute_wm0(dev, 2,
+       /*
+        * Calculate and update the self-refresh watermark only when one
+        * display plane is used.
+        *
+        * SNB support 3 levels of watermark.
+        *
+        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
+        * and disabled in the descending order
+        *
+        */
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
+
+       if (!single_plane_enabled(enabled) ||
+           dev_priv->sprite_scaling_enabled)
+               return;
+       enabled = ffs(enabled) - 1;
+
+       /* WM1 */
+       if (!ironlake_compute_srwm(dev, 1, enabled,
+                                  SNB_READ_WM1_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM1_LP_ILK,
+                  WM1_LP_SR_EN |
+                  (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+                  (fbc_wm << WM1_LP_FBC_SHIFT) |
+                  (plane_wm << WM1_LP_SR_SHIFT) |
+                  cursor_wm);
+
+       /* WM2 */
+       if (!ironlake_compute_srwm(dev, 2, enabled,
+                                  SNB_READ_WM2_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM2_LP_ILK,
+                  WM2_LP_EN |
+                  (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+                  (fbc_wm << WM1_LP_FBC_SHIFT) |
+                  (plane_wm << WM1_LP_SR_SHIFT) |
+                  cursor_wm);
+
+       /* WM3 */
+       if (!ironlake_compute_srwm(dev, 3, enabled,
+                                  SNB_READ_WM3_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM3_LP_ILK,
+                  WM3_LP_EN |
+                  (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+                  (fbc_wm << WM1_LP_FBC_SHIFT) |
+                  (plane_wm << WM1_LP_SR_SHIFT) |
+                  cursor_wm);
+}
+
+static void ivybridge_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
+       u32 val;
+       int fbc_wm, plane_wm, cursor_wm;
+       int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
+       unsigned int enabled;
+
+       enabled = 0;
+       if (g4x_compute_wm0(dev, 0,
+                           &sandybridge_display_wm_info, latency,
+                           &sandybridge_cursor_wm_info, latency,
+                           &plane_wm, &cursor_wm)) {
+               val = I915_READ(WM0_PIPEA_ILK);
+               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEA_ILK, val |
+                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
+               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
+                             " plane %d, " "cursor: %d\n",
+                             plane_wm, cursor_wm);
+               enabled |= 1;
+       }
+
+       if (g4x_compute_wm0(dev, 1,
+                           &sandybridge_display_wm_info, latency,
+                           &sandybridge_cursor_wm_info, latency,
+                           &plane_wm, &cursor_wm)) {
+               val = I915_READ(WM0_PIPEB_ILK);
+               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEB_ILK, val |
+                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
+               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
+                             " plane %d, cursor: %d\n",
+                             plane_wm, cursor_wm);
+               enabled |= 2;
+       }
+
+       if (g4x_compute_wm0(dev, 2,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1875,12 +1992,17 @@ static void sandybridge_update_wm(struct drm_device *dev)
                   (plane_wm << WM1_LP_SR_SHIFT) |
                   cursor_wm);
 
-       /* WM3 */
+       /* WM3, note we have to correct the cursor latency */
        if (!ironlake_compute_srwm(dev, 3, enabled,
                                   SNB_READ_WM3_LATENCY() * 500,
                                   &sandybridge_display_srwm_info,
                                   &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
+                                  &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
+           !ironlake_compute_srwm(dev, 3, enabled,
+                                  2 * SNB_READ_WM3_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
                return;
 
        I915_WRITE(WM3_LP_ILK,
@@ -1929,7 +2051,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
        int entries, tlb_miss;
 
        crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled) {
+       if (!intel_crtc_active(crtc)) {
                *sprite_wm = display->guard_size;
                return false;
        }
@@ -3471,6 +3593,15 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                   I915_READ(ILK_DISPLAY_CHICKEN2) |
                   ILK_ELPIN_409_SELECT);
 
+       /* WaDisableHiZPlanesWhenMSAAEnabled */
+       I915_WRITE(_3D_CHICKEN,
+                  _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB));
+
+       /* WaSetupGtModeTdRowDispatch */
+       if (IS_SNB_GT1(dev))
+               I915_WRITE(GEN6_GT_MODE,
+                          _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
+
        I915_WRITE(WM3_LP_ILK, 0);
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
@@ -3999,7 +4130,7 @@ void intel_init_pm(struct drm_device *dev)
                } else if (IS_IVYBRIDGE(dev)) {
                        /* FIXME: detect B0+ stepping and use auto training */
                        if (SNB_READ_WM0_LATENCY()) {
-                               dev_priv->display.update_wm = sandybridge_update_wm;
+                               dev_priv->display.update_wm = ivybridge_update_wm;
                                dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
                        } else {
                                DRM_DEBUG_KMS("Failed to read display plane latency. "
@@ -4119,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
-       POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
 }
 
 static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
@@ -4136,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
                DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-       POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
 
        if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
                            FORCEWAKE_ACK_TIMEOUT_MS))
@@ -4173,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
 static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
-       /* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE */
+       POSTING_READ(ECOBUS);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       /* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
@@ -4220,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
+       /* something from same cacheline, but !FORCEWAKE_VLV */
+       POSTING_READ(FORCEWAKE_ACK_VLV);
 }
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
@@ -4240,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       /* The below doubles as a POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE_VLV */
+       POSTING_READ(FORCEWAKE_ACK_VLV);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
index 2346b920bd86ef96c70d7632ba13c254b21302a4..42ff97d667d2b84ad339b27ab1f59110ba5831e8 100644 (file)
@@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret = init_ring_common(ring);
 
-       if (INTEL_INFO(dev)->gen > 3) {
+       if (INTEL_INFO(dev)->gen > 3)
                I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
-               if (IS_GEN7(dev))
-                       I915_WRITE(GFX_MODE_GEN7,
-                                  _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
-                                  _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
-       }
+
+       /* We need to disable the AsyncFlip performance optimisations in order
+        * to use MI_WAIT_FOR_EVENT within the CS. It should already be
+        * programmed to '1' on all products.
+        */
+       if (INTEL_INFO(dev)->gen >= 6)
+               I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
+
+       /* Required for the hardware to program scanline values for waiting */
+       if (INTEL_INFO(dev)->gen == 6)
+               I915_WRITE(GFX_MODE,
+                          _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS));
+
+       if (IS_GEN7(dev))
+               I915_WRITE(GFX_MODE_GEN7,
+                          _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
+                          _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
 
        if (INTEL_INFO(dev)->gen >= 5) {
                ret = init_pipe_control(ring);
@@ -547,9 +559,14 @@ static int init_render_ring(struct intel_ring_buffer *ring)
 
 static void render_ring_cleanup(struct intel_ring_buffer *ring)
 {
+       struct drm_device *dev = ring->dev;
+
        if (!ring->private)
                return;
 
+       if (HAS_BROKEN_CS_TLB(dev))
+               drm_gem_object_unreference(to_gem_object(ring->private));
+
        cleanup_pipe_control(ring);
 }
 
@@ -969,6 +986,8 @@ i965_dispatch_execbuffer(struct intel_ring_buffer *ring,
        return 0;
 }
 
+/* Just userspace ABI convention to limit the wa batch bo to a resonable size */
+#define I830_BATCH_LIMIT (256*1024)
 static int
 i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
                                u32 offset, u32 len,
@@ -976,15 +995,47 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
 {
        int ret;
 
-       ret = intel_ring_begin(ring, 4);
-       if (ret)
-               return ret;
+       if (flags & I915_DISPATCH_PINNED) {
+               ret = intel_ring_begin(ring, 4);
+               if (ret)
+                       return ret;
 
-       intel_ring_emit(ring, MI_BATCH_BUFFER);
-       intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
-       intel_ring_emit(ring, offset + len - 8);
-       intel_ring_emit(ring, 0);
-       intel_ring_advance(ring);
+               intel_ring_emit(ring, MI_BATCH_BUFFER);
+               intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
+               intel_ring_emit(ring, offset + len - 8);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_advance(ring);
+       } else {
+               struct drm_i915_gem_object *obj = ring->private;
+               u32 cs_offset = obj->gtt_offset;
+
+               if (len > I830_BATCH_LIMIT)
+                       return -ENOSPC;
+
+               ret = intel_ring_begin(ring, 9+3);
+               if (ret)
+                       return ret;
+               /* Blit the batch (which has now all relocs applied) to the stable batch
+                * scratch bo area (so that the CS never stumbles over its tlb
+                * invalidation bug) ... */
+               intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD |
+                               XY_SRC_COPY_BLT_WRITE_ALPHA |
+                               XY_SRC_COPY_BLT_WRITE_RGB);
+               intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096);
+               intel_ring_emit(ring, 0);
+               intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024);
+               intel_ring_emit(ring, cs_offset);
+               intel_ring_emit(ring, 0);
+               intel_ring_emit(ring, 4096);
+               intel_ring_emit(ring, offset);
+               intel_ring_emit(ring, MI_FLUSH);
+
+               /* ... and execute it. */
+               intel_ring_emit(ring, MI_BATCH_BUFFER);
+               intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
+               intel_ring_emit(ring, cs_offset + len - 8);
+               intel_ring_advance(ring);
+       }
 
        return 0;
 }
@@ -1596,6 +1647,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
        ring->init = init_render_ring;
        ring->cleanup = render_ring_cleanup;
 
+       /* Workaround batchbuffer to combat CS tlb bug. */
+       if (HAS_BROKEN_CS_TLB(dev)) {
+               struct drm_i915_gem_object *obj;
+               int ret;
+
+               obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT);
+               if (obj == NULL) {
+                       DRM_ERROR("Failed to allocate batch bo\n");
+                       return -ENOMEM;
+               }
+
+               ret = i915_gem_object_pin(obj, 0, true, false);
+               if (ret != 0) {
+                       drm_gem_object_unreference(&obj->base);
+                       DRM_ERROR("Failed to ping batch bo\n");
+                       return ret;
+               }
+
+               ring->private = obj;
+       }
+
        return intel_init_ring_buffer(dev, ring);
 }
 
index 526182ed0c6d78b83bf35265f2d98987fab1652a..6af87cd0572501fb8621f34732627b37d89a83ac 100644 (file)
@@ -94,6 +94,7 @@ struct  intel_ring_buffer {
                                               u32 offset, u32 length,
                                               unsigned flags);
 #define I915_DISPATCH_SECURE 0x1
+#define I915_DISPATCH_PINNED 0x2
        void            (*cleanup)(struct intel_ring_buffer *ring);
        int             (*sync_to)(struct intel_ring_buffer *ring,
                                   struct intel_ring_buffer *to,
index 827dcd4edf1c31eff9018c7c9bec37139e93602f..d7b060e0a23199b064c21d30366dd5ff78566e13 100644 (file)
@@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
        I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 
-       linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+       linear_offset = y * fb->pitches[0] + x * pixel_size;
        sprsurf_offset =
                intel_gen4_compute_offset_xtiled(&x, &y,
-                                                fb->bits_per_pixel / 8,
-                                                fb->pitches[0]);
+                                                pixel_size, fb->pitches[0]);
        linear_offset -= sprsurf_offset;
 
        /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
@@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
        I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 
-       linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+       linear_offset = y * fb->pitches[0] + x * pixel_size;
        dvssurf_offset =
                intel_gen4_compute_offset_xtiled(&x, &y,
-                                                fb->bits_per_pixel / 8,
-                                                fb->pitches[0]);
+                                                pixel_size, fb->pitches[0]);
        linear_offset -= dvssurf_offset;
 
        if (obj->tiling_mode != I915_TILING_NONE)
index 1e910117b0a2e808da6d1529656a7fdfa93166de..122b571ccc7ce7a940f267ab002821952a535c08 100644 (file)
@@ -60,8 +60,7 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev)
 }
 
 
-static int __devinit
-mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        mgag200_kick_out_firmware_fb(pdev);
 
index c617f0480071ae4c07e9d524513149cfb1ac0452..8bbb58f94a193da85a769a5a387bc57b51ef5530 100644 (file)
@@ -66,10 +66,8 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg,
 
        ret = nouveau_handle_create(nv_object(client), ~0, ~0,
                                    nv_object(client), &client->root);
-       if (ret) {
-               nouveau_namedb_destroy(&client->base);
+       if (ret)
                return ret;
-       }
 
        /* prevent init/fini being called, os in in charge of this */
        atomic_set(&nv_object(client)->usecount, 2);
index 6b0843c338775d6455322a099f568a4390d8db64..e05c15777588616f69b753e915c7c8bcb59a922f 100644 (file)
@@ -73,8 +73,11 @@ _nouveau_falcon_init(struct nouveau_object *object)
        nv_debug(falcon, "data limit: %d\n", falcon->data.limit);
 
        /* wait for 'uc halted' to be signalled before continuing */
-       if (falcon->secret) {
-               nv_wait(falcon, 0x008, 0x00000010, 0x00000010);
+       if (falcon->secret && falcon->version < 4) {
+               if (!falcon->version)
+                       nv_wait(falcon, 0x008, 0x00000010, 0x00000010);
+               else
+                       nv_wait(falcon, 0x180, 0x80000000, 0);
                nv_wo32(falcon, 0x004, 0x00000010);
        }
 
index b8d2cbf8a7a7bb9b0f5a2c8fabfb65de9e93142a..264c2b338ac3a23fc82e1f6594d58dffcf8547d8 100644 (file)
@@ -109,7 +109,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle,
        while (!nv_iclass(namedb, NV_NAMEDB_CLASS))
                namedb = namedb->parent;
 
-       handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL);
+       handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle)
                return -ENOMEM;
 
@@ -146,6 +146,9 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle,
        }
 
        hprintk(handle, TRACE, "created\n");
+
+       *phandle = handle;
+
        return 0;
 }
 
index f74c30aa33a0e334eda733ae1a0ea5b9a3d10377..48f06378d3f9d5f9e09e03291a11d6e26527f674 100644 (file)
@@ -99,7 +99,7 @@ nouveau_subdev_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       mutex_init(&subdev->mutex);
+       __mutex_init(&subdev->mutex, subname, &oclass->lock_class_key);
        subdev->name = subname;
 
        if (parent) {
index 0f09af135415582ec7428d14af33351197d8f8e3..ca1a7d76a95b50d87864e95954b20aebd7906f76 100644 (file)
@@ -851,20 +851,23 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
        for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
                ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
 
-       if (nv_device(priv)->chipset  < 0x90 ||
-           nv_device(priv)->chipset == 0x92 ||
-           nv_device(priv)->chipset == 0xa0) {
-               for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
-                       ctrl = nv_rd32(priv, 0x610b74 + (i * 8));
-               i += 3;
-       } else {
-               for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
-                       ctrl = nv_rd32(priv, 0x610798 + (i * 8));
-               i += 3;
+       if (!(ctrl & (1 << head))) {
+               if (nv_device(priv)->chipset  < 0x90 ||
+                   nv_device(priv)->chipset == 0x92 ||
+                   nv_device(priv)->chipset == 0xa0) {
+                       for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
+                               ctrl = nv_rd32(priv, 0x610b74 + (i * 8));
+                       i += 4;
+               } else {
+                       for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
+                               ctrl = nv_rd32(priv, 0x610798 + (i * 8));
+                       i += 4;
+               }
        }
 
        if (!(ctrl & (1 << head)))
                return false;
+       i--;
 
        data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
        if (data) {
@@ -898,20 +901,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
        for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
                ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
 
-       if (nv_device(priv)->chipset  < 0x90 ||
-           nv_device(priv)->chipset == 0x92 ||
-           nv_device(priv)->chipset == 0xa0) {
-               for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
-                       ctrl = nv_rd32(priv, 0x610b70 + (i * 8));
-               i += 3;
-       } else {
-               for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
-                       ctrl = nv_rd32(priv, 0x610794 + (i * 8));
-               i += 3;
+       if (!(ctrl & (1 << head))) {
+               if (nv_device(priv)->chipset  < 0x90 ||
+                   nv_device(priv)->chipset == 0x92 ||
+                   nv_device(priv)->chipset == 0xa0) {
+                       for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
+                               ctrl = nv_rd32(priv, 0x610b70 + (i * 8));
+                       i += 4;
+               } else {
+                       for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
+                               ctrl = nv_rd32(priv, 0x610794 + (i * 8));
+                       i += 4;
+               }
        }
 
        if (!(ctrl & (1 << head)))
                return 0x0000;
+       i--;
 
        data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1);
        if (!data)
index 7b715fda276356849647c50793da6db4ede26937..62ab231cd6b65cd52449f1bdba2338e391e7ba82 100644 (file)
@@ -57,6 +57,11 @@ chipsets:
 .b16 #nve4_gpc_mmio_tail
 .b16 #nve4_tpc_mmio_head
 .b16 #nve4_tpc_mmio_tail
+.b8  0xe6 0 0 0
+.b16 #nve4_gpc_mmio_head
+.b16 #nve4_gpc_mmio_tail
+.b16 #nve4_tpc_mmio_head
+.b16 #nve4_tpc_mmio_tail
 .b8  0 0 0 0
 
 // GPC mmio lists
index 26c2165bad0fc75b6ab5667be24ce2bdb2bba9c1..09ee4702c8b29ff587be71e6908040ab9d35d98d 100644 (file)
@@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = {
        0x00000000,
 /* 0x0064: chipsets */
        0x000000e4,
-       0x01040080,
-       0x014c0104,
+       0x0110008c,
+       0x01580110,
        0x000000e7,
-       0x01040080,
-       0x014c0104,
+       0x0110008c,
+       0x01580110,
+       0x000000e6,
+       0x0110008c,
+       0x01580110,
        0x00000000,
-/* 0x0080: nve4_gpc_mmio_head */
+/* 0x008c: nve4_gpc_mmio_head */
        0x00000380,
        0x04000400,
        0x0800040c,
@@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = {
        0x14003100,
        0x000031d0,
        0x040031e0,
-/* 0x0104: nve4_gpc_mmio_tail */
-/* 0x0104: nve4_tpc_mmio_head */
+/* 0x0110: nve4_gpc_mmio_tail */
+/* 0x0110: nve4_tpc_mmio_head */
        0x00000048,
        0x00000064,
        0x00000088,
index acfc457654bdcffb0bc15ac22e36c1c4c4fa7e9c..0bcfa4d447e569f5506a40a30988b6e81903b04c 100644 (file)
@@ -754,6 +754,16 @@ ctx_mmio_exec:
 //             on load it means: "a save preceeded this load"
 //
 ctx_xfer:
+       // according to mwk, some kind of wait for idle
+       mov $r15 0xc00
+       shl b32 $r15 6
+       mov $r14 4
+       iowr I[$r15 + 0x200] $r14
+       ctx_xfer_idle:
+               iord $r14 I[$r15 + 0x000]
+               and $r14 0x2000
+               bra ne #ctx_xfer_idle
+
        bra not $p1 #ctx_xfer_pre
        bra $p2 #ctx_xfer_pre_load
        ctx_xfer_pre:
index 85a8d556f484d3984ec9350ed7c1f1980c7d315c..bb03d2a1d57b51a8469447c562a08448ccf499ef 100644 (file)
@@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = {
        0x01fa0613,
        0xf803f806,
 /* 0x0829: ctx_xfer */
-       0x0611f400,
-/* 0x082f: ctx_xfer_pre */
-       0xf01102f4,
-       0x21f510f7,
-       0x21f50698,
-       0x11f40631,
-/* 0x083d: ctx_xfer_pre_load */
-       0x02f7f01c,
-       0x065721f5,
-       0x066621f5,
-       0x067821f5,
-       0x21f5f4bd,
-       0x21f50657,
-/* 0x0856: ctx_xfer_exec */
-       0x019806b8,
-       0x1427f116,
-       0x0624b604,
-       0xf10020d0,
-       0xf0a500e7,
-       0x1fb941e3,
-       0x8d21f402,
-       0xf004e0b6,
-       0x2cf001fc,
-       0x0124b602,
-       0xf405f2fd,
-       0x17f18d21,
-       0x13f04afc,
-       0x0c27f002,
-       0xf50012d0,
-       0xf1020721,
-       0xf047fc27,
-       0x20d00223,
-       0x012cf000,
-       0xd00320b6,
-       0xacf00012,
-       0x06a5f001,
-       0x9800b7f0,
-       0x0d98140c,
-       0x00e7f015,
-       0x015c21f5,
-       0xf508a7f0,
-       0xf5010321,
-       0xf4020721,
-       0xa7f02201,
-       0xc921f40c,
-       0x0a1017f1,
-       0xf00614b6,
-       0x12d00527,
-/* 0x08dd: ctx_xfer_post_save_wait */
-       0x0012cf00,
-       0xf40522fd,
-       0x02f4fa1b,
-/* 0x08e9: ctx_xfer_post */
-       0x02f7f032,
-       0x065721f5,
-       0x21f5f4bd,
-       0x21f50698,
-       0x21f50226,
-       0xf4bd0666,
-       0x065721f5,
-       0x981011f4,
-       0x11fd8001,
-       0x070bf405,
-       0x07df21f5,
-/* 0x0914: ctx_xfer_no_post_mmio */
-       0x064921f5,
-/* 0x0918: ctx_xfer_done */
-       0x000000f8,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x00f7f100,
+       0x06f4b60c,
+       0xd004e7f0,
+/* 0x0836: ctx_xfer_idle */
+       0xfecf80fe,
+       0x00e4f100,
+       0xf91bf420,
+       0xf40611f4,
+/* 0x0846: ctx_xfer_pre */
+       0xf7f01102,
+       0x9821f510,
+       0x3121f506,
+       0x1c11f406,
+/* 0x0854: ctx_xfer_pre_load */
+       0xf502f7f0,
+       0xf5065721,
+       0xf5066621,
+       0xbd067821,
+       0x5721f5f4,
+       0xb821f506,
+/* 0x086d: ctx_xfer_exec */
+       0x16019806,
+       0x041427f1,
+       0xd00624b6,
+       0xe7f10020,
+       0xe3f0a500,
+       0x021fb941,
+       0xb68d21f4,
+       0xfcf004e0,
+       0x022cf001,
+       0xfd0124b6,
+       0x21f405f2,
+       0xfc17f18d,
+       0x0213f04a,
+       0xd00c27f0,
+       0x21f50012,
+       0x27f10207,
+       0x23f047fc,
+       0x0020d002,
+       0xb6012cf0,
+       0x12d00320,
+       0x01acf000,
+       0xf006a5f0,
+       0x0c9800b7,
+       0x150d9814,
+       0xf500e7f0,
+       0xf0015c21,
+       0x21f508a7,
+       0x21f50103,
+       0x01f40207,
+       0x0ca7f022,
+       0xf1c921f4,
+       0xb60a1017,
+       0x27f00614,
+       0x0012d005,
+/* 0x08f4: ctx_xfer_post_save_wait */
+       0xfd0012cf,
+       0x1bf40522,
+       0x3202f4fa,
+/* 0x0900: ctx_xfer_post */
+       0xf502f7f0,
+       0xbd065721,
+       0x9821f5f4,
+       0x2621f506,
+       0x6621f502,
+       0xf5f4bd06,
+       0xf4065721,
+       0x01981011,
+       0x0511fd80,
+       0xf5070bf4,
+/* 0x092b: ctx_xfer_no_post_mmio */
+       0xf507df21,
+/* 0x092f: ctx_xfer_done */
+       0xf8064921,
        0x00000000,
        0x00000000,
        0x00000000,
index 138eeaa286650998797b11eba246d6d2e72ecc0c..7fe9d7cf486b8ff81a879b7339f703e5b88a3c33 100644 (file)
@@ -44,6 +44,9 @@ chipsets:
 .b8  0xe7 0 0 0
 .b16 #nve4_hub_mmio_head
 .b16 #nve4_hub_mmio_tail
+.b8  0xe6 0 0 0
+.b16 #nve4_hub_mmio_head
+.b16 #nve4_hub_mmio_tail
 .b8  0 0 0 0
 
 nve4_hub_mmio_head:
@@ -680,6 +683,16 @@ ctx_mmio_exec:
 //             on load it means: "a save preceeded this load"
 //
 ctx_xfer:
+       // according to mwk, some kind of wait for idle
+       mov $r15 0xc00
+       shl b32 $r15 6
+       mov $r14 4
+       iowr I[$r15 + 0x200] $r14
+       ctx_xfer_idle:
+               iord $r14 I[$r15 + 0x000]
+               and $r14 0x2000
+               bra ne #ctx_xfer_idle
+
        bra not $p1 #ctx_xfer_pre
        bra $p2 #ctx_xfer_pre_load
        ctx_xfer_pre:
index decf0c60ca3bf079d5f0ad2e3a94a887737a026d..e3421af68ab9504467e1e976eeefdb08b16288e0 100644 (file)
@@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = {
        0x00000000,
 /* 0x005c: chipsets */
        0x000000e4,
-       0x013c0070,
+       0x01440078,
        0x000000e7,
-       0x013c0070,
+       0x01440078,
+       0x000000e6,
+       0x01440078,
        0x00000000,
-/* 0x0070: nve4_hub_mmio_head */
+/* 0x0078: nve4_hub_mmio_head */
        0x0417e91c,
        0x04400204,
        0x18404010,
@@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = {
        0x00408840,
        0x08408900,
        0x00408980,
-/* 0x013c: nve4_hub_mmio_tail */
-       0x00000000,
-       0x00000000,
+/* 0x0144: nve4_hub_mmio_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = {
        0x0613f002,
        0xf80601fa,
 /* 0x07fb: ctx_xfer */
-       0xf400f803,
-       0x02f40611,
-/* 0x0801: ctx_xfer_pre */
-       0x10f7f00d,
-       0x067221f5,
-/* 0x080b: ctx_xfer_pre_load */
-       0xf01c11f4,
-       0x21f502f7,
-       0x21f50631,
-       0x21f50640,
-       0xf4bd0652,
-       0x063121f5,
-       0x069221f5,
-/* 0x0824: ctx_xfer_exec */
-       0xf1160198,
-       0xb6041427,
-       0x20d00624,
-       0x00e7f100,
-       0x41e3f0a5,
-       0xf4021fb9,
-       0xe0b68d21,
-       0x01fcf004,
-       0xb6022cf0,
-       0xf2fd0124,
-       0x8d21f405,
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x0721f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f006a5,
-       0x140c9800,
-       0xf0150d98,
-       0x21f500e7,
-       0xa7f0015c,
-       0x0321f508,
-       0x0721f501,
-       0x2201f402,
-       0xf40ca7f0,
-       0x17f1c921,
-       0x14b60a10,
-       0x0527f006,
-/* 0x08ab: ctx_xfer_post_save_wait */
-       0xcf0012d0,
-       0x22fd0012,
-       0xfa1bf405,
-/* 0x08b7: ctx_xfer_post */
-       0xf02e02f4,
-       0x21f502f7,
-       0xf4bd0631,
-       0x067221f5,
-       0x022621f5,
-       0x064021f5,
-       0x21f5f4bd,
-       0x11f40631,
-       0x80019810,
-       0xf40511fd,
-       0x21f5070b,
-/* 0x08e2: ctx_xfer_no_post_mmio */
-/* 0x08e2: ctx_xfer_done */
-       0x00f807b1,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0xf100f803,
+       0xb60c00f7,
+       0xe7f006f4,
+       0x80fed004,
+/* 0x0808: ctx_xfer_idle */
+       0xf100fecf,
+       0xf42000e4,
+       0x11f4f91b,
+       0x0d02f406,
+/* 0x0818: ctx_xfer_pre */
+       0xf510f7f0,
+       0xf4067221,
+/* 0x0822: ctx_xfer_pre_load */
+       0xf7f01c11,
+       0x3121f502,
+       0x4021f506,
+       0x5221f506,
+       0xf5f4bd06,
+       0xf5063121,
+/* 0x083b: ctx_xfer_exec */
+       0x98069221,
+       0x27f11601,
+       0x24b60414,
+       0x0020d006,
+       0xa500e7f1,
+       0xb941e3f0,
+       0x21f4021f,
+       0x04e0b68d,
+       0xf001fcf0,
+       0x24b6022c,
+       0x05f2fd01,
+       0xf18d21f4,
+       0xf04afc17,
+       0x27f00213,
+       0x0012d00c,
+       0x020721f5,
+       0x47fc27f1,
+       0xd00223f0,
+       0x2cf00020,
+       0x0320b601,
+       0xf00012d0,
+       0xa5f001ac,
+       0x00b7f006,
+       0x98140c98,
+       0xe7f0150d,
+       0x5c21f500,
+       0x08a7f001,
+       0x010321f5,
+       0x020721f5,
+       0xf02201f4,
+       0x21f40ca7,
+       0x1017f1c9,
+       0x0614b60a,
+       0xd00527f0,
+/* 0x08c2: ctx_xfer_post_save_wait */
+       0x12cf0012,
+       0x0522fd00,
+       0xf4fa1bf4,
+/* 0x08ce: ctx_xfer_post */
+       0xf7f02e02,
+       0x3121f502,
+       0xf5f4bd06,
+       0xf5067221,
+       0xf5022621,
+       0xbd064021,
+       0x3121f5f4,
+       0x1011f406,
+       0xfd800198,
+       0x0bf40511,
+       0xb121f507,
+/* 0x08f9: ctx_xfer_no_post_mmio */
+/* 0x08f9: ctx_xfer_done */
+       0x0000f807,
        0x00000000,
 };
index 47a02081d70836efe11d77e54839fcd483c04e31..45aff5f5085aa83d8837309cb8117f620950d0bd 100644 (file)
@@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
        struct nouveau_device *device = nv_device(parent);
        struct nvc0_graph_priv *priv;
-       bool enable = true;
        int ret, i;
 
-       switch (device->chipset) {
-       case 0xd9: /* known broken without binary driver firmware */
-               enable = false;
-               break;
-       default:
-               break;
-       }
-
-       ret = nouveau_graph_create(parent, engine, oclass, enable, &priv);
+       ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 18d2210e12eb2acab56cf35fc3b06c8ca705f804..a1e78de46456b446e0a0261bf92e3f474c949ad6 100644 (file)
@@ -121,6 +121,7 @@ nvc0_graph_class(void *obj)
                return 0x9297;
        case 0xe4:
        case 0xe7:
+       case 0xe6:
                return 0xa097;
        default:
                return 0;
index 539d4c72f192eb6bda3ff3385c4895854b8d95a8..9f82e9702b4661208cf1f021ee246fcb721a986e 100644 (file)
@@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_graph_priv *priv;
        int ret, i;
 
-       ret = nouveau_graph_create(parent, engine, oclass, false, &priv);
+       ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
@@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        priv->magic_not_rop_nr = 1;
                break;
        case 0xe7:
+       case 0xe6:
                priv->magic_not_rop_nr = 1;
                break;
        default:
index 0193532ceac97c71cdfc544039eb530ce1806963..63acc0346ff2c437cda76e06df68c709d51bc46e 100644 (file)
@@ -36,6 +36,9 @@ nouveau_client(void *obj)
 
 int  nouveau_client_create_(const char *name, u64 device, const char *cfg,
                            const char *dbg, int, void **);
+#define nouveau_client_destroy(p)                                              \
+       nouveau_namedb_destroy(&(p)->base)
+
 int  nouveau_client_init(struct nouveau_client *);
 int  nouveau_client_fini(struct nouveau_client *, bool suspend);
 
index 5982935ee23a96896fb12d98e2dc5f723ab245e0..106bb19fdd9a65ee12b0c92241ea5045a4b692ac 100644 (file)
@@ -50,10 +50,13 @@ int  nouveau_object_fini(struct nouveau_object *, bool suspend);
 
 extern struct nouveau_ofuncs nouveau_object_ofuncs;
 
+/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
+ * ".data". */
 struct nouveau_oclass {
        u32 handle;
-       struct nouveau_ofuncs *ofuncs;
-       struct nouveau_omthds *omthds;
+       struct nouveau_ofuncs * const ofuncs;
+       struct nouveau_omthds * const omthds;
+       struct lock_class_key lock_class_key;
 };
 
 #define nv_oclass(o)    nv_object(o)->oclass
index d145b25e6be40f483ddd23fbaf4c69d4208d9365..5bd1ca8cd20dbe03bee67fa3e0fddd4faf1410cb 100644 (file)
@@ -17,6 +17,7 @@ struct nouveau_bios {
                u8 chip;
                u8 minor;
                u8 micro;
+               u8 patch;
        } version;
 };
 
index 2bf178082a36dd5a9fa866b20d278b595ea674bb..e6563b5cb08edb7c48ac4811627fa6007fe7b3d4 100644 (file)
@@ -25,9 +25,11 @@ struct dcb_gpio_func {
        u8 param;
 };
 
-u16 dcb_gpio_table(struct nouveau_bios *);
-u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver);
-int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line,
+u16 dcb_gpio_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len);
+u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len,
                   struct dcb_gpio_func *);
+u16 dcb_gpio_match(struct nouveau_bios *, int idx, u8 func, u8 line,
+                  u8 *ver, u8 *len, struct dcb_gpio_func *);
 
 #endif
index e69a8bdc6e97371072476b28c682a9d8f0427612..ca2f6bf37f46228d5e0b4f496c4ad78110adaf2d 100644 (file)
@@ -13,6 +13,7 @@ struct nvbios_init {
        u32 nested;
        u16 repeat;
        u16 repend;
+       u32 ramcfg;
 };
 
 int nvbios_exec(struct nvbios_init *);
index c345097592f20bcf191f1d71db11beddfb044053..b2f3d4d0aa49fab5883234af8be8e3c44fa6c9ee 100644 (file)
@@ -38,6 +38,8 @@ enum nvbios_pll_type {
        PLL_UNK42  = 0x42,
        PLL_VPLL0  = 0x80,
        PLL_VPLL1  = 0x81,
+       PLL_VPLL2  = 0x82,
+       PLL_VPLL3  = 0x83,
        PLL_MAX    = 0xff
 };
 
index 9ea2b12cc15d02707eec26b72ad05ad719cc3731..b75e8f18e52c8432a2506e4eb9924f31afc56989 100644 (file)
@@ -11,7 +11,7 @@ struct nouveau_gpio {
        struct nouveau_subdev base;
 
        /* hardware interfaces */
-       void (*reset)(struct nouveau_gpio *);
+       void (*reset)(struct nouveau_gpio *, u8 func);
        int  (*drive)(struct nouveau_gpio *, int line, int dir, int out);
        int  (*sense)(struct nouveau_gpio *, int line);
        void (*irq_enable)(struct nouveau_gpio *, int line, bool);
index dd111947eb8654a022bae8b65f787075c0d318ad..f621f69fa1a245a1f5d633b493d7542b71c21d38 100644 (file)
@@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent,
                bios->version.chip  = nv_ro08(bios, bit_i.offset + 2);
                bios->version.minor = nv_ro08(bios, bit_i.offset + 1);
                bios->version.micro = nv_ro08(bios, bit_i.offset + 0);
+               bios->version.patch = nv_ro08(bios, bit_i.offset + 4);
        } else
        if (bmp_version(bios)) {
                bios->version.major = nv_ro08(bios, bios->bmp_offset + 13);
@@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent,
                bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10);
        }
 
-       nv_info(bios, "version %02x.%02x.%02x.%02x\n",
+       nv_info(bios, "version %02x.%02x.%02x.%02x.%02x\n",
                bios->version.major, bios->version.chip,
-               bios->version.minor, bios->version.micro);
+               bios->version.minor, bios->version.micro, bios->version.patch);
 
        return 0;
 }
index c90d4aa3ae4f6334ffa6f73cd51c76ebd4246925..c84e93fa6d9550cf258a23096967a8b6846f440f 100644 (file)
 #include <subdev/bios/gpio.h>
 
 u16
-dcb_gpio_table(struct nouveau_bios *bios)
+dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
-       u8  ver, hdr, cnt, len;
-       u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len);
+       u16 data = 0x0000;
+       u16 dcb = dcb_table(bios, ver, hdr, cnt, len);
        if (dcb) {
-               if (ver >= 0x30 && hdr >= 0x0c)
-                       return nv_ro16(bios, dcb + 0x0a);
-               if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13)
-                       return nv_ro16(bios, dcb - 0x0f);
+               if (*ver >= 0x30 && *hdr >= 0x0c)
+                       data = nv_ro16(bios, dcb + 0x0a);
+               else
+               if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13)
+                       data = nv_ro16(bios, dcb - 0x0f);
+
+               if (data) {
+                       *ver = nv_ro08(bios, data + 0x00);
+                       if (*ver < 0x30) {
+                               *hdr = 3;
+                               *cnt = nv_ro08(bios, data + 0x02);
+                               *len = nv_ro08(bios, data + 0x01);
+                       } else
+                       if (*ver <= 0x41) {
+                               *hdr = nv_ro08(bios, data + 0x01);
+                               *cnt = nv_ro08(bios, data + 0x02);
+                               *len = nv_ro08(bios, data + 0x03);
+                       } else {
+                               data = 0x0000;
+                       }
+               }
        }
-       return 0x0000;
+       return data;
 }
 
 u16
-dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver)
+dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len)
 {
-       u16 gpio = dcb_gpio_table(bios);
-       if (gpio) {
-               *ver = nv_ro08(bios, gpio);
-               if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2))
-                       return gpio + 3 + (ent * nv_ro08(bios, gpio + 1));
-               else if (ent < nv_ro08(bios, gpio + 2))
-                       return gpio + nv_ro08(bios, gpio + 1) +
-                              (ent * nv_ro08(bios, gpio + 3));
-       }
+       u8  hdr, cnt;
+       u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000;
+       if (gpio && ent < cnt)
+               return gpio + hdr + (ent * *len);
        return 0x0000;
 }
 
-int
-dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line,
+u16
+dcb_gpio_parse(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len,
               struct dcb_gpio_func *gpio)
 {
-       u8  ver, hdr, cnt, len;
-       u16 entry;
-       int i = -1;
-
-       while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) {
-               if (ver < 0x40) {
-                       u16 data = nv_ro16(bios, entry);
+       u16 data = dcb_gpio_entry(bios, idx, ent, ver, len);
+       if (data) {
+               if (*ver < 0x40) {
+                       u16 info = nv_ro16(bios, data);
                        *gpio = (struct dcb_gpio_func) {
-                               .line = (data & 0x001f) >> 0,
-                               .func = (data & 0x07e0) >> 5,
-                               .log[0] = (data & 0x1800) >> 11,
-                               .log[1] = (data & 0x6000) >> 13,
-                               .param = !!(data & 0x8000),
+                               .line = (info & 0x001f) >> 0,
+                               .func = (info & 0x07e0) >> 5,
+                               .log[0] = (info & 0x1800) >> 11,
+                               .log[1] = (info & 0x6000) >> 13,
+                               .param = !!(info & 0x8000),
                        };
                } else
-               if (ver < 0x41) {
-                       u32 data = nv_ro32(bios, entry);
+               if (*ver < 0x41) {
+                       u32 info = nv_ro32(bios, data);
                        *gpio = (struct dcb_gpio_func) {
-                               .line = (data & 0x0000001f) >> 0,
-                               .func = (data & 0x0000ff00) >> 8,
-                               .log[0] = (data & 0x18000000) >> 27,
-                               .log[1] = (data & 0x60000000) >> 29,
-                               .param = !!(data & 0x80000000),
+                               .line = (info & 0x0000001f) >> 0,
+                               .func = (info & 0x0000ff00) >> 8,
+                               .log[0] = (info & 0x18000000) >> 27,
+                               .log[1] = (info & 0x60000000) >> 29,
+                               .param = !!(info & 0x80000000),
                        };
                } else {
-                       u32 data = nv_ro32(bios, entry + 0);
-                       u8 data1 = nv_ro32(bios, entry + 4);
+                       u32 info = nv_ro32(bios, data + 0);
+                       u8 info1 = nv_ro32(bios, data + 4);
                        *gpio = (struct dcb_gpio_func) {
-                               .line = (data & 0x0000003f) >> 0,
-                               .func = (data & 0x0000ff00) >> 8,
-                               .log[0] = (data1 & 0x30) >> 4,
-                               .log[1] = (data1 & 0xc0) >> 6,
-                               .param = !!(data & 0x80000000),
+                               .line = (info & 0x0000003f) >> 0,
+                               .func = (info & 0x0000ff00) >> 8,
+                               .log[0] = (info1 & 0x30) >> 4,
+                               .log[1] = (info1 & 0xc0) >> 6,
+                               .param = !!(info & 0x80000000),
                        };
                }
+       }
+
+       return data;
+}
 
+u16
+dcb_gpio_match(struct nouveau_bios *bios, int idx, u8 func, u8 line,
+              u8 *ver, u8 *len, struct dcb_gpio_func *gpio)
+{
+       u8  hdr, cnt, i = 0;
+       u16 data;
+
+       while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) {
                if ((line == 0xff || line == gpio->line) &&
                    (func == 0xff || func == gpio->func))
-                       return 0;
+                       return data;
        }
 
        /* DCB 2.2, fixed TVDAC GPIO data */
-       if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) {
-               if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) {
-                       u8 conf = nv_ro08(bios, entry - 5);
-                       u8 addr = nv_ro08(bios, entry - 4);
+       if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) {
+               if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) {
+                       u8 conf = nv_ro08(bios, data - 5);
+                       u8 addr = nv_ro08(bios, data - 4);
                        if (conf & 0x01) {
                                *gpio = (struct dcb_gpio_func) {
                                        .func = DCB_GPIO_TVDAC0,
@@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line,
                                        .log[0] = !!(conf & 0x02),
                                        .log[1] =  !(conf & 0x02),
                                };
-                               return 0;
+                               *ver = 0x00;
+                               return data;
                        }
                }
        }
 
-       return -EINVAL;
+       return 0x0000;
 }
index ae168bbb86d851a0bd1a81a532106281bae91a83..690ed438b2adbcf6c3263d5962e84054a62fef5d 100644 (file)
@@ -2,11 +2,12 @@
 #include <core/device.h>
 
 #include <subdev/bios.h>
-#include <subdev/bios/conn.h>
 #include <subdev/bios/bmp.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/conn.h>
 #include <subdev/bios/dcb.h>
 #include <subdev/bios/dp.h>
+#include <subdev/bios/gpio.h>
 #include <subdev/bios/init.h>
 #include <subdev/devinit.h>
 #include <subdev/clock.h>
@@ -409,10 +410,26 @@ init_ram_restrict_group_count(struct nvbios_init *init)
        return 0x00;
 }
 
+static u8
+init_ram_restrict_strap(struct nvbios_init *init)
+{
+       /* This appears to be the behaviour of the VBIOS parser, and *is*
+        * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
+        * avoid fucking up the memory controller (somehow) by reading it
+        * on every INIT_RAM_RESTRICT_ZM_GROUP opcode.
+        *
+        * Preserving the non-caching behaviour on earlier chipsets just
+        * in case *not* re-reading the strap causes similar breakage.
+        */
+       if (!init->ramcfg || init->bios->version.major < 0x70)
+               init->ramcfg = init_rd32(init, 0x101000);
+       return (init->ramcfg & 0x00000003c) >> 2;
+}
+
 static u8
 init_ram_restrict(struct nvbios_init *init)
 {
-       u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2;
+       u8  strap = init_ram_restrict_strap(init);
        u16 table = init_ram_restrict_table(init);
        if (table)
                return nv_ro08(init->bios, table + strap);
@@ -1517,7 +1534,6 @@ init_io(struct nvbios_init *init)
                mdelay(10);
                init_wr32(init, 0x614100, 0x10000018);
                init_wr32(init, 0x614900, 0x10000018);
-               return;
        }
 
        value = init_rdport(init, port) & mask;
@@ -1781,7 +1797,7 @@ init_gpio(struct nvbios_init *init)
        init->offset += 1;
 
        if (init_exec(init) && gpio && gpio->reset)
-               gpio->reset(gpio);
+               gpio->reset(gpio, DCB_GPIO_UNUSED);
 }
 
 /**
@@ -1995,6 +2011,47 @@ init_i2c_long_if(struct nvbios_init *init)
        init_exec_set(init, false);
 }
 
+/**
+ * INIT_GPIO_NE - opcode 0xa9
+ *
+ */
+static void
+init_gpio_ne(struct nvbios_init *init)
+{
+       struct nouveau_bios *bios = init->bios;
+       struct nouveau_gpio *gpio = nouveau_gpio(bios);
+       struct dcb_gpio_func func;
+       u8 count = nv_ro08(bios, init->offset + 1);
+       u8 idx = 0, ver, len;
+       u16 data, i;
+
+       trace("GPIO_NE\t");
+       init->offset += 2;
+
+       for (i = init->offset; i < init->offset + count; i++)
+               cont("0x%02x ", nv_ro08(bios, i));
+       cont("\n");
+
+       while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) {
+               if (func.func != DCB_GPIO_UNUSED) {
+                       for (i = init->offset; i < init->offset + count; i++) {
+                               if (func.func == nv_ro08(bios, i))
+                                       break;
+                       }
+
+                       trace("\tFUNC[0x%02x]", func.func);
+                       if (i == (init->offset + count)) {
+                               cont(" *");
+                               if (init_exec(init) && gpio && gpio->reset)
+                                       gpio->reset(gpio, func.func);
+                       }
+                       cont("\n");
+               }
+       }
+
+       init->offset += count;
+}
+
 static struct nvbios_init_opcode {
        void (*exec)(struct nvbios_init *);
 } init_opcode[] = {
@@ -2059,6 +2116,7 @@ static struct nvbios_init_opcode {
        [0x98] = { init_auxch },
        [0x99] = { init_zm_auxch },
        [0x9a] = { init_i2c_long_if },
+       [0xa9] = { init_gpio_ne },
 };
 
 #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))
index f6962c9b6c36b6f00db2715287dedf1c3adb9f4e..7c9626258a467029cf3bc7b63b37429dfa0e4fa8 100644 (file)
@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
        switch (info.type) {
        case PLL_VPLL0:
        case PLL_VPLL1:
+       case PLL_VPLL2:
+       case PLL_VPLL3:
                nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100);
                nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M);
                nv_wr32(priv, info.reg + 0x10, fN << 16);
index 9b7881e76634c934335545e76f250c314d0758db..03a652876e731d4e1428b984adb8825223bad053 100644 (file)
@@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                break;
+       case 0xe6:
+               device->cname = "GK106";
+               device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
+               device->oclass[NVDEV_SUBDEV_GPIO   ] = &nvd0_gpio_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nouveau_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
+               device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
+               device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] = &nve0_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] = &nve0_graph_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
+               device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
+               device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
+               device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
+               device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
+               break;
        default:
                nv_fatal(device, "unknown Kepler chipset\n");
                return -EINVAL;
index d6d16007ec1ac08e0e88ca35e8c4e8d20ae4e2f9..d62045f454b265df1c07ebcc9cd77207482b7dea 100644 (file)
@@ -86,8 +86,8 @@ nouveau_fb_preinit(struct nouveau_fb *pfb)
                        return ret;
        }
 
-       if (!nouveau_mm_initialised(&pfb->tags) && tags) {
-               ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1);
+       if (!nouveau_mm_initialised(&pfb->tags)) {
+               ret = nouveau_mm_init(&pfb->tags, 0, tags ? ++tags : 0, 1);
                if (ret)
                        return ret;
        }
index 487cb8c6c204dda270d1957e869b42beae4fdccd..eac236ed19b251042ea3bfe1ef75d6da6856d188 100644 (file)
@@ -99,7 +99,7 @@ nv50_fb_vram_init(struct nouveau_fb *pfb)
        struct nouveau_bios *bios = nouveau_bios(device);
        const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
        const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
-       u32 size;
+       u32 size, tags = 0;
        int ret;
 
        pfb->ram.size = nv_rd32(pfb, 0x10020c);
@@ -140,10 +140,11 @@ nv50_fb_vram_init(struct nouveau_fb *pfb)
                        return ret;
 
                pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
+               tags = nv_rd32(pfb, 0x100320);
                break;
        }
 
-       return nv_rd32(pfb, 0x100320);
+       return tags;
 }
 
 static int
index 306bdf121452e6e9da8d6ddeb7ba6210ddeb0bde..7606ed15b6faf55ea531e6637cc86976b24012c2 100644 (file)
@@ -145,14 +145,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
        mem->memtype = type;
        mem->size = size;
 
-       mutex_lock(&mm->mutex);
+       mutex_lock(&pfb->base.mutex);
        do {
                if (back)
                        ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r);
                else
                        ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r);
                if (ret) {
-                       mutex_unlock(&mm->mutex);
+                       mutex_unlock(&pfb->base.mutex);
                        pfb->ram.put(pfb, &mem);
                        return ret;
                }
@@ -160,7 +160,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
                list_add_tail(&r->rl_entry, &mem->regions);
                size -= r->length;
        } while (size);
-       mutex_unlock(&mm->mutex);
+       mutex_unlock(&pfb->base.mutex);
 
        r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
        mem->offset = (u64)r->offset << 12;
index acf818c58bf0b2428873e26602834fc56ccc16a8..9fb0f9b92d49efacf84ae5826b61b4662d59699c 100644 (file)
@@ -43,10 +43,15 @@ static int
 nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,
                  struct dcb_gpio_func *func)
 {
+       struct nouveau_bios *bios = nouveau_bios(gpio);
+       u8  ver, len;
+       u16 data;
+
        if (line == 0xff && tag == 0xff)
                return -EINVAL;
 
-       if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func))
+       data = dcb_gpio_match(bios, idx, tag, line, &ver, &len, func);
+       if (data)
                return 0;
 
        /* Apple iMac G4 NV18 */
@@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio)
        int ret = nouveau_subdev_init(&gpio->base);
        if (ret == 0 && gpio->reset) {
                if (dmi_check_system(gpio_reset_ids))
-                       gpio->reset(gpio);
+                       gpio->reset(gpio, DCB_GPIO_UNUSED);
        }
        return ret;
 }
index f3502c961cd93ea3be50b367f6eaeb62d8c720f9..bf13a1200f26188935d22dd8183855129a51e187 100644 (file)
@@ -29,15 +29,15 @@ struct nv50_gpio_priv {
 };
 
 static void
-nv50_gpio_reset(struct nouveau_gpio *gpio)
+nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)
 {
        struct nouveau_bios *bios = nouveau_bios(gpio);
        struct nv50_gpio_priv *priv = (void *)gpio;
+       u8 ver, len;
        u16 entry;
-       u8 ver;
        int ent = -1;
 
-       while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) {
+       while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) {
                static const u32 regs[] = { 0xe100, 0xe28c };
                u32 data = nv_ro32(bios, entry);
                u8  line =   (data & 0x0000001f);
@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio)
                u32 val = (unk1 << 16) | unk0;
                u32 reg = regs[line >> 4]; line &= 0x0f;
 
-               if (func == 0xff)
+               if ( func  == DCB_GPIO_UNUSED ||
+                   (match != DCB_GPIO_UNUSED && match != func))
                        continue;
 
                gpio->set(gpio, 0, func, line, defs);
index 8d18fcad26e09843899583fce69b271a42fbfa67..83e8b8f16e6ad1f3ad4a3ba5e8676ff078107c69 100644 (file)
@@ -29,15 +29,15 @@ struct nvd0_gpio_priv {
 };
 
 static void
-nvd0_gpio_reset(struct nouveau_gpio *gpio)
+nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)
 {
        struct nouveau_bios *bios = nouveau_bios(gpio);
        struct nvd0_gpio_priv *priv = (void *)gpio;
+       u8 ver, len;
        u16 entry;
-       u8 ver;
        int ent = -1;
 
-       while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) {
+       while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) {
                u32 data = nv_ro32(bios, entry);
                u8  line =   (data & 0x0000003f);
                u8  defs = !!(data & 0x00000080);
@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio)
                u8  unk0 =   (data & 0x00ff0000) >> 16;
                u8  unk1 =   (data & 0x1f000000) >> 24;
 
-               if (func == 0xff)
+               if ( func  == DCB_GPIO_UNUSED ||
+                   (match != DCB_GPIO_UNUSED && match != func))
                        continue;
 
                gpio->set(gpio, 0, func, line, defs);
index 1188227ca6aa909b88f4912608c97d1b3aa2d186..6565f3dbbe04e7e04c0721ad49f3523688f8b729 100644 (file)
@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
+       mutex_lock(&imem->base.mutex);
        list_add(&iobj->head, &imem->list);
+       mutex_unlock(&imem->base.mutex);
        return 0;
 }
 
 void
 nouveau_instobj_destroy(struct nouveau_instobj *iobj)
 {
-       if (iobj->head.prev)
-               list_del(&iobj->head);
+       struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
+
+       mutex_lock(&subdev->mutex);
+       list_del(&iobj->head);
+       mutex_unlock(&subdev->mutex);
+
        return nouveau_object_destroy(&iobj->base);
 }
 
@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem)
        if (ret)
                return ret;
 
+       mutex_lock(&imem->base.mutex);
+
        list_for_each_entry(iobj, &imem->list, head) {
                if (iobj->suspend) {
                        for (i = 0; i < iobj->size; i += 4)
@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem)
                }
        }
 
+       mutex_unlock(&imem->base.mutex);
+
        return 0;
 }
 
@@ -104,17 +114,26 @@ int
 nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
 {
        struct nouveau_instobj *iobj;
-       int i;
+       int i, ret = 0;
 
        if (suspend) {
+               mutex_lock(&imem->base.mutex);
+
                list_for_each_entry(iobj, &imem->list, head) {
                        iobj->suspend = vmalloc(iobj->size);
-                       if (iobj->suspend) {
-                               for (i = 0; i < iobj->size; i += 4)
-                                       iobj->suspend[i / 4] = nv_ro32(iobj, i);
-                       } else
-                               return -ENOMEM;
+                       if (!iobj->suspend) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+
+                       for (i = 0; i < iobj->size; i += 4)
+                               iobj->suspend[i / 4] = nv_ro32(iobj, i);
                }
+
+               mutex_unlock(&imem->base.mutex);
+
+               if (ret)
+                       return ret;
        }
 
        return nouveau_subdev_fini(&imem->base, suspend);
index 93e3ddf7303a17efec9e70d95303f5906e847bad..e286e132c7e7d744d88d99522cf2ce733b4899a6 100644 (file)
@@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent,
 
        data = mxm_table(bios, &ver, &len);
        if (!data || !(ver = nv_ro08(bios, data))) {
-               nv_info(mxm, "no VBIOS data, nothing to do\n");
+               nv_debug(mxm, "no VBIOS data, nothing to do\n");
                return 0;
        }
 
index 082c11b75acb8a23a6559ae7a5840b882aa67fbe..77c67fc970e64f187d0b37d533fd3bef3cc8139c 100644 (file)
@@ -352,7 +352,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
        u64 mm_length = (offset + length) - mm_offset;
        int ret;
 
-       vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL);
+       vm = kzalloc(sizeof(*vm), GFP_KERNEL);
        if (!vm)
                return -ENOMEM;
 
@@ -376,6 +376,8 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
                return ret;
        }
 
+       *pvm = vm;
+
        return 0;
 }
 
index 5614c89148cbc4cc4c9ce1b586611015588e6cde..1699a9083a2f86b179d0b4eba8ea1029fd52b97d 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <core/engine.h>
+#include <linux/swiotlb.h>
 
 #include <subdev/fb.h>
 #include <subdev/vm.h>
@@ -1276,7 +1277,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                if (drm->agp.stat == ENABLED) {
                        mem->bus.offset = mem->start << PAGE_SHIFT;
                        mem->bus.base = drm->agp.base;
-                       mem->bus.is_iomem = true;
+                       mem->bus.is_iomem = !dev->agp->cant_use_aperture;
                }
 #endif
                break;
index ac340ba32017402e4fc19e26c0189961e9b96927..e620ba8271b4bc4e5d71edbd8f787a2c14eecf0b 100644 (file)
@@ -127,12 +127,26 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
                             struct nouveau_encoder **pnv_encoder)
 {
        struct drm_device *dev = connector->dev;
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
        struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
-       int i;
+       struct nouveau_i2c_port *port = NULL;
+       int i, panel = -ENODEV;
+
+       /* eDP panels need powering on by us (if the VBIOS doesn't default it
+        * to on) before doing any AUX channel transactions.  LVDS panel power
+        * is handled by the SOR itself, and not required for LVDS DDC.
+        */
+       if (nv_connector->type == DCB_CONNECTOR_eDP) {
+               panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff);
+               if (panel == 0) {
+                       gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
+                       msleep(300);
+               }
+       }
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               struct nouveau_i2c_port *port = NULL;
                struct nouveau_encoder *nv_encoder;
                struct drm_mode_object *obj;
                int id;
@@ -150,11 +164,19 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
                        port = i2c->find(i2c, nv_encoder->dcb->i2c_index);
                if (port && nv_probe_i2c(port, 0x50)) {
                        *pnv_encoder = nv_encoder;
-                       return port;
+                       break;
                }
+
+               port = NULL;
        }
 
-       return NULL;
+       /* eDP panel not detected, restore panel power GPIO to previous
+        * state to avoid confusing the SOR for other output types.
+        */
+       if (!port && panel == 0)
+               gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel);
+
+       return port;
 }
 
 static struct nouveau_encoder *
index e4188f24fc758a457f26cd447d5b1d62fc763e17..508b00a2ce0de6d48b80e33d1ef1bc515598b3d2 100644 (file)
@@ -225,15 +225,6 @@ nouveau_display_init(struct drm_device *dev)
        if (ret)
                return ret;
 
-       /* power on internal panel if it's not already.  the init tables of
-        * some vbios default this to off for some reason, causing the
-        * panel to not work after resume
-        */
-       if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) {
-               gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
-               msleep(300);
-       }
-
        /* enable polling for external displays */
        drm_kms_helper_poll_enable(dev);
 
index 01c403ddb99b75893594deb571f0b6e8ef27a1a3..5e7aef23825a0d33f08addfdcb97cc8e663f62b8 100644 (file)
@@ -84,11 +84,16 @@ nouveau_cli_create(struct pci_dev *pdev, const char *name,
        struct nouveau_cli *cli;
        int ret;
 
+       *pcli = NULL;
        ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config,
                                     nouveau_debug, size, pcli);
        cli = *pcli;
-       if (ret)
+       if (ret) {
+               if (cli)
+                       nouveau_client_destroy(&cli->base);
+               *pcli = NULL;
                return ret;
+       }
 
        mutex_init(&cli->mutex);
        return 0;
@@ -189,8 +194,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
        nouveau_bo_move_init(drm);
 }
 
-static int __devinit
-nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
+static int nouveau_drm_probe(struct pci_dev *pdev,
+                            const struct pci_device_id *pent)
 {
        struct nouveau_device *device;
        struct apertures_struct *aper;
@@ -240,6 +245,8 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
        return 0;
 }
 
+static struct lock_class_key drm_client_lock_class_key;
+
 static int
 nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 {
@@ -251,6 +258,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
        ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm);
        if (ret)
                return ret;
+       lockdep_set_class(&drm->client.mutex, &drm_client_lock_class_key);
 
        dev->dev_private = drm;
        drm->dev = dev;
index bedafd1c9539f5ae0f659c29e1c034dbd36de855..cdb83acdffe264b2144e615f96bc55d346384116 100644 (file)
@@ -60,6 +60,7 @@ u32  nv10_fence_read(struct nouveau_channel *);
 void nv10_fence_context_del(struct nouveau_channel *);
 void nv10_fence_destroy(struct nouveau_drm *);
 int  nv10_fence_create(struct nouveau_drm *);
+void nv17_fence_resume(struct nouveau_drm *drm);
 
 int nv50_fence_create(struct nouveau_drm *);
 int nv84_fence_create(struct nouveau_drm *);
index 5566172774df4b2ff891db4745483b8655754a5b..a701ff5ffa5b8fdb63497eac6782523814a2cdf7 100644 (file)
@@ -698,10 +698,10 @@ static int
 nouveau_hwmon_init(struct drm_device *dev)
 {
        struct nouveau_pm *pm = nouveau_pm(dev);
-       struct nouveau_drm *drm = nouveau_drm(dev);
-       struct nouveau_therm *therm = nouveau_therm(drm->device);
 
 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
+       struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_therm *therm = nouveau_therm(drm->device);
        struct device *hwmon_dev;
        int ret = 0;
 
index 3543fec2355e52804dc69fcf8fd695632308a7a4..b8e05ae38212db2b8912f874dc4fe5fb627e7102 100644 (file)
@@ -193,6 +193,7 @@ struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev,
                if (nvbo->gem) {
                        if (nvbo->gem->dev == dev) {
                                drm_gem_object_reference(nvbo->gem);
+                               dma_buf_put(dma_buf);
                                return nvbo->gem;
                        }
                }
index 184cdf806761c0bc0cefb52af00a8799ae8e6393..39ffc07f906b8f57fcaf2427e3a5be3bbfd76bb5 100644 (file)
@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
 
 static inline bool is_powersaving_dpms(int mode)
 {
-       return (mode != DRM_MODE_DPMS_ON);
+       return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED;
 }
 
 static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
index 7ae7f97a6d4d84c273853d31bae664f16b7ca453..03017f24d593fa84b569a6c3f370b310b7ab09c2 100644 (file)
@@ -162,6 +162,13 @@ nv10_fence_destroy(struct nouveau_drm *drm)
        kfree(priv);
 }
 
+void nv17_fence_resume(struct nouveau_drm *drm)
+{
+       struct nv10_fence_priv *priv = drm->fence;
+
+       nouveau_bo_wr32(priv->bo, 0, priv->sequence);
+}
+
 int
 nv10_fence_create(struct nouveau_drm *drm)
 {
@@ -197,6 +204,7 @@ nv10_fence_create(struct nouveau_drm *drm)
                if (ret == 0) {
                        nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
                        priv->base.sync = nv17_fence_sync;
+                       priv->base.resume = nv17_fence_resume;
                }
        }
 
index c20f2727ea0ba2d114699aaf2df56416e9794729..d889f3ac0d412d4affac8c1a17428270b6f0a448 100644 (file)
@@ -122,6 +122,7 @@ nv50_fence_create(struct nouveau_drm *drm)
        if (ret == 0) {
                nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
                priv->base.sync = nv17_fence_sync;
+               priv->base.resume = nv17_fence_resume;
        }
 
        if (ret)
index f95d7fc1f5e0f8bc2446f216ca0717b4d5af14f4..a2d478e8692a0ea4e0bf0300164c400045b4c655 100644 (file)
@@ -1313,14 +1313,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
                                        radeon_wait_for_vblank(rdev, i);
                                        tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                        WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                                }
                        } else {
                                tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
                                if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
                                        radeon_wait_for_vblank(rdev, i);
                                        tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                        WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                                }
                        }
                        /* wait for the next frame */
@@ -1345,6 +1349,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                blackout &= ~BLACKOUT_MODE_MASK;
                WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
        }
+       /* wait for the MC to settle */
+       udelay(100);
 }
 
 void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
@@ -1378,11 +1384,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
                        if (ASIC_IS_DCE6(rdev)) {
                                tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
                                tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                        } else {
                                tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
                                tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                        }
                        /* wait for the next frame */
                        frame_count = radeon_get_vblank_counter(rdev, i);
@@ -2036,9 +2046,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(HDP_ADDR_CONFIG, gb_addr_config);
        WREG32(DMA_TILING_CONFIG, gb_addr_config);
 
-       tmp = gb_addr_config & NUM_PIPES_MASK;
-       tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
-                                       EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
+       if ((rdev->config.evergreen.max_backends == 1) &&
+           (rdev->flags & RADEON_IS_IGP)) {
+               if ((disabled_rb_mask & 3) == 1) {
+                       /* RB0 disabled, RB1 enabled */
+                       tmp = 0x11111111;
+               } else {
+                       /* RB1 disabled, RB0 enabled */
+                       tmp = 0x00000000;
+               }
+       } else {
+               tmp = gb_addr_config & NUM_PIPES_MASK;
+               tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
+                                               EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
+       }
        WREG32(GB_BACKEND_MAP, tmp);
 
        WREG32(CGTS_SYS_TCC_DISABLE, 0);
@@ -2306,22 +2327,20 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
        return radeon_ring_test_lockup(rdev, ring);
 }
 
-static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
+static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev)
 {
-       struct evergreen_mc_save save;
        u32 grbm_reset = 0;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return 0;
+               return;
 
-       dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -2331,10 +2350,7 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
-       evergreen_mc_stop(rdev, &save);
-       if (evergreen_mc_wait_for_idle(rdev)) {
-               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
-       }
+
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
 
@@ -2358,15 +2374,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
        udelay(50);
        WREG32(GRBM_SOFT_RESET, 0);
        (void)RREG32(GRBM_SOFT_RESET);
-       /* Wait a little for things to settle down */
-       udelay(50);
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -2376,13 +2391,71 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
+}
+
+static void evergreen_gpu_soft_reset_dma(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               return;
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+}
+
+static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+{
+       struct evergreen_mc_save save;
+
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
+       if (reset_mask == 0)
+               return 0;
+
+       dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
+
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
+               evergreen_gpu_soft_reset_gfx(rdev);
+
+       if (reset_mask & RADEON_RESET_DMA)
+               evergreen_gpu_soft_reset_dma(rdev);
+
+       /* Wait a little for things to settle down */
+       udelay(50);
+
        evergreen_mc_resume(rdev, &save);
        return 0;
 }
 
 int evergreen_asic_reset(struct radeon_device *rdev)
 {
-       return evergreen_gpu_soft_reset(rdev);
+       return evergreen_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
+                                              RADEON_RESET_COMPUTE |
+                                              RADEON_RESET_DMA));
 }
 
 /* Interrupts */
@@ -3215,7 +3288,7 @@ void evergreen_dma_fence_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0));
        /* flush HDP */
        radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0));
-       radeon_ring_write(ring, (0xf << 16) | HDP_MEM_COHERENCY_FLUSH_CNTL);
+       radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2));
        radeon_ring_write(ring, 1);
 }
 
index 74c6b42d259788fab5f35fd3d10343b16b38f8f2..ee4cff534f100dae84d64bff2122b9b2bc89a9aa 100644 (file)
@@ -2654,6 +2654,35 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        ib[idx+4] = upper_32_bits(offset) & 0xff;
                }
                break;
+       case PACKET3_MEM_WRITE:
+       {
+               u64 offset;
+
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad MEM_WRITE (invalid count)\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
+                       return -EINVAL;
+               }
+               offset = radeon_get_ib_value(p, idx+0);
+               offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
+               if (offset & 0x7) {
+                       DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
+                       return -EINVAL;
+               }
+               if ((offset + 8) > radeon_bo_size(reloc->robj)) {
+                       DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
+                                 offset + 8, radeon_bo_size(reloc->robj));
+                       return -EINVAL;
+               }
+               offset += reloc->lobj.gpu_offset;
+               ib[idx+0] = offset;
+               ib[idx+1] = upper_32_bits(offset) & 0xff;
+               break;
+       }
        case PACKET3_COPY_DW:
                if (pkt->count != 4) {
                        DRM_ERROR("bad COPY_DW (invalid count)\n");
@@ -2880,14 +2909,14 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                return -EINVAL;
                        }
                        if (tiled) {
-                               dst_offset = ib[idx+1];
+                               dst_offset = radeon_get_ib_value(p, idx+1);
                                dst_offset <<= 8;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 7;
                        } else {
-                               dst_offset = ib[idx+1];
-                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
+                               dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
@@ -2925,12 +2954,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                        DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
                                                        return -EINVAL;
                                                }
-                                               dst_offset = ib[idx+1];
+                                               dst_offset = radeon_get_ib_value(p, idx+1);
                                                dst_offset <<= 8;
-                                               dst2_offset = ib[idx+2];
+                                               dst2_offset = radeon_get_ib_value(p, idx+2);
                                                dst2_offset <<= 8;
-                                               src_offset = ib[idx+8];
-                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               src_offset = radeon_get_ib_value(p, idx+8);
+                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
                                                if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                                        dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
                                                                 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
@@ -2985,12 +3014,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                        DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
                                                        return -EINVAL;
                                                }
-                                               dst_offset = ib[idx+1];
+                                               dst_offset = radeon_get_ib_value(p, idx+1);
                                                dst_offset <<= 8;
-                                               dst2_offset = ib[idx+2];
+                                               dst2_offset = radeon_get_ib_value(p, idx+2);
                                                dst2_offset <<= 8;
-                                               src_offset = ib[idx+8];
-                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               src_offset = radeon_get_ib_value(p, idx+8);
+                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
                                                if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                                        dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
                                                                 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
@@ -3017,22 +3046,22 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                /* detile bit */
                                                if (idx_value & (1 << 31)) {
                                                        /* tiled src, linear dst */
-                                                       src_offset = ib[idx+1];
+                                                       src_offset = radeon_get_ib_value(p, idx+1);
                                                        src_offset <<= 8;
                                                        ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
 
-                                                       dst_offset = ib[idx+7];
-                                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       dst_offset = radeon_get_ib_value(p, idx+7);
+                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
                                                        ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                                        ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                                } else {
                                                        /* linear src, tiled dst */
-                                                       src_offset = ib[idx+7];
-                                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       src_offset = radeon_get_ib_value(p, idx+7);
+                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
                                                        ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                                        ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 
-                                                       dst_offset = ib[idx+1];
+                                                       dst_offset = radeon_get_ib_value(p, idx+1);
                                                        dst_offset <<= 8;
                                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                                }
@@ -3069,12 +3098,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                        DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
                                                        return -EINVAL;
                                                }
-                                               dst_offset = ib[idx+1];
+                                               dst_offset = radeon_get_ib_value(p, idx+1);
                                                dst_offset <<= 8;
-                                               dst2_offset = ib[idx+2];
+                                               dst2_offset = radeon_get_ib_value(p, idx+2);
                                                dst2_offset <<= 8;
-                                               src_offset = ib[idx+8];
-                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               src_offset = radeon_get_ib_value(p, idx+8);
+                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
                                                if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                                        dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
                                                                 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
@@ -3106,22 +3135,22 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                /* detile bit */
                                                if (idx_value & (1 << 31)) {
                                                        /* tiled src, linear dst */
-                                                       src_offset = ib[idx+1];
+                                                       src_offset = radeon_get_ib_value(p, idx+1);
                                                        src_offset <<= 8;
                                                        ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
 
-                                                       dst_offset = ib[idx+7];
-                                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       dst_offset = radeon_get_ib_value(p, idx+7);
+                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
                                                        ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                                        ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                                } else {
                                                        /* linear src, tiled dst */
-                                                       src_offset = ib[idx+7];
-                                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       src_offset = radeon_get_ib_value(p, idx+7);
+                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
                                                        ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                                        ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 
-                                                       dst_offset = ib[idx+1];
+                                                       dst_offset = radeon_get_ib_value(p, idx+1);
                                                        dst_offset <<= 8;
                                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                                }
@@ -3147,10 +3176,10 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                        switch (misc) {
                                        case 0:
                                                /* L2L, byte */
-                                               src_offset = ib[idx+2];
-                                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
-                                               dst_offset = ib[idx+1];
-                                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                                               src_offset = radeon_get_ib_value(p, idx+2);
+                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                               dst_offset = radeon_get_ib_value(p, idx+1);
+                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
                                                if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
                                                        dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
                                                                 src_offset + count, radeon_bo_size(src_reloc->robj));
@@ -3187,12 +3216,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                                        DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
                                                        return -EINVAL;
                                                }
-                                               dst_offset = ib[idx+1];
-                                               dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
-                                               dst2_offset = ib[idx+2];
-                                               dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
-                                               src_offset = ib[idx+3];
-                                               src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                               dst_offset = radeon_get_ib_value(p, idx+1);
+                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                               dst2_offset = radeon_get_ib_value(p, idx+2);
+                                               dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32;
+                                               src_offset = radeon_get_ib_value(p, idx+3);
+                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                                if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                                        dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
                                                                 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
@@ -3222,10 +3251,10 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                        }
                                } else {
                                        /* L2L, dw */
-                                       src_offset = ib[idx+2];
-                                       src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
-                                       dst_offset = ib[idx+1];
-                                       dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                                       src_offset = radeon_get_ib_value(p, idx+2);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
                                        if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                                dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
                                                         src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
@@ -3250,8 +3279,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
                                return -EINVAL;
                        }
-                       dst_offset = ib[idx+1];
-                       dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
+                       dst_offset = radeon_get_ib_value(p, idx+1);
+                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
                                         dst_offset, radeon_bo_size(dst_reloc->robj));
@@ -3287,6 +3316,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
 
        /* check config regs */
        switch (reg) {
+       case WAIT_UNTIL:
        case GRBM_GFX_INDEX:
        case CP_STRMOUT_CNTL:
        case CP_COHER_CNTL:
index cb9baaac9e85102505347cac84c1dd717709d2e4..0bfd0e9e469b57ca395049ce1dfae500b67b3936 100644 (file)
 #define                SOFT_RESET_ROM                          (1 << 14)
 #define                SOFT_RESET_SEM                          (1 << 15)
 #define                SOFT_RESET_VMC                          (1 << 17)
+#define                SOFT_RESET_DMA                          (1 << 20)
 #define                SOFT_RESET_TST                          (1 << 21)
-#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_REGBB                        (1 << 22)
 #define                SOFT_RESET_ORB                          (1 << 23)
 
 /* display watermarks */
 /* cayman packet3 addition */
 #define        CAYMAN_PACKET3_DEALLOC_STATE                    0x14
 
+/* DMA regs common on r6xx/r7xx/evergreen/ni */
+#define DMA_RB_CNTL                                       0xd000
+#       define DMA_RB_ENABLE                              (1 << 0)
+#       define DMA_RB_SIZE(x)                             ((x) << 1) /* log2 */
+#       define DMA_RB_SWAP_ENABLE                         (1 << 9) /* 8IN32 */
+#       define DMA_RPTR_WRITEBACK_ENABLE                  (1 << 12)
+#       define DMA_RPTR_WRITEBACK_SWAP_ENABLE             (1 << 13)  /* 8IN32 */
+#       define DMA_RPTR_WRITEBACK_TIMER(x)                ((x) << 16) /* log2 */
+#define DMA_STATUS_REG                                    0xd034
+#       define DMA_IDLE                                   (1 << 0)
+
 #endif
index 7bdbcb00aaf267df84a7c0c02f39541d6f61abeb..835992d8d067bf199bdf2ec633e634133ed16a4a 100644 (file)
@@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev)
 int cayman_dma_resume(struct radeon_device *rdev)
 {
        struct radeon_ring *ring;
-       u32 rb_cntl, dma_cntl;
+       u32 rb_cntl, dma_cntl, ib_cntl;
        u32 rb_bufsz;
        u32 reg_offset, wb_offset;
        int i, r;
@@ -1265,7 +1265,11 @@ int cayman_dma_resume(struct radeon_device *rdev)
                WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8);
 
                /* enable DMA IBs */
-               WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE);
+               ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE;
+#ifdef __BIG_ENDIAN
+               ib_cntl |= DMA_IB_SWAP_ENABLE;
+#endif
+               WREG32(DMA_IB_CNTL + reg_offset, ib_cntl);
 
                dma_cntl = RREG32(DMA_CNTL + reg_offset);
                dma_cntl &= ~CTXEMPTY_INT_ENABLE;
@@ -1306,22 +1310,20 @@ void cayman_dma_fini(struct radeon_device *rdev)
        radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]);
 }
 
-static int cayman_gpu_soft_reset(struct radeon_device *rdev)
+static void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev)
 {
-       struct evergreen_mc_save save;
        u32 grbm_reset = 0;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return 0;
+               return;
 
-       dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1331,19 +1333,7 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
-       dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
-                RREG32(0x14F8));
-       dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
-                RREG32(0x14D8));
-       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-                RREG32(0x14FC));
-       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-                RREG32(0x14DC));
 
-       evergreen_mc_stop(rdev, &save);
-       if (evergreen_mc_wait_for_idle(rdev)) {
-               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
-       }
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
 
@@ -1368,16 +1358,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
        udelay(50);
        WREG32(GRBM_SOFT_RESET, 0);
        (void)RREG32(GRBM_SOFT_RESET);
-       /* Wait a little for things to settle down */
-       udelay(50);
 
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1387,13 +1375,87 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
+
+}
+
+static void cayman_gpu_soft_reset_dma(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               return;
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+
+}
+
+static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+{
+       struct evergreen_mc_save save;
+
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
+       if (reset_mask == 0)
+               return 0;
+
+       dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
+
+       dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
+                RREG32(0x14F8));
+       dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
+                RREG32(0x14D8));
+       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
+                RREG32(0x14FC));
+       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+                RREG32(0x14DC));
+
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
+               cayman_gpu_soft_reset_gfx(rdev);
+
+       if (reset_mask & RADEON_RESET_DMA)
+               cayman_gpu_soft_reset_dma(rdev);
+
+       /* Wait a little for things to settle down */
+       udelay(50);
+
        evergreen_mc_resume(rdev, &save);
        return 0;
 }
 
 int cayman_asic_reset(struct radeon_device *rdev)
 {
-       return cayman_gpu_soft_reset(rdev);
+       return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
+                                           RADEON_RESET_COMPUTE |
+                                           RADEON_RESET_DMA));
 }
 
 /**
index b93186b8ee4ba951189c1ca2b45d381c07ed51c4..48e5022ee921d33081f86de17d8ab6b0520ea037 100644 (file)
@@ -65,7 +65,7 @@
 #define                SOFT_RESET_VMC                          (1 << 17)
 #define                SOFT_RESET_DMA                          (1 << 20)
 #define                SOFT_RESET_TST                          (1 << 21)
-#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_REGBB                        (1 << 22)
 #define                SOFT_RESET_ORB                          (1 << 23)
 
 #define VM_CONTEXT0_REQUEST_RESPONSE                   0x1470
 #define        DMA_PACKET_NOP                                    0xf
 
 #endif
-
index 2aaf147969bd8ef80522af9e38900e5987002d4c..becb03e8b32f6fdcc17630108c00bfc9fb4a973d 100644 (file)
@@ -1258,9 +1258,8 @@ void r600_vram_scratch_fini(struct radeon_device *rdev)
  * reset, it's up to the caller to determine if the GPU needs one. We
  * might add an helper function to check that.
  */
-static int r600_gpu_soft_reset(struct radeon_device *rdev)
+static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev)
 {
-       struct rv515_mc_save save;
        u32 grbm_busy_mask = S_008010_VC_BUSY(1) | S_008010_VGT_BUSY_NO_DMA(1) |
                                S_008010_VGT_BUSY(1) | S_008010_TA03_BUSY(1) |
                                S_008010_TC_BUSY(1) | S_008010_SX_BUSY(1) |
@@ -1280,14 +1279,13 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
        u32 tmp;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return 0;
+               return;
 
-       dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
                RREG32(R_008010_GRBM_STATUS));
-       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
                RREG32(R_008014_GRBM_STATUS2));
-       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
                RREG32(R_000E50_SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1297,12 +1295,10 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
-       rv515_mc_stop(rdev, &save);
-       if (r600_mc_wait_for_idle(rdev)) {
-               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
-       }
+
        /* Disable CP parsing/prefetching */
        WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+
        /* Check if any of the rendering block is busy and reset it */
        if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) ||
            (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) {
@@ -1332,13 +1328,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
        RREG32(R_008020_GRBM_SOFT_RESET);
        mdelay(15);
        WREG32(R_008020_GRBM_SOFT_RESET, 0);
-       /* Wait a little for things to settle down */
-       mdelay(1);
-       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
                RREG32(R_008010_GRBM_STATUS));
-       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
                RREG32(R_008014_GRBM_STATUS2));
-       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
                RREG32(R_000E50_SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1348,6 +1343,66 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
+
+}
+
+static void r600_gpu_soft_reset_dma(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               return;
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       /* Reset dma */
+       if (rdev->family >= CHIP_RV770)
+               WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA);
+       else
+               WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+}
+
+static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+{
+       struct rv515_mc_save save;
+
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
+       if (reset_mask == 0)
+               return 0;
+
+       dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
+
+       rv515_mc_stop(rdev, &save);
+       if (r600_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
+               r600_gpu_soft_reset_gfx(rdev);
+
+       if (reset_mask & RADEON_RESET_DMA)
+               r600_gpu_soft_reset_dma(rdev);
+
+       /* Wait a little for things to settle down */
+       mdelay(1);
+
        rv515_mc_resume(rdev, &save);
        return 0;
 }
@@ -1395,7 +1450,9 @@ bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 
 int r600_asic_reset(struct radeon_device *rdev)
 {
-       return r600_gpu_soft_reset(rdev);
+       return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
+                                         RADEON_RESET_COMPUTE |
+                                         RADEON_RESET_DMA));
 }
 
 u32 r6xx_remap_render_backend(struct radeon_device *rdev,
@@ -1405,12 +1462,15 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev,
                              u32 disabled_rb_mask)
 {
        u32 rendering_pipe_num, rb_num_width, req_rb_num;
-       u32 pipe_rb_ratio, pipe_rb_remain;
+       u32 pipe_rb_ratio, pipe_rb_remain, tmp;
        u32 data = 0, mask = 1 << (max_rb_num - 1);
        unsigned i, j;
 
        /* mask out the RBs that don't exist on that asic */
-       disabled_rb_mask |= (0xff << max_rb_num) & 0xff;
+       tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff);
+       /* make sure at least one RB is available */
+       if ((tmp & 0xff) != 0xff)
+               disabled_rb_mask = tmp;
 
        rendering_pipe_num = 1 << tiling_pipe_num;
        req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask);
@@ -2256,7 +2316,7 @@ void r600_dma_stop(struct radeon_device *rdev)
 int r600_dma_resume(struct radeon_device *rdev)
 {
        struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
-       u32 rb_cntl, dma_cntl;
+       u32 rb_cntl, dma_cntl, ib_cntl;
        u32 rb_bufsz;
        int r;
 
@@ -2296,7 +2356,11 @@ int r600_dma_resume(struct radeon_device *rdev)
        WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
 
        /* enable DMA IBs */
-       WREG32(DMA_IB_CNTL, DMA_IB_ENABLE);
+       ib_cntl = DMA_IB_ENABLE;
+#ifdef __BIG_ENDIAN
+       ib_cntl |= DMA_IB_SWAP_ENABLE;
+#endif
+       WREG32(DMA_IB_CNTL, ib_cntl);
 
        dma_cntl = RREG32(DMA_CNTL);
        dma_cntl &= ~CTXEMPTY_INT_ENABLE;
@@ -2595,7 +2659,7 @@ int r600_copy_blit(struct radeon_device *rdev,
  * @num_gpu_pages: number of GPU pages to xfer
  * @fence: radeon fence object
  *
- * Copy GPU paging using the DMA engine (r6xx-r7xx).
+ * Copy GPU paging using the DMA engine (r6xx).
  * Used by the radeon ttm implementation to move pages if
  * registered as the asic copy callback.
  */
@@ -2618,8 +2682,8 @@ int r600_copy_dma(struct radeon_device *rdev,
        }
 
        size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4;
-       num_loops = DIV_ROUND_UP(size_in_dw, 0xffff);
-       r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8);
+       num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFE);
+       r = radeon_ring_lock(rdev, ring, num_loops * 4 + 8);
        if (r) {
                DRM_ERROR("radeon: moving bo (%d).\n", r);
                radeon_semaphore_free(rdev, &sem, NULL);
@@ -2636,14 +2700,14 @@ int r600_copy_dma(struct radeon_device *rdev,
 
        for (i = 0; i < num_loops; i++) {
                cur_size_in_dw = size_in_dw;
-               if (cur_size_in_dw > 0xFFFF)
-                       cur_size_in_dw = 0xFFFF;
+               if (cur_size_in_dw > 0xFFFE)
+                       cur_size_in_dw = 0xFFFE;
                size_in_dw -= cur_size_in_dw;
                radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw));
                radeon_ring_write(ring, dst_offset & 0xfffffffc);
                radeon_ring_write(ring, src_offset & 0xfffffffc);
-               radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff);
-               radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff);
+               radeon_ring_write(ring, (((upper_32_bits(dst_offset) & 0xff) << 16) |
+                                        (upper_32_bits(src_offset) & 0xff)));
                src_offset += cur_size_in_dw * 4;
                dst_offset += cur_size_in_dw * 4;
        }
index 0be768be530c7ceea8e0b4125a3932ed4e696c35..9b2512bf1a46638f870b5967a45877455fc48c0f 100644 (file)
@@ -2294,6 +2294,35 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        ib[idx+4] = upper_32_bits(offset) & 0xff;
                }
                break;
+       case PACKET3_MEM_WRITE:
+       {
+               u64 offset;
+
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad MEM_WRITE (invalid count)\n");
+                       return -EINVAL;
+               }
+               r = r600_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
+                       return -EINVAL;
+               }
+               offset = radeon_get_ib_value(p, idx+0);
+               offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
+               if (offset & 0x7) {
+                       DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
+                       return -EINVAL;
+               }
+               if ((offset + 8) > radeon_bo_size(reloc->robj)) {
+                       DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
+                                 offset + 8, radeon_bo_size(reloc->robj));
+                       return -EINVAL;
+               }
+               offset += reloc->lobj.gpu_offset;
+               ib[idx+0] = offset;
+               ib[idx+1] = upper_32_bits(offset) & 0xff;
+               break;
+       }
        case PACKET3_COPY_DW:
                if (pkt->count != 4) {
                        DRM_ERROR("bad COPY_DW (invalid count)\n");
@@ -2447,8 +2476,10 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
        kfree(parser->relocs);
        for (i = 0; i < parser->nchunks; i++) {
                kfree(parser->chunks[i].kdata);
-               kfree(parser->chunks[i].kpage[0]);
-               kfree(parser->chunks[i].kpage[1]);
+               if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) {
+                       kfree(parser->chunks[i].kpage[0]);
+                       kfree(parser->chunks[i].kpage[1]);
+               }
        }
        kfree(parser->chunks);
        kfree(parser->chunks_array);
@@ -2532,16 +2563,16 @@ int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
        struct radeon_cs_chunk *relocs_chunk;
        unsigned idx;
 
+       *cs_reloc = NULL;
        if (p->chunk_relocs_idx == -1) {
                DRM_ERROR("No relocation chunk !\n");
                return -EINVAL;
        }
-       *cs_reloc = NULL;
        relocs_chunk = &p->chunks[p->chunk_relocs_idx];
        idx = p->dma_reloc_idx;
-       if (idx >= relocs_chunk->length_dw) {
+       if (idx >= p->nrelocs) {
                DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
+                         idx, p->nrelocs);
                return -EINVAL;
        }
        *cs_reloc = p->relocs_ptr[idx];
@@ -2592,14 +2623,14 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                return -EINVAL;
                        }
                        if (tiled) {
-                               dst_offset = ib[idx+1];
+                               dst_offset = radeon_get_ib_value(p, idx+1);
                                dst_offset <<= 8;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 5;
                        } else {
-                               dst_offset = ib[idx+1];
-                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
+                               dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
@@ -2627,37 +2658,50 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                /* detile bit */
                                if (idx_value & (1 << 31)) {
                                        /* tiled src, linear dst */
-                                       src_offset = ib[idx+1];
+                                       src_offset = radeon_get_ib_value(p, idx+1);
                                        src_offset <<= 8;
                                        ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
 
-                                       dst_offset = ib[idx+5];
-                                       dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+5);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
                                        /* linear src, tiled dst */
-                                       src_offset = ib[idx+5];
-                                       src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       src_offset = radeon_get_ib_value(p, idx+5);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 
-                                       dst_offset = ib[idx+1];
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
                                        dst_offset <<= 8;
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
                                p->idx += 7;
                        } else {
-                               src_offset = ib[idx+2];
-                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
-                               dst_offset = ib[idx+1];
-                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
-
-                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                               p->idx += 5;
+                               if (p->family >= CHIP_RV770) {
+                                       src_offset = radeon_get_ib_value(p, idx+2);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
+
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                       ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                       p->idx += 5;
+                               } else {
+                                       src_offset = radeon_get_ib_value(p, idx+2);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16;
+
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+3] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                       ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff) << 16;
+                                       p->idx += 4;
+                               }
                        }
                        if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
                                dev_warn(p->dev, "DMA copy src buffer too small (%llu %lu)\n",
@@ -2680,8 +2724,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                DRM_ERROR("bad DMA_PACKET_WRITE\n");
                                return -EINVAL;
                        }
-                       dst_offset = ib[idx+1];
-                       dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
+                       dst_offset = radeon_get_ib_value(p, idx+1);
+                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
                                         dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
index 5dc744d43d128a537078153a5cf94803a4906101..a08f657329a0e821d681678a6e1f74de357b042e 100644 (file)
@@ -132,6 +132,11 @@ extern int radeon_lockup_timeout;
 #define RADEON_VA_RESERVED_SIZE                        (8 << 20)
 #define RADEON_IB_VM_MAX_SIZE                  (64 << 10)
 
+/* reset flags */
+#define RADEON_RESET_GFX                       (1 << 0)
+#define RADEON_RESET_COMPUTE                   (1 << 1)
+#define RADEON_RESET_DMA                       (1 << 2)
+
 /*
  * Errata workarounds.
  */
@@ -225,12 +230,13 @@ struct radeon_fence {
 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
 int radeon_fence_driver_init(struct radeon_device *rdev);
 void radeon_fence_driver_fini(struct radeon_device *rdev);
+void radeon_fence_driver_force_completion(struct radeon_device *rdev);
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring);
 void radeon_fence_process(struct radeon_device *rdev, int ring);
 bool radeon_fence_signaled(struct radeon_fence *fence);
 int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
 int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
 int radeon_fence_wait_any(struct radeon_device *rdev,
                          struct radeon_fence **fences,
                          bool intr);
@@ -318,7 +324,6 @@ struct radeon_bo {
        struct list_head                list;
        /* Protected by tbo.reserved */
        u32                             placements[3];
-       u32                             busy_placements[3];
        struct ttm_placement            placement;
        struct ttm_buffer_object        tbo;
        struct ttm_bo_kmap_obj          kmap;
@@ -648,6 +653,8 @@ struct radeon_ring {
        u32                     ptr_reg_mask;
        u32                     nop;
        u32                     idx;
+       u64                     last_semaphore_signal_addr;
+       u64                     last_semaphore_wait_addr;
 };
 
 /*
index 596bcbe80ed06d5a8e50c271ded50d0a9003afaf..0b202c07fe509075ed9bfedb3c8d9b01feb5d8d8 100644 (file)
@@ -1140,9 +1140,9 @@ static struct radeon_asic rv770_asic = {
        .copy = {
                .blit = &r600_copy_blit,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
-               .dma = &r600_copy_dma,
+               .dma = &rv770_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
-               .copy = &r600_copy_dma,
+               .copy = &rv770_copy_dma,
                .copy_ring_index = R600_RING_TYPE_DMA_INDEX,
        },
        .surface = {
@@ -1445,7 +1445,7 @@ static struct radeon_asic cayman_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1572,7 +1572,7 @@ static struct radeon_asic trinity_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1699,7 +1699,7 @@ static struct radeon_asic si_asic = {
        .vm = {
                .init = &si_vm_init,
                .fini = &si_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &si_vm_set_page,
        },
        .ring = {
index 5f4882cc2152eda52e3bf25bf3bd9573bf4e610a..15d70e613076d48e89aff920becbd7e18419a7d8 100644 (file)
@@ -403,6 +403,10 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 void r700_cp_stop(struct radeon_device *rdev);
 void r700_cp_fini(struct radeon_device *rdev);
+int rv770_copy_dma(struct radeon_device *rdev,
+                 uint64_t src_offset, uint64_t dst_offset,
+                 unsigned num_gpu_pages,
+                  struct radeon_fence **fence);
 
 /*
  * evergreen
index 4af89126e223c4fd2b8dc85c86ef377544b30ee9..3e403bdda58fc8eb69b3583d647770f2b9b41210 100644 (file)
@@ -1548,6 +1548,9 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                           of_machine_is_compatible("PowerBook6,7")) {
                        /* ibook */
                        rdev->mode_info.connector_table = CT_IBOOK;
+               } else if (of_machine_is_compatible("PowerMac3,5")) {
+                       /* PowerMac G4 Silver radeon 7500 */
+                       rdev->mode_info.connector_table = CT_MAC_G4_SILVER;
                } else if (of_machine_is_compatible("PowerMac4,4")) {
                        /* emac */
                        rdev->mode_info.connector_table = CT_EMAC;
@@ -2212,6 +2215,54 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                            CONNECTOR_OBJECT_ID_SVIDEO,
                                            &hpd);
                break;
+       case CT_MAC_G4_SILVER:
+               DRM_INFO("Connector Table: %d (mac g4 silver)\n",
+                        rdev->mode_info.connector_table);
+               /* DVI-I - tv dac, int tmds */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
+               hpd.hpd = RADEON_HPD_1; /* ??? */
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_DFP1_SUPPORT,
+                                                               0),
+                                         ATOM_DEVICE_DFP1_SUPPORT);
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_CRT2_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_CRT2_SUPPORT);
+               radeon_add_legacy_connector(dev, 0,
+                                           ATOM_DEVICE_DFP1_SUPPORT |
+                                           ATOM_DEVICE_CRT2_SUPPORT,
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+                                           &hpd);
+               /* VGA - primary dac */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_CRT1_SUPPORT,
+                                                               1),
+                                         ATOM_DEVICE_CRT1_SUPPORT);
+               radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               /* TV - TV DAC */
+               ddc_i2c.valid = false;
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_TV1_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_TV1_SUPPORT);
+               radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_SVIDEO,
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO,
+                                           &hpd);
+               break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
                         rdev->mode_info.connector_table);
@@ -2419,6 +2470,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                                   1),
                                                                  ATOM_DEVICE_CRT1_SUPPORT);
                                }
+                               /* RV100 board with external TDMS bit mis-set.
+                                * Actually uses internal TMDS, clear the bit.
+                                */
+                               if (dev->pdev->device == 0x5159 &&
+                                   dev->pdev->subsystem_vendor == 0x1014 &&
+                                   dev->pdev->subsystem_device == 0x029A) {
+                                       tmp &= ~(1 << 4);
+                               }
                                if ((tmp >> 4) & 0x1) {
                                        devices |= ATOM_DEVICE_DFP2_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
index 47bf162ab9c672825d80a803e14d8aa652a98f04..2399f25ec0370cfba03b256174de69e407e01353 100644 (file)
@@ -741,7 +741,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
                ret = connector_status_disconnected;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector, false);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -947,7 +947,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                return connector->status;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector, false);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -1401,7 +1401,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                if (encoder) {
                        /* setup ddc on the bridge */
                        radeon_atom_ext_encoder_setup_ddc(encoder);
-                       if (radeon_ddc_probe(radeon_connector)) /* try DDC */
+                       /* bridge chips are always aux */
+                       if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */
                                ret = connector_status_connected;
                        else if (radeon_connector->dac_load_detect) { /* try load detection */
                                struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -1419,7 +1420,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                if (radeon_dp_getdpcd(radeon_connector))
                                        ret = connector_status_connected;
                        } else {
-                               if (radeon_ddc_probe(radeon_connector))
+                               /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */
+                               if (radeon_ddc_probe(radeon_connector, false))
                                        ret = connector_status_connected;
                        }
                }
index 396baba0141a9c2abefbd5e8782a83e5634c4c96..5407459e56d2b5dd9619e698c2ec306c56104f4a 100644 (file)
@@ -279,13 +279,15 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                                  p->chunks[p->chunk_ib_idx].length_dw);
                        return -EINVAL;
                }
-               if ((p->rdev->flags & RADEON_IS_AGP)) {
+               if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) {
                        p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
                        p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
                        if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
                            p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
-                               kfree(p->chunks[i].kpage[0]);
-                               kfree(p->chunks[i].kpage[1]);
+                               kfree(p->chunks[p->chunk_ib_idx].kpage[0]);
+                               kfree(p->chunks[p->chunk_ib_idx].kpage[1]);
+                               p->chunks[p->chunk_ib_idx].kpage[0] = NULL;
+                               p->chunks[p->chunk_ib_idx].kpage[1] = NULL;
                                return -ENOMEM;
                        }
                }
@@ -583,7 +585,8 @@ static int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
        struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
        int i;
        int size = PAGE_SIZE;
-       bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true;
+       bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ?
+               false : true;
 
        for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
                if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)),
index ad6df625e8b8a1cf869ac06bb898503022406a6b..0d67674b64b13e9a4618548fb1ca3d2d2211f797 100644 (file)
@@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                y = 0;
        }
 
-       if (ASIC_IS_AVIVO(rdev)) {
+       /* fixed on DCE6 and newer */
+       if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
                int i = 0;
                struct drm_crtc *crtc_p;
 
index 49b06590001e1a30ca65761cfab2e20d901bc215..0d6562bb0c93e61e7b57e4fd09f31a802ba34d99 100644 (file)
@@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev)
 {
        uint32_t reg;
 
-       if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
+       if (efi_enabled(EFI_BOOT) &&
+           rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
                return false;
 
        /* first check CRTCs */
@@ -896,6 +897,25 @@ static void radeon_check_arguments(struct radeon_device *rdev)
        }
 }
 
+/**
+ * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is
+ * needed for waking up.
+ *
+ * @pdev: pci dev pointer
+ */
+static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
+{
+
+       /* 6600m in a macbook pro */
+       if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+           pdev->subsystem_device == 0x00e2) {
+               printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n");
+               return true;
+       }
+
+       return false;
+}
+
 /**
  * radeon_switcheroo_set_state - set switcheroo state
  *
@@ -910,10 +930,19 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
+               unsigned d3_delay = dev->pdev->d3_delay;
+
                printk(KERN_INFO "radeon: switched on\n");
                /* don't suspend or resume card normally */
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
+
+               if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
+                       dev->pdev->d3_delay = 20;
+
                radeon_resume_kms(dev);
+
+               dev->pdev->d3_delay = d3_delay;
+
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
                drm_kms_helper_poll_enable(dev);
        } else {
@@ -1164,6 +1193,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
        struct drm_crtc *crtc;
        struct drm_connector *connector;
        int i, r;
+       bool force_completion = false;
 
        if (dev == NULL || dev->dev_private == NULL) {
                return -ENODEV;
@@ -1206,8 +1236,16 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
        mutex_lock(&rdev->ring_lock);
        /* wait for gpu to finish processing current batch */
-       for (i = 0; i < RADEON_NUM_RINGS; i++)
-               radeon_fence_wait_empty_locked(rdev, i);
+       for (i = 0; i < RADEON_NUM_RINGS; i++) {
+               r = radeon_fence_wait_empty_locked(rdev, i);
+               if (r) {
+                       /* delay GPU reset to resume */
+                       force_completion = true;
+               }
+       }
+       if (force_completion) {
+               radeon_fence_driver_force_completion(rdev);
+       }
        mutex_unlock(&rdev->ring_lock);
 
        radeon_save_bios_scratch_regs(rdev);
@@ -1338,7 +1376,6 @@ retry:
        }
 
        radeon_restore_bios_scratch_regs(rdev);
-       drm_helper_resume_force_mode(rdev->ddev);
 
        if (!r) {
                for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -1358,11 +1395,14 @@ retry:
                        }
                }
        } else {
+               radeon_fence_driver_force_completion(rdev);
                for (i = 0; i < RADEON_NUM_RINGS; ++i) {
                        kfree(ring_data[i]);
                }
        }
 
+       drm_helper_resume_force_mode(rdev->ddev);
+
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
        if (r) {
                /* bad news, how to tell it to userspace ? */
index 310c0e5254babc770ec620b9f1735390ffb8ce78..05c96fa0b0515a9eab3a89b6bcab97fd1af888dd 100644 (file)
@@ -699,10 +699,15 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
        if (radeon_connector->router.ddc_valid)
                radeon_router_select_ddc_port(radeon_connector);
 
-       if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
-           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
-           (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
-            ENCODER_OBJECT_ID_NONE)) {
+       if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
+           ENCODER_OBJECT_ID_NONE) {
+               struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
+               if (dig->dp_i2c_bus)
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &dig->dp_i2c_bus->adapter);
+       } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+                  (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
 
                if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
@@ -1110,14 +1115,16 @@ radeon_user_framebuffer_create(struct drm_device *dev,
        }
 
        radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
-       if (radeon_fb == NULL)
+       if (radeon_fb == NULL) {
+               drm_gem_object_unreference_unlocked(obj);
                return ERR_PTR(-ENOMEM);
+       }
 
        ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
        if (ret) {
                kfree(radeon_fb);
                drm_gem_object_unreference_unlocked(obj);
-               return NULL;
+               return ERR_PTR(ret);
        }
 
        return &radeon_fb->base;
index 9b1a727d3c9e450b926cae872735fd7c05d3456a..d9bf96ee299acc88181f003b1eff5dc226f7ced4 100644 (file)
  *   2.25.0 - eg+: new info request for num SE and num SH
  *   2.26.0 - r600-eg: fix htile size computation
  *   2.27.0 - r600-SI: Add CS ioctl support for async DMA
+ *   2.28.0 - r600-eg: Add MEM_WRITE packet support
+ *   2.29.0 - R500 FP16 color clear registers
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       27
+#define KMS_DRIVER_MINOR       29
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -305,8 +307,8 @@ static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
        return 0;
 }
 
-static int __devinit
-radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int radeon_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        int ret;
 
index 410a975a8eec8f7e042a608cfcea0d7c274f1932..34356252567ad23291d9a60c6df1a06ed211c149 100644 (file)
@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
  * Returns 0 if the fences have passed, error for all other cases.
  * Caller must hold ring lock.
  */
-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
 {
        uint64_t seq = rdev->fence_drv[ring].sync_seq[ring];
+       int r;
 
-       while(1) {
-               int r;
-               r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
+       r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
+       if (r) {
                if (r == -EDEADLK) {
-                       mutex_unlock(&rdev->ring_lock);
-                       r = radeon_gpu_reset(rdev);
-                       mutex_lock(&rdev->ring_lock);
-                       if (!r)
-                               continue;
-               }
-               if (r) {
-                       dev_err(rdev->dev, "error waiting for ring to become"
-                               " idle (%d)\n", r);
+                       return -EDEADLK;
                }
-               return;
+               dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n",
+                       ring, r);
        }
+       return 0;
 }
 
 /**
@@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
  */
 void radeon_fence_driver_fini(struct radeon_device *rdev)
 {
-       int ring;
+       int ring, r;
 
        mutex_lock(&rdev->ring_lock);
        for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
                if (!rdev->fence_drv[ring].initialized)
                        continue;
-               radeon_fence_wait_empty_locked(rdev, ring);
+               r = radeon_fence_wait_empty_locked(rdev, ring);
+               if (r) {
+                       /* no need to trigger GPU reset as we are unloading */
+                       radeon_fence_driver_force_completion(rdev);
+               }
                wake_up_all(&rdev->fence_queue);
                radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
                rdev->fence_drv[ring].initialized = false;
@@ -868,6 +866,25 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
        mutex_unlock(&rdev->ring_lock);
 }
 
+/**
+ * radeon_fence_driver_force_completion - force all fence waiter to complete
+ *
+ * @rdev: radeon device pointer
+ *
+ * In case of GPU reset failure make sure no process keep waiting on fence
+ * that will never complete.
+ */
+void radeon_fence_driver_force_completion(struct radeon_device *rdev)
+{
+       int ring;
+
+       for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
+               if (!rdev->fence_drv[ring].initialized)
+                       continue;
+               radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring);
+       }
+}
+
 
 /*
  * Fence debugfs
index c5bddd630eb94e088f6f90a1c7cf93f8659a8cc1..fc60b74ee304dd779d98db03b3ec60c58767ed9a 100644 (file)
@@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap);
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux)
 {
        u8 out = 0x0;
        u8 buf[8];
@@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
        if (radeon_connector->router.ddc_valid)
                radeon_router_select_ddc_port(radeon_connector);
 
-       ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+       if (use_aux) {
+               struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+               ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2);
+       } else {
+               ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+       }
+
        if (ret != 2)
                /* Couldn't find an accessible DDC on this connector */
                return false;
index f5ba2241dacc6cfd2bb6b55fead51a7ae2c395e8..62cd512f5c8d4161ff3708204fe32f560566402e 100644 (file)
@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
        enum drm_connector_status found = connector_status_disconnected;
        bool color = true;
 
+       /* just don't bother on RN50 those chip are often connected to remoting
+        * console hw and often we get failure to load detect those. So to make
+        * everyone happy report the encoder as always connected.
+        */
+       if (ASIC_IS_RN50(rdev)) {
+               return connector_status_connected;
+       }
+
        /* save the regs we need */
        vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
        crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
index d818b503b42f545e8fff7d2287d6129d20a14de1..4003f5a68c098a06458cf7d0d18cd894412c3fe3 100644 (file)
@@ -209,7 +209,8 @@ enum radeon_connector_table {
        CT_RN50_POWER,
        CT_MAC_X800,
        CT_MAC_G5_9600,
-       CT_SAM440EP
+       CT_SAM440EP,
+       CT_MAC_G4_SILVER
 };
 
 enum radeon_dvo_chip {
@@ -558,7 +559,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
                                u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
index 883c95d8d90f4559b04b8a6e4ca319a896629681..d3aface2d12d6f3a03ee5f5a2667b42caf52d7d5 100644 (file)
@@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        rbo->placement.fpfn = 0;
        rbo->placement.lpfn = 0;
        rbo->placement.placement = rbo->placements;
+       rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM)
                rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
                                        TTM_PL_FLAG_VRAM;
@@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        if (!c)
                rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
        rbo->placement.num_placement = c;
-
-       c = 0;
-       rbo->placement.busy_placement = rbo->busy_placements;
-       if (rbo->rdev->flags & RADEON_IS_AGP) {
-               rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
-       } else {
-               rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
-       }
        rbo->placement.num_busy_placement = c;
 }
 
@@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head)
 {
        struct radeon_bo_list *lobj;
        struct radeon_bo *bo;
+       u32 domain;
        int r;
 
        r = ttm_eu_reserve_buffers(head);
@@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head)
        list_for_each_entry(lobj, head, tv.head) {
                bo = lobj->bo;
                if (!bo->pin_count) {
+                       domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+                       
+               retry:
+                       radeon_ttm_placement_from_domain(bo, domain);
                        r = ttm_bo_validate(&bo->tbo, &bo->placement,
                                                true, false);
                        if (unlikely(r)) {
+                               if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+                                       domain |= RADEON_GEM_DOMAIN_GTT;
+                                       goto retry;
+                               }
                                return r;
                        }
                }
index aa14dbb7e4fbac2a81070f3d14abb28a24c3db30..0bfa656aa87d482fead90b86c73aac94e94849de 100644 (file)
@@ -234,7 +234,7 @@ static void radeon_set_power_state(struct radeon_device *rdev)
 
 static void radeon_pm_set_clocks(struct radeon_device *rdev)
 {
-       int i;
+       int i, r;
 
        /* no need to take locks, etc. if nothing's going to change */
        if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
        /* wait for the rings to drain */
        for (i = 0; i < RADEON_NUM_RINGS; i++) {
                struct radeon_ring *ring = &rdev->ring[i];
-               if (ring->ready)
-                       radeon_fence_wait_empty_locked(rdev, i);
+               if (!ring->ready) {
+                       continue;
+               }
+               r = radeon_fence_wait_empty_locked(rdev, i);
+               if (r) {
+                       /* needs a GPU reset dont reset here */
+                       mutex_unlock(&rdev->ring_lock);
+                       up_write(&rdev->pm.mclk_lock);
+                       mutex_unlock(&rdev->ddev->struct_mutex);
+                       return;
+               }
        }
 
        radeon_unmap_vram_bos(rdev);
index e09521858f64469cf51b7c8700576d5b6744998e..26c23bb651c6b53835a2061096bdecd4f9d47492 100644 (file)
@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_import(struct drm_device *dev,
                bo = dma_buf->priv;
                if (bo->gem_base.dev == dev) {
                        drm_gem_object_reference(&bo->gem_base);
+                       dma_buf_put(dma_buf);
                        return &bo->gem_base;
                }
        }
index ebd69562ef6c802af7956dd168de29bf27f6f19f..cd72062d5a9134bd596c8a6388b78fd45bb02425 100644 (file)
@@ -377,6 +377,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
 {
        int r;
 
+       /* make sure we aren't trying to allocate more space than there is on the ring */
+       if (ndw > (ring->ring_size / 4))
+               return -ENOMEM;
        /* Align requested size with padding so unlock_commit can
         * pad safely */
        ndw = (ndw + ring->align_mask) & ~ring->align_mask;
@@ -770,22 +773,30 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
        int ridx = *(int*)node->info_ent->data;
        struct radeon_ring *ring = &rdev->ring[ridx];
        unsigned count, i, j;
+       u32 tmp;
 
        radeon_ring_free_size(rdev, ring);
        count = (ring->ring_size / 4) - ring->ring_free_dw;
-       seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg));
-       seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg));
+       tmp = RREG32(ring->wptr_reg) >> ring->ptr_reg_shift;
+       seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp);
+       tmp = RREG32(ring->rptr_reg) >> ring->ptr_reg_shift;
+       seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp);
        if (ring->rptr_save_reg) {
                seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,
                           RREG32(ring->rptr_save_reg));
        }
-       seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr);
-       seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr);
+       seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
+       seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
+       seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
+       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n", ring->last_semaphore_wait_addr);
        seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
        seq_printf(m, "%u dwords in ring\n", count);
-       i = ring->rptr;
-       for (j = 0; j <= count; j++) {
-               seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+       /* print 8 dw before current rptr as often it's the last executed
+        * packet that is the root issue
+        */
+       i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
+       for (j = 0; j <= (count + 32); j++) {
+               seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
                i = (i + 1) & ring->ptr_mask;
        }
        return 0;
@@ -794,11 +805,15 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 static int radeon_ring_type_gfx_index = RADEON_RING_TYPE_GFX_INDEX;
 static int cayman_ring_type_cp1_index = CAYMAN_RING_TYPE_CP1_INDEX;
 static int cayman_ring_type_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX;
+static int radeon_ring_type_dma1_index = R600_RING_TYPE_DMA_INDEX;
+static int radeon_ring_type_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX;
 
 static struct drm_info_list radeon_debugfs_ring_info_list[] = {
        {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_ring_type_gfx_index},
        {"radeon_ring_cp1", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp1_index},
        {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index},
+       {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma1_index},
+       {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_ring_type_dma2_index},
 };
 
 static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
index 97f3ece81cd257bba371c57d126bb54ddbfbee18..8dcc20f53d734ebe12b24f57b175e69988d93309 100644 (file)
@@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
        /* we assume caller has already allocated space on waiters ring */
        radeon_semaphore_emit_wait(rdev, waiter, semaphore);
 
+       /* for debugging lockup only, used by sysfs debug files */
+       rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr;
+       rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr;
+
        return 0;
 }
 
index 1d8ff2f850ba0d6d4a4a47c68913bc4cbb4392e7..93f760e27a9200a81b94dfee8ce6d14ac935b49a 100644 (file)
@@ -38,6 +38,7 @@
 #include <drm/radeon_drm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/swiotlb.h>
 #include "radeon_reg.h"
 #include "radeon.h"
 
index 0f656b111c15f913f6c09045f045b81bf016c2b2..a072fa8c46b04a00a9c78886b20a29615f7ad86c 100644 (file)
@@ -1,5 +1,6 @@
 cayman 0x9400
 0x0000802C GRBM_GFX_INDEX
+0x00008040 WAIT_UNTIL
 0x000084FC CP_STRMOUT_CNTL
 0x000085F0 CP_COHER_CNTL
 0x000085F4 CP_COHER_SIZE
index 911a8fbd32bb3fcafe37bd0179dd8fd28157e948..78d5e99d759da97426cdc548857971f3820e5427 100644 (file)
@@ -324,6 +324,8 @@ rv515 0x6d40
 0x46AC US_OUT_FMT_2
 0x46B0 US_OUT_FMT_3
 0x46B4 US_W_FMT
+0x46C0 RB3D_COLOR_CLEAR_VALUE_AR
+0x46C4 RB3D_COLOR_CLEAR_VALUE_GB
 0x4BC0 FG_FOG_BLEND
 0x4BC4 FG_FOG_FACTOR
 0x4BC8 FG_FOG_COLOR_R
index 2bb6d0e84b3d94361546d06705c5d3252b7126bf..435ed35513643b868907716b9b4a231de4d0a58c 100644 (file)
@@ -336,6 +336,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
                                WREG32(R600_CITF_CNTL, blackout);
                }
        }
+       /* wait for the MC to settle */
+       udelay(100);
 }
 
 void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
index 87c979c4f721c7e3c5a6ab757a29ef07bb6e9788..1b2444f4d8f4ffa7327fd24093704a594389b151 100644 (file)
@@ -887,6 +887,80 @@ static int rv770_mc_init(struct radeon_device *rdev)
        return 0;
 }
 
+/**
+ * rv770_copy_dma - copy pages using the DMA engine
+ *
+ * @rdev: radeon_device pointer
+ * @src_offset: src GPU address
+ * @dst_offset: dst GPU address
+ * @num_gpu_pages: number of GPU pages to xfer
+ * @fence: radeon fence object
+ *
+ * Copy GPU paging using the DMA engine (r7xx).
+ * Used by the radeon ttm implementation to move pages if
+ * registered as the asic copy callback.
+ */
+int rv770_copy_dma(struct radeon_device *rdev,
+                 uint64_t src_offset, uint64_t dst_offset,
+                 unsigned num_gpu_pages,
+                 struct radeon_fence **fence)
+{
+       struct radeon_semaphore *sem = NULL;
+       int ring_index = rdev->asic->copy.dma_ring_index;
+       struct radeon_ring *ring = &rdev->ring[ring_index];
+       u32 size_in_dw, cur_size_in_dw;
+       int i, num_loops;
+       int r = 0;
+
+       r = radeon_semaphore_create(rdev, &sem);
+       if (r) {
+               DRM_ERROR("radeon: moving bo (%d).\n", r);
+               return r;
+       }
+
+       size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4;
+       num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFF);
+       r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8);
+       if (r) {
+               DRM_ERROR("radeon: moving bo (%d).\n", r);
+               radeon_semaphore_free(rdev, &sem, NULL);
+               return r;
+       }
+
+       if (radeon_fence_need_sync(*fence, ring->idx)) {
+               radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+                                           ring->idx);
+               radeon_fence_note_sync(*fence, ring->idx);
+       } else {
+               radeon_semaphore_free(rdev, &sem, NULL);
+       }
+
+       for (i = 0; i < num_loops; i++) {
+               cur_size_in_dw = size_in_dw;
+               if (cur_size_in_dw > 0xFFFF)
+                       cur_size_in_dw = 0xFFFF;
+               size_in_dw -= cur_size_in_dw;
+               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw));
+               radeon_ring_write(ring, dst_offset & 0xfffffffc);
+               radeon_ring_write(ring, src_offset & 0xfffffffc);
+               radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff);
+               radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff);
+               src_offset += cur_size_in_dw * 4;
+               dst_offset += cur_size_in_dw * 4;
+       }
+
+       r = radeon_fence_emit(rdev, fence, ring->idx);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               return r;
+       }
+
+       radeon_ring_unlock_commit(rdev, ring);
+       radeon_semaphore_free(rdev, &sem, *fence);
+
+       return r;
+}
+
 static int rv770_startup(struct radeon_device *rdev)
 {
        struct radeon_ring *ring;
index ef683653f0b71be1be31cf0eb027c743eed707d8..ae8b48205a6c10257de328c0b669628436e8b0a0 100644 (file)
@@ -2126,15 +2126,13 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
        return radeon_ring_test_lockup(rdev, ring);
 }
 
-static int si_gpu_soft_reset(struct radeon_device *rdev)
+static void si_gpu_soft_reset_gfx(struct radeon_device *rdev)
 {
-       struct evergreen_mc_save save;
        u32 grbm_reset = 0;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return 0;
+               return;
 
-       dev_info(rdev->dev, "GPU softreset \n");
        dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
                RREG32(GRBM_STATUS));
        dev_info(rdev->dev, "  GRBM_STATUS2=0x%08X\n",
@@ -2145,10 +2143,7 @@ static int si_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
                RREG32(SRBM_STATUS));
-       evergreen_mc_stop(rdev, &save);
-       if (radeon_mc_wait_for_idle(rdev)) {
-               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
-       }
+
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
 
@@ -2173,8 +2168,7 @@ static int si_gpu_soft_reset(struct radeon_device *rdev)
        udelay(50);
        WREG32(GRBM_SOFT_RESET, 0);
        (void)RREG32(GRBM_SOFT_RESET);
-       /* Wait a little for things to settle down */
-       udelay(50);
+
        dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
                RREG32(GRBM_STATUS));
        dev_info(rdev->dev, "  GRBM_STATUS2=0x%08X\n",
@@ -2185,13 +2179,81 @@ static int si_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
                RREG32(SRBM_STATUS));
+}
+
+static void si_gpu_soft_reset_dma(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               return;
+
+       dev_info(rdev->dev, "  DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       dev_info(rdev->dev, "  DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+}
+
+static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+{
+       struct evergreen_mc_save save;
+
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
+       if (reset_mask == 0)
+               return 0;
+
+       dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
+
+       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
+                RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR));
+       dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+                RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
+
+       evergreen_mc_stop(rdev, &save);
+       if (radeon_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
+               si_gpu_soft_reset_gfx(rdev);
+
+       if (reset_mask & RADEON_RESET_DMA)
+               si_gpu_soft_reset_dma(rdev);
+
+       /* Wait a little for things to settle down */
+       udelay(50);
+
        evergreen_mc_resume(rdev, &save);
        return 0;
 }
 
 int si_asic_reset(struct radeon_device *rdev)
 {
-       return si_gpu_soft_reset(rdev);
+       return si_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
+                                       RADEON_RESET_COMPUTE |
+                                       RADEON_RESET_DMA));
 }
 
 /* MC */
index 62b46215d423a785ca481aa00da188217450f9da..c056aae814f090693a4eb445d83d3ca2be30efd7 100644 (file)
 
 #define        SRBM_STATUS                                     0xE50
 
+#define        SRBM_SOFT_RESET                                 0x0E60
+#define                SOFT_RESET_BIF                          (1 << 1)
+#define                SOFT_RESET_DC                           (1 << 5)
+#define                SOFT_RESET_DMA1                         (1 << 6)
+#define                SOFT_RESET_GRBM                         (1 << 8)
+#define                SOFT_RESET_HDP                          (1 << 9)
+#define                SOFT_RESET_IH                           (1 << 10)
+#define                SOFT_RESET_MC                           (1 << 11)
+#define                SOFT_RESET_ROM                          (1 << 14)
+#define                SOFT_RESET_SEM                          (1 << 15)
+#define                SOFT_RESET_VMC                          (1 << 17)
+#define                SOFT_RESET_DMA                          (1 << 20)
+#define                SOFT_RESET_TST                          (1 << 21)
+#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_ORB                          (1 << 23)
+
 #define        CC_SYS_RB_BACKEND_DISABLE                       0xe80
 #define        GC_USER_SYS_RB_BACKEND_DISABLE                  0xe84
 
 #       define DATA_SWAP_ENABLE                           (1 << 3)
 #       define FENCE_SWAP_ENABLE                          (1 << 4)
 #       define CTXEMPTY_INT_ENABLE                        (1 << 28)
+#define DMA_STATUS_REG                                    0xd034
+#       define DMA_IDLE                                   (1 << 0)
 #define DMA_TILING_CONFIG                                0xd0b8
 
 #define DMA_PACKET(cmd, b, t, s, n)    ((((cmd) & 0xF) << 28) |        \
index 1c350fc4e449715edd5ef997e6eb791722d0f604..d1d5306ebf24a6a6f563cdc7a7c3e0af375b72e4 100644 (file)
@@ -33,7 +33,7 @@
  * Hardware initialization
  */
 
-static int __devinit shmob_drm_init_interface(struct shmob_drm_device *sdev)
+static int shmob_drm_init_interface(struct shmob_drm_device *sdev)
 {
        static const u32 ldmt1r[] = {
                [SHMOB_DRM_IFACE_RGB8] = LDMT1R_MIFTYP_RGB8,
@@ -67,7 +67,7 @@ static int __devinit shmob_drm_init_interface(struct shmob_drm_device *sdev)
        return 0;
 }
 
-static int __devinit shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
+static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
                                            enum shmob_drm_clk_source clksrc)
 {
        struct clk *clk;
@@ -330,12 +330,12 @@ static const struct dev_pm_ops shmob_drm_pm_ops = {
  * Platform driver
  */
 
-static int __devinit shmob_drm_probe(struct platform_device *pdev)
+static int shmob_drm_probe(struct platform_device *pdev)
 {
        return drm_platform_init(&shmob_drm_driver, pdev);
 }
 
-static int __devexit shmob_drm_remove(struct platform_device *pdev)
+static int shmob_drm_remove(struct platform_device *pdev)
 {
        drm_platform_exit(&shmob_drm_driver, pdev);
 
@@ -344,7 +344,7 @@ static int __devexit shmob_drm_remove(struct platform_device *pdev)
 
 static struct platform_driver shmob_drm_platform_driver = {
        .probe          = shmob_drm_probe,
-       .remove         = __devexit_p(shmob_drm_remove),
+       .remove         = shmob_drm_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "shmob-drm",
index 074410371e2a40e4af77ce196069473a53b8860f..656b2e3334a621109426806043032ae3422d9631 100644 (file)
@@ -102,12 +102,12 @@ static int tegra_dc_set_timings(struct tegra_dc *dc,
                ((mode->hsync_end - mode->hsync_start) <<  0);
        tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
 
-       value = ((mode->vsync_start - mode->vdisplay) << 16) |
-               ((mode->hsync_start - mode->hdisplay) <<  0);
-       tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
-
        value = ((mode->vtotal - mode->vsync_end) << 16) |
                ((mode->htotal - mode->hsync_end) <<  0);
+       tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
+
+       value = ((mode->vsync_start - mode->vdisplay) << 16) |
+               ((mode->hsync_start - mode->hdisplay) <<  0);
        tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
 
        value = (mode->vdisplay << 16) | mode->hdisplay;
@@ -221,8 +221,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
        win.stride = crtc->fb->pitches[0];
 
        /* program window registers */
-       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_WINDOW_HEADER);
-       value |= WINDOW_A_SELECT;
+       value = WINDOW_A_SELECT;
        tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
 
        tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH);
index 3a843a77ddc7cfeeeb556011c0f5049d6cfd7bfa..741b5dc2742cc7498fb3f763c273da81885222ba 100644 (file)
@@ -204,24 +204,6 @@ extern int tegra_output_parse_dt(struct tegra_output *output);
 extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
 extern int tegra_output_exit(struct tegra_output *output);
 
-/* from gem.c */
-extern struct tegra_gem_object *tegra_gem_alloc(struct drm_device *drm,
-                                               size_t size);
-extern int tegra_gem_handle_create(struct drm_device *drm,
-                                  struct drm_file *file, size_t size,
-                                  unsigned long flags, uint32_t *handle);
-extern int tegra_gem_dumb_create(struct drm_file *file, struct drm_device *drm,
-                                struct drm_mode_create_dumb *args);
-extern int tegra_gem_dumb_map_offset(struct drm_file *file,
-                                    struct drm_device *drm, uint32_t handle,
-                                    uint64_t *offset);
-extern int tegra_gem_dumb_destroy(struct drm_file *file,
-                                 struct drm_device *drm, uint32_t handle);
-extern int tegra_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
-extern int tegra_gem_init_object(struct drm_gem_object *obj);
-extern void tegra_gem_free_object(struct drm_gem_object *obj);
-extern struct vm_operations_struct tegra_gem_vm_ops;
-
 /* from fb.c */
 extern int tegra_drm_fb_init(struct drm_device *drm);
 extern void tegra_drm_fb_exit(struct drm_device *drm);
index ab4016412bbfea48079ca0d197fd4a85c3fbaf3b..e060c7e6434dba886e8698782cbfb0c3ce4b9cf7 100644 (file)
@@ -149,7 +149,7 @@ struct tmds_config {
 };
 
 static const struct tmds_config tegra2_tmds_config[] = {
-       { /* 480p modes */
+       { /* slow pixel clock modes */
                .pclk = 27000000,
                .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
                        SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
@@ -163,21 +163,8 @@ static const struct tmds_config tegra2_tmds_config[] = {
                        DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
                        DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
                        DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
-       }, { /* 720p modes */
-               .pclk = 74250000,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
-                       SOR_PLL_TX_REG_LOAD(3),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
-               .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_6_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
-       }, { /* 1080p modes */
+       },
+       { /* high pixel clock modes */
                .pclk = UINT_MAX,
                .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
                        SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
@@ -479,7 +466,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
                return;
        }
 
-       h_front_porch = mode->htotal - mode->hsync_end;
+       h_front_porch = mode->hsync_start - mode->hdisplay;
        memset(&frame, 0, sizeof(frame));
        frame.r = HDMI_AVI_R_SAME;
 
@@ -634,8 +621,8 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
 
        pclk = mode->clock * 1000;
        h_sync_width = mode->hsync_end - mode->hsync_start;
-       h_front_porch = mode->htotal - mode->hsync_end;
-       h_back_porch = mode->hsync_start - mode->hdisplay;
+       h_back_porch = mode->htotal - mode->hsync_end;
+       h_front_porch = mode->hsync_start - mode->hdisplay;
 
        err = regulator_enable(hdmi->vdd);
        if (err < 0) {
index bdb97a564d8201fd6dc367eb15dd65551fef3cdd..5d17b113a6fc7d2618e409c735c4273d3ade6c8a 100644 (file)
@@ -239,6 +239,8 @@ int host1x_register_client(struct host1x *host1x, struct host1x_client *client)
                }
        }
 
+       client->host1x = host1x;
+
        return 0;
 }
 
index 33d20be87db5f4e6070a5c20fe114816b88e7efe..52b20b12c83a3859da1b5fbbc1449fd3d4e907a4 100644 (file)
@@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
                        bo->mem = tmp_mem;
                        bdev->driver->move_notify(bo, mem);
                        bo->mem = *mem;
+                       *mem = tmp_mem;
                }
 
                goto out_err;
index 9e9c5d2a5c748a910fcd29a856c128d25a4f8ae0..8be35c809c7b612c5a33bc5271051273bd58cd92 100644 (file)
@@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 
        if (ttm->state == tt_unpopulated) {
                ret = ttm->bdev->driver->ttm_tt_populate(ttm);
-               if (ret)
+               if (ret) {
+                       /* if we fail here don't nuke the mm node
+                        * as the bo still owns it */
+                       old_copy.mm_node = NULL;
                        goto out1;
+               }
        }
 
        add = 0;
@@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
                                                   prot);
                } else
                        ret = ttm_copy_io_page(new_iomap, old_iomap, page);
-               if (ret)
+               if (ret) {
+                       /* failing here, means keep old copy as-is */
+                       old_copy.mm_node = NULL;
                        goto out1;
+               }
        }
        mb();
 out2:
@@ -422,7 +429,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        struct ttm_bo_device *bdev = bo->bdev;
        struct ttm_bo_driver *driver = bdev->driver;
 
-       fbo = kzalloc(sizeof(*fbo), GFP_KERNEL);
+       fbo = kmalloc(sizeof(*fbo), GFP_KERNEL);
        if (!fbo)
                return -ENOMEM;
 
@@ -441,7 +448,12 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        fbo->vm_node = NULL;
        atomic_set(&fbo->cpu_writers, 0);
 
-       fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+       spin_lock(&bdev->fence_lock);
+       if (bo->sync_obj)
+               fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+       else
+               fbo->sync_obj = NULL;
+       spin_unlock(&bdev->fence_lock);
        kref_init(&fbo->list_kref);
        kref_init(&fbo->kref);
        fbo->destroy = &ttm_transfered_destroy;
index 512f44add89f41fae6706114c5ce497279a4f107..fe5cdbcf263605b7b5ec853b4d5f354f7c754b13 100644 (file)
 static u8 *udl_get_edid(struct udl_device *udl)
 {
        u8 *block;
-       char rbuf[3];
+       char *rbuf;
        int ret, i;
 
        block = kmalloc(EDID_LENGTH, GFP_KERNEL);
        if (block == NULL)
                return NULL;
 
+       rbuf = kmalloc(2, GFP_KERNEL);
+       if (rbuf == NULL)
+               goto error;
+
        for (i = 0; i < EDID_LENGTH; i++) {
                ret = usb_control_msg(udl->ddev->usbdev,
                                      usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02),
@@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl)
                                      HZ);
                if (ret < 1) {
                        DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
-                       i--;
                        goto error;
                }
                block[i] = rbuf[1];
        }
 
+       kfree(rbuf);
        return block;
 
 error:
        kfree(block);
+       kfree(rbuf);
        return NULL;
 }
 
@@ -57,6 +62,14 @@ static int udl_get_modes(struct drm_connector *connector)
 
        edid = (struct edid *)udl_get_edid(udl);
 
+       /*
+        * We only read the main block, but if the monitor reports extension
+        * blocks then the drm edid code expects them to be present, so patch
+        * the extension count to 0.
+        */
+       edid->checksum += edid->extensions;
+       edid->extensions = 0;
+
        drm_mode_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
        kfree(edid);
index 4dfa605e2d14417203e734c4a68dc2447e86f5c2..34e25471aeaaaa547f1e4ea1a1879426d7350444 100644 (file)
 #define USB_VENDOR_ID_EZKEY            0x0518
 #define USB_DEVICE_ID_BTC_8193         0x0002
 
+#define USB_VENDOR_ID_FORMOSA          0x147a
+#define USB_DEVICE_ID_FORMOSA_IR_RECEIVER      0xe03e
+
 #define USB_VENDOR_ID_FREESCALE                0x15A2
 #define USB_DEVICE_ID_FREESCALE_MX28   0x004F
 
index 9ef222442ca0e989438ec3695ab473fc427339f3..e766b5614ef59fcae45aaeff49a98df9de3e9693 100644 (file)
@@ -540,13 +540,24 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 {
        struct i2c_client *client = hid->driver_data;
        int report_id = buf[0];
+       int ret;
 
        if (report_type == HID_INPUT_REPORT)
                return -EINVAL;
 
-       return i2c_hid_set_report(client,
+       if (report_id) {
+               buf++;
+               count--;
+       }
+
+       ret = i2c_hid_set_report(client,
                                report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
                                report_id, buf, count);
+
+       if (report_id && ret >= 0)
+               ret++; /* add report_id to the number of transfered bytes */
+
+       return ret;
 }
 
 static int i2c_hid_parse(struct hid_device *hid)
@@ -731,7 +742,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
        .hidinput_input_event = i2c_hid_hidinput_input_event,
 };
 
-static int __devinit i2c_hid_init_irq(struct i2c_client *client)
+static int i2c_hid_init_irq(struct i2c_client *client)
 {
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        int ret;
@@ -753,7 +764,7 @@ static int __devinit i2c_hid_init_irq(struct i2c_client *client)
        return 0;
 }
 
-static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
+static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
 {
        struct i2c_client *client = ihid->client;
        struct i2c_hid_desc *hdesc = &ihid->hdesc;
@@ -810,8 +821,8 @@ static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
        return 0;
 }
 
-static int __devinit i2c_hid_probe(struct i2c_client *client,
-               const struct i2c_device_id *dev_id)
+static int i2c_hid_probe(struct i2c_client *client,
+                        const struct i2c_device_id *dev_id)
 {
        int ret;
        struct i2c_hid *ihid;
@@ -902,7 +913,7 @@ err:
        return ret;
 }
 
-static int __devexit i2c_hid_remove(struct i2c_client *client)
+static int i2c_hid_remove(struct i2c_client *client)
 {
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid;
@@ -967,7 +978,7 @@ static struct i2c_driver i2c_hid_driver = {
        },
 
        .probe          = i2c_hid_probe,
-       .remove         = __devexit_p(i2c_hid_remove),
+       .remove         = i2c_hid_remove,
 
        .id_table       = i2c_hid_id_table,
 };
index ac9e35228254f0e6a942845520bb542752ca0921..e0e6abf1cd3bd9b3cfa3d7cc73a2247c84c31be4 100644 (file)
@@ -70,6 +70,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
index 3ad91f6447d8eee319e570f4098a2fb75f9be49e..e61e5f991aa538831644c5c1d1f13e5f71a69334 100644 (file)
@@ -675,7 +675,7 @@ static const struct file_operations hsc_fops = {
        .release        = hsc_release,
 };
 
-static void __devinit hsc_channel_init(struct hsc_channel *channel)
+static void hsc_channel_init(struct hsc_channel *channel)
 {
        init_waitqueue_head(&channel->rx_wait);
        init_waitqueue_head(&channel->tx_wait);
@@ -685,7 +685,7 @@ static void __devinit hsc_channel_init(struct hsc_channel *channel)
        INIT_LIST_HEAD(&channel->tx_msgs_queue);
 }
 
-static int __devinit hsc_probe(struct device *dev)
+static int hsc_probe(struct device *dev)
 {
        const char devname[] = "hsi_char";
        struct hsc_client_data *cl_data;
@@ -744,7 +744,7 @@ out1:
        return ret;
 }
 
-static int __devexit hsc_remove(struct device *dev)
+static int hsc_remove(struct device *dev)
 {
        struct hsi_client *cl = to_hsi_client(dev);
        struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
@@ -763,7 +763,7 @@ static struct hsi_client_driver hsc_driver = {
                .name   = "hsi_char",
                .owner  = THIS_MODULE,
                .probe  = hsc_probe,
-               .remove = __devexit_p(hsc_remove),
+               .remove = hsc_remove,
        },
 };
 
index f6c0011a0337e53ff783837a0970a2002675ddb5..dd289fd179ca8e3953b3d8f2d0b65c94fb5b878e 100644 (file)
@@ -403,7 +403,7 @@ struct dm_info_header {
  */
 
 struct dm_info_msg {
-       struct dm_info_header header;
+       struct dm_header hdr;
        __u32 reserved;
        __u32 info_size;
        __u8  info[];
@@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg)
 
 static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
 {
-       switch (msg->header.type) {
+       struct dm_info_header *info_hdr;
+
+       info_hdr = (struct dm_info_header *)msg->info;
+
+       switch (info_hdr->type) {
        case INFO_TYPE_MAX_PAGE_CNT:
                pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
-               pr_info("Data Size is %d\n", msg->header.data_size);
+               pr_info("Data Size is %d\n", info_hdr->data_size);
                break;
        default:
-               pr_info("Received Unknown type: %d\n", msg->header.type);
+               pr_info("Received Unknown type: %d\n", info_hdr->type);
        }
 }
 
@@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev,
                        balloon_onchannelcallback, dev);
 
        if (ret)
-               return ret;
+               goto probe_error0;
 
        dm_device.dev = dev;
        dm_device.state = DM_INITIALIZING;
@@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev,
                 kthread_run(dm_thread_func, &dm_device, "hv_balloon");
        if (IS_ERR(dm_device.thread)) {
                ret = PTR_ERR(dm_device.thread);
-               goto probe_error0;
+               goto probe_error1;
        }
 
        hv_set_drvdata(dev, &dm_device);
@@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev,
                                VM_PKT_DATA_INBAND,
                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
        if (ret)
-               goto probe_error1;
+               goto probe_error2;
 
        t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
        if (t == 0) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        /*
@@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev,
         */
        if (dm_device.state == DM_INIT_ERROR) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
        /*
         * Now submit our capabilities to the host.
@@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev,
                                VM_PKT_DATA_INBAND,
                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
        if (ret)
-               goto probe_error1;
+               goto probe_error2;
 
        t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
        if (t == 0) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        /*
@@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev,
         */
        if (dm_device.state == DM_INIT_ERROR) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        dm_device.state = DM_INITIALIZED;
 
        return 0;
 
-probe_error1:
+probe_error2:
        kthread_stop(dm_device.thread);
 
-probe_error0:
+probe_error1:
        vmbus_close(dev->channel);
+probe_error0:
+       kfree(send_buffer);
        return ret;
 }
 
@@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev)
 
        vmbus_close(dev->channel);
        kthread_stop(dm->thread);
+       kfree(send_buffer);
 
        return 0;
 }
index a98c917b5888f219ad219ebb7ed7b20d7d937dea..789bd4fb329b9b2eeca82b07751ab538b5c19e9a 100644 (file)
@@ -187,7 +187,7 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev)
  * Sysfs callback functions
  */
 
-static const u16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 };
+static const s16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 };
 
 static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
        char *buf)
index 8fa2632cbbaf7b8f817cfe24a46e176f092646fb..7272176a9ec786c397b6427d43ac42b10ff80fb2 100644 (file)
@@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
        struct i2c_client *client = to_i2c_client(dev);
        long temp;
        short value;
+       s32 err;
 
        int status = kstrtol(buf, 10, &temp);
        if (status < 0)
@@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
        /* Write value */
        value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
                (LM73_TEMP_MAX*4)) << 5;
-       i2c_smbus_write_word_swapped(client, attr->index, value);
-       return count;
+       err = i2c_smbus_write_word_swapped(client, attr->index, value);
+       return (err < 0) ? err : count;
 }
 
 static ssize_t show_temp(struct device *dev, struct device_attribute *da,
@@ -66,11 +67,16 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct i2c_client *client = to_i2c_client(dev);
+       int temp;
+
+       s32 err = i2c_smbus_read_word_swapped(client, attr->index);
+       if (err < 0)
+               return err;
+
        /* use integer division instead of equivalent right shift to
           guarantee arithmetic shift and preserve the sign */
-       int temp = ((s16) (i2c_smbus_read_word_swapped(client,
-                   attr->index))*250) / 32;
-       return sprintf(buf, "%d\n", temp);
+       temp = (((s16) err) * 250) / 32;
+       return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
 
 
index 59fd1268e58ae6703e3bd372f5d510dcd1344f18..d867e6bb2be1f7e1b1ebb41788c27f568bd7c579 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/vexpress.h>
@@ -196,7 +197,7 @@ error:
        return err;
 }
 
-static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
+static int vexpress_hwmon_remove(struct platform_device *pdev)
 {
        struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
        const struct of_device_id *match;
@@ -213,7 +214,7 @@ static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
 
 static struct platform_driver vexpress_hwmon_driver = {
        .probe = vexpress_hwmon_probe,
-       .remove = __devexit_p(vexpress_hwmon_remove),
+       .remove = vexpress_hwmon_remove,
        .driver = {
                .name = DRVNAME,
                .owner = THIS_MODULE,
index 125cd8e0ad25c69c1206298d421e74da48284efe..3f491815e2c4759a5d0b7d850de20abeafe42381 100644 (file)
@@ -139,7 +139,7 @@ static unsigned short ali1535_offset;
    Note the differences between kernels with the old PCI BIOS interface and
    newer kernels with the real PCI interface. In compat.h some things are
    defined to make the transition easier. */
-static int __devinit ali1535_setup(struct pci_dev *dev)
+static int ali1535_setup(struct pci_dev *dev)
 {
        int retval;
        unsigned char temp;
@@ -502,7 +502,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = {
 
 MODULE_DEVICE_TABLE(pci, ali1535_ids);
 
-static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        if (ali1535_setup(dev)) {
                dev_warn(&dev->dev,
@@ -518,7 +518,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
        return i2c_add_adapter(&ali1535_adapter);
 }
 
-static void __devexit ali1535_remove(struct pci_dev *dev)
+static void ali1535_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&ali1535_adapter);
        release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
@@ -528,7 +528,7 @@ static struct pci_driver ali1535_driver = {
        .name           = "ali1535_smbus",
        .id_table       = ali1535_ids,
        .probe          = ali1535_probe,
-       .remove         = __devexit_p(ali1535_remove),
+       .remove         = ali1535_remove,
 };
 
 module_pci_driver(ali1535_driver);
index e02d9f86c6a0ad22a573f18b6f371cd1b2f1fc25..84ccd9496a5e91934e197f49192cf5a54fc492ef 100644 (file)
@@ -326,7 +326,7 @@ static u32 ali1563_func(struct i2c_adapter * a)
 }
 
 
-static int __devinit ali1563_setup(struct pci_dev * dev)
+static int ali1563_setup(struct pci_dev *dev)
 {
        u16 ctrl;
 
@@ -390,8 +390,8 @@ static struct i2c_adapter ali1563_adapter = {
        .algo   = &ali1563_algorithm,
 };
 
-static int __devinit ali1563_probe(struct pci_dev * dev,
-                               const struct pci_device_id * id_table)
+static int ali1563_probe(struct pci_dev *dev,
+                        const struct pci_device_id *id_table)
 {
        int error;
 
@@ -411,7 +411,7 @@ exit:
        return error;
 }
 
-static void __devexit ali1563_remove(struct pci_dev * dev)
+static void ali1563_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&ali1563_adapter);
        ali1563_shutdown(dev);
@@ -428,7 +428,7 @@ static struct pci_driver ali1563_pci_driver = {
        .name           = "ali1563_smbus",
        .id_table       = ali1563_id_table,
        .probe          = ali1563_probe,
-       .remove         = __devexit_p(ali1563_remove),
+       .remove         = ali1563_remove,
 };
 
 module_pci_driver(ali1563_pci_driver);
index ce8d26d053a5650434ee63fc31831b11278150b9..26bcc6127cee62c1b12749944af43af76ae3b908 100644 (file)
@@ -131,7 +131,7 @@ MODULE_PARM_DESC(force_addr,
 static struct pci_driver ali15x3_driver;
 static unsigned short ali15x3_smba;
 
-static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev)
+static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
 {
        u16 a;
        unsigned char temp;
@@ -484,7 +484,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = {
 
 MODULE_DEVICE_TABLE (pci, ali15x3_ids);
 
-static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        if (ali15x3_setup(dev)) {
                dev_err(&dev->dev,
@@ -500,7 +500,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
        return i2c_add_adapter(&ali15x3_adapter);
 }
 
-static void __devexit ali15x3_remove(struct pci_dev *dev)
+static void ali15x3_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&ali15x3_adapter);
        release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
@@ -510,7 +510,7 @@ static struct pci_driver ali15x3_driver = {
        .name           = "ali15x3_smbus",
        .id_table       = ali15x3_ids,
        .probe          = ali15x3_probe,
-       .remove         = __devexit_p(ali15x3_remove),
+       .remove         = ali15x3_remove,
 };
 
 module_pci_driver(ali15x3_driver);
index 304aa03b57b25f5efca7f771ba7f5a4a7cbece41..e13e2aa2d05d9fb379299fdd84635742cf37efba 100644 (file)
@@ -324,8 +324,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = {
 
 MODULE_DEVICE_TABLE (pci, amd756_ids);
 
-static int __devinit amd756_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id)
+static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int nforce = (id->driver_data == NFORCE);
        int error;
@@ -397,7 +396,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
        return error;
 }
 
-static void __devexit amd756_remove(struct pci_dev *dev)
+static void amd756_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&amd756_smbus);
        release_region(amd756_ioport, SMB_IOSIZE);
@@ -407,7 +406,7 @@ static struct pci_driver amd756_driver = {
        .name           = "amd756_smbus",
        .id_table       = amd756_ids,
        .probe          = amd756_probe,
-       .remove         = __devexit_p(amd756_remove),
+       .remove         = amd756_remove,
 };
 
 module_pci_driver(amd756_driver);
index 0919ac1d99aacab197bbecf13ef944f4b88d4074..a44e6e77c5a1d1e55dde1a326c67c6ad1cf39dd2 100644 (file)
@@ -422,8 +422,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = {
 
 MODULE_DEVICE_TABLE (pci, amd8111_ids);
 
-static int __devinit amd8111_probe(struct pci_dev *dev,
-               const struct pci_device_id *id)
+static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct amd_smbus *smbus;
        int error;
@@ -475,7 +474,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
        return error;
 }
 
-static void __devexit amd8111_remove(struct pci_dev *dev)
+static void amd8111_remove(struct pci_dev *dev)
 {
        struct amd_smbus *smbus = pci_get_drvdata(dev);
 
@@ -488,7 +487,7 @@ static struct pci_driver amd8111_driver = {
        .name           = "amd8111_smbus2",
        .id_table       = amd8111_ids,
        .probe          = amd8111_probe,
-       .remove         = __devexit_p(amd8111_remove),
+       .remove         = amd8111_remove,
 };
 
 module_pci_driver(amd8111_driver);
index b4575ee4bdf35923fabe292f1163916fbbc97e62..2bfc04d0a1b16b4eae2b3bc112218addfb6c2bf9 100644 (file)
@@ -145,7 +145,7 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
  * Calculate symmetric clock as stated in datasheet:
  * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
  */
-static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
+static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 {
        int ckdiv, cdiv, div;
        struct at91_twi_pdata *pdata = dev->pdata;
@@ -604,7 +604,7 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
 #define atmel_twi_dt_ids NULL
 #endif
 
-static bool __devinit filter(struct dma_chan *chan, void *slave)
+static bool filter(struct dma_chan *chan, void *slave)
 {
        struct at_dma_slave *sl = slave;
 
@@ -616,7 +616,7 @@ static bool __devinit filter(struct dma_chan *chan, void *slave)
        }
 }
 
-static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
+static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
 {
        int ret = 0;
        struct at_dma_slave *sdata;
@@ -688,7 +688,7 @@ error:
        return ret;
 }
 
-static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
+static struct at91_twi_pdata *at91_twi_get_driver_data(
                                        struct platform_device *pdev)
 {
        if (pdev->dev.of_node) {
@@ -701,7 +701,7 @@ static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
        return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
 }
 
-static int __devinit at91_twi_probe(struct platform_device *pdev)
+static int at91_twi_probe(struct platform_device *pdev)
 {
        struct at91_twi_dev *dev;
        struct resource *mem;
@@ -779,7 +779,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit at91_twi_remove(struct platform_device *pdev)
+static int at91_twi_remove(struct platform_device *pdev)
 {
        struct at91_twi_dev *dev = platform_get_drvdata(pdev);
        int rc;
@@ -820,7 +820,7 @@ static const struct dev_pm_ops at91_twi_pm = {
 
 static struct platform_driver at91_twi_driver = {
        .probe          = at91_twi_probe,
-       .remove         = __devexit_p(at91_twi_remove),
+       .remove         = at91_twi_remove,
        .id_table       = at91_twi_devtypes,
        .driver         = {
                .name   = "at91_i2c",
index 582d616db34615611c4783525cbfc46bccf37351..b278298787d78b9687b99e2f148b80d17dcc4d29 100644 (file)
@@ -313,7 +313,7 @@ static void i2c_au1550_disable(struct i2c_au1550_data *priv)
  * Prior to calling us, the 50MHz clock frequency and routing
  * must have been set up for the PSC indicated by the adapter.
  */
-static int __devinit
+static int
 i2c_au1550_probe(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv;
@@ -372,7 +372,7 @@ out:
        return ret;
 }
 
-static int __devexit i2c_au1550_remove(struct platform_device *pdev)
+static int i2c_au1550_remove(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
 
@@ -423,7 +423,7 @@ static struct platform_driver au1xpsc_smbus_driver = {
                .pm     = AU1XPSC_SMBUS_PMOPS,
        },
        .probe          = i2c_au1550_probe,
-       .remove         = __devexit_p(i2c_au1550_remove),
+       .remove         = i2c_au1550_remove,
 };
 
 module_platform_driver(au1xpsc_smbus_driver);
index c1e1096ba06936a08cb60950123d67fdf59b3e96..2e79c1024191dc9084f066478be02f3edbaa288c 100644 (file)
@@ -426,7 +426,7 @@ static const struct i2c_adapter cpm_ops = {
        .algo           = &cpm_i2c_algo,
 };
 
-static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
+static int cpm_i2c_setup(struct cpm_i2c *cpm)
 {
        struct platform_device *ofdev = cpm->ofdev;
        const u32 *data;
@@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
                cpm_muram_free(cpm->i2c_addr);
 }
 
-static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
+static int cpm_i2c_probe(struct platform_device *ofdev)
 {
        int result, len;
        struct cpm_i2c *cpm;
@@ -688,7 +688,7 @@ out_free:
        return result;
 }
 
-static int __devexit cpm_i2c_remove(struct platform_device *ofdev)
+static int cpm_i2c_remove(struct platform_device *ofdev)
 {
        struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev);
 
@@ -716,7 +716,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match);
 
 static struct platform_driver cpm_i2c_driver = {
        .probe          = cpm_i2c_probe,
-       .remove         = __devexit_p(cpm_i2c_remove),
+       .remove         = cpm_i2c_remove,
        .driver = {
                .name = "fsl-i2c-cpm",
                .owner = THIS_MODULE,
index cbba7db9ad594df3cd10a37e6fa8b16fc456f817..f5258c205de555ec569f5a8c967531577336344c 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include "i2c-designware-core.h"
 
 /*
@@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
        return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
 EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
+
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
+MODULE_LICENSE("GPL");
index 92a1e2c15baad8e3875337cde50dc132acd06a7d..6add851e9dee2f44c4e6cd7538a8d458543b5d84 100644 (file)
@@ -207,7 +207,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
        return dev->controller->clk_khz;
 }
 
-static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+static int i2c_dw_pci_probe(struct pci_dev *pdev,
 const struct pci_device_id *id)
 {
        struct dw_i2c_dev *dev;
@@ -328,7 +328,7 @@ exit:
        return r;
 }
 
-static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+static void i2c_dw_pci_remove(struct pci_dev *pdev)
 {
        struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
 
@@ -368,7 +368,7 @@ static struct pci_driver dw_i2c_driver = {
        .name           = DRIVER_NAME,
        .id_table       = i2_designware_pci_ids,
        .probe          = i2c_dw_pci_probe,
-       .remove         = __devexit_p(i2c_dw_pci_remove),
+       .remove         = i2c_dw_pci_remove,
        .driver         = {
                .pm     = &i2c_dw_pm_ops,
        },
index 0506fef8dc001ed8a8bb026ed9cae3674309d5ce..343357a2b5b42fda96d27d2f3514a183e0bd901f 100644 (file)
@@ -50,7 +50,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
        return clk_get_rate(dev->clk)/1000;
 }
 
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
+static int dw_i2c_probe(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev;
        struct i2c_adapter *adap;
@@ -169,7 +169,7 @@ err_release_region:
        return r;
 }
 
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
+static int dw_i2c_remove(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
        struct resource *mem;
@@ -228,7 +228,7 @@ static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
 MODULE_ALIAS("platform:i2c_designware");
 
 static struct platform_driver dw_i2c_driver = {
-       .remove         = __devexit_p(dw_i2c_remove),
+       .remove         = dw_i2c_remove,
        .driver         = {
                .name   = "i2c_designware",
                .owner  = THIS_MODULE,
index 259f7697bf25388085e9efd2bbd5a57e78943962..5e7886e7136e5f3858fc9361fc9c2a7cdf4a598b 100644 (file)
@@ -758,7 +758,7 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
        iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK);
 }
 
-static int __devinit pch_i2c_probe(struct pci_dev *pdev,
+static int pch_i2c_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *id)
 {
        void __iomem *base_addr;
@@ -851,7 +851,7 @@ err_pci_enable:
        return ret;
 }
 
-static void __devexit pch_i2c_remove(struct pci_dev *pdev)
+static void pch_i2c_remove(struct pci_dev *pdev)
 {
        int i;
        struct adapter_info *adap_info = pci_get_drvdata(pdev);
@@ -948,7 +948,7 @@ static struct pci_driver pch_pcidriver = {
        .name = KBUILD_MODNAME,
        .id_table = pch_pcidev_id,
        .probe = pch_i2c_probe,
-       .remove = __devexit_p(pch_i2c_remove),
+       .remove = pch_i2c_remove,
        .suspend = pch_i2c_suspend,
        .resume = pch_i2c_resume
 };
index 37e2e82a9c8876d9344b66b040c26e139fd625e7..485497066ed7abca4df32b602b17f1e72b455a73 100644 (file)
@@ -205,7 +205,7 @@ static struct i2c_adapter pcf_isa_ops = {
        .name           = "i2c-elektor",
 };
 
-static int __devinit elektor_match(struct device *dev, unsigned int id)
+static int elektor_match(struct device *dev, unsigned int id)
 {
 #ifdef __alpha__
        /* check to see we have memory mapped PCF8584 connected to the
@@ -264,7 +264,7 @@ static int __devinit elektor_match(struct device *dev, unsigned int id)
        return 1;
 }
 
-static int __devinit elektor_probe(struct device *dev, unsigned int id)
+static int elektor_probe(struct device *dev, unsigned int id)
 {
        init_waitqueue_head(&pcf_wait);
        if (pcf_isa_init())
@@ -293,7 +293,7 @@ static int __devinit elektor_probe(struct device *dev, unsigned int id)
        return -ENODEV;
 }
 
-static int __devexit elektor_remove(struct device *dev, unsigned int id)
+static int elektor_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pcf_isa_ops);
 
@@ -316,7 +316,7 @@ static int __devexit elektor_remove(struct device *dev, unsigned int id)
 static struct isa_driver i2c_elektor_driver = {
        .match          = elektor_match,
        .probe          = elektor_probe,
-       .remove         = __devexit_p(elektor_remove),
+       .remove         = elektor_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "i2c-elektor",
index 257299a92df3cad926707343aeebf60cf698cd4d..f3fa4332bbdf9fa93ad497002fee91ab858d06ee 100644 (file)
@@ -85,7 +85,7 @@ static int i2c_gpio_getscl(void *data)
        return gpio_get_value(pdata->scl_pin);
 }
 
-static int __devinit of_i2c_gpio_probe(struct device_node *np,
+static int of_i2c_gpio_probe(struct device_node *np,
                             struct i2c_gpio_platform_data *pdata)
 {
        u32 reg;
@@ -117,7 +117,7 @@ static int __devinit of_i2c_gpio_probe(struct device_node *np,
        return 0;
 }
 
-static int __devinit i2c_gpio_probe(struct platform_device *pdev)
+static int i2c_gpio_probe(struct platform_device *pdev)
 {
        struct i2c_gpio_private_data *priv;
        struct i2c_gpio_platform_data *pdata;
@@ -218,7 +218,7 @@ err_request_sda:
        return ret;
 }
 
-static int __devexit i2c_gpio_remove(struct platform_device *pdev)
+static int i2c_gpio_remove(struct platform_device *pdev)
 {
        struct i2c_gpio_private_data *priv;
        struct i2c_gpio_platform_data *pdata;
@@ -251,7 +251,7 @@ static struct platform_driver i2c_gpio_driver = {
                .of_match_table = of_match_ptr(i2c_gpio_dt_ids),
        },
        .probe          = i2c_gpio_probe,
-       .remove         = __devexit_p(i2c_gpio_remove),
+       .remove         = i2c_gpio_remove,
 };
 
 static int __init i2c_gpio_init(void)
index 19515df610219a32fea7b2c162744a4474ead8bd..3351cc7ed11f639b429d99e63415a7384adb38df 100644 (file)
@@ -356,7 +356,7 @@ static const struct i2c_algorithm highlander_i2c_algo = {
        .functionality  = highlander_i2c_func,
 };
 
-static int __devinit highlander_i2c_probe(struct platform_device *pdev)
+static int highlander_i2c_probe(struct platform_device *pdev)
 {
        struct highlander_i2c_dev *dev;
        struct i2c_adapter *adap;
@@ -441,7 +441,7 @@ err:
        return ret;
 }
 
-static int __devexit highlander_i2c_remove(struct platform_device *pdev)
+static int highlander_i2c_remove(struct platform_device *pdev)
 {
        struct highlander_i2c_dev *dev = platform_get_drvdata(pdev);
 
@@ -465,7 +465,7 @@ static struct platform_driver highlander_i2c_driver = {
        },
 
        .probe          = highlander_i2c_probe,
-       .remove         = __devexit_p(highlander_i2c_remove),
+       .remove         = highlander_i2c_remove,
 };
 
 module_platform_driver(highlander_i2c_driver);
index c9f95e1666a8fe6a84a8a0765424b67ba4ca25a3..79c3d9069a487328edc82c33228c84908b401222 100644 (file)
@@ -112,7 +112,7 @@ static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = {
 
 MODULE_DEVICE_TABLE (pci, hydra_ids);
 
-static int __devinit hydra_probe(struct pci_dev *dev,
+static int hydra_probe(struct pci_dev *dev,
                                 const struct pci_device_id *id)
 {
        unsigned long base = pci_resource_start(dev, 0);
@@ -139,7 +139,7 @@ static int __devinit hydra_probe(struct pci_dev *dev,
        return 0;
 }
 
-static void __devexit hydra_remove(struct pci_dev *dev)
+static void hydra_remove(struct pci_dev *dev)
 {
        pdregw(hydra_bit_data.data, 0);         /* clear SCLK_OE and SDAT_OE */
        i2c_del_adapter(&hydra_adap);
@@ -153,7 +153,7 @@ static struct pci_driver hydra_driver = {
        .name           = "hydra_smbus",
        .id_table       = hydra_ids,
        .probe          = hydra_probe,
-       .remove         = __devexit_p(hydra_remove),
+       .remove         = hydra_remove,
 };
 
 module_pci_driver(hydra_driver);
index 1e73638225e1c8c37d3e159d600554b461d244e2..3092387f6ef495e3f3a6770de786eeb1a4d180d9 100644 (file)
@@ -841,14 +841,14 @@ struct dmi_onboard_device_info {
        const char *i2c_type;
 };
 
-static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
+static const struct dmi_onboard_device_info dmi_devices[] = {
        { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
        { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
        { "Hades",  DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
 };
 
-static void __devinit dmi_check_onboard_device(u8 type, const char *name,
-                                              struct i2c_adapter *adap)
+static void dmi_check_onboard_device(u8 type, const char *name,
+                                    struct i2c_adapter *adap)
 {
        int i;
        struct i2c_board_info info;
@@ -871,8 +871,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name,
 /* We use our own function to check for onboard devices instead of
    dmi_find_device() as some buggy BIOS's have the devices we are interested
    in marked as disabled */
-static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
-                                               void *adap)
+static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap)
 {
        int i, count;
 
@@ -901,7 +900,7 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
 }
 
 /* Register optional slaves */
-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
+static void i801_probe_optional_slaves(struct i801_priv *priv)
 {
        /* Only register slaves on main SMBus channel */
        if (priv->features & FEATURE_IDF)
@@ -921,7 +920,7 @@ static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
 }
 #else
 static void __init input_apanel_init(void) {}
-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
+static void i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif /* CONFIG_X86 && CONFIG_DMI */
 
 #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
@@ -944,7 +943,7 @@ static struct i801_mux_config i801_mux_config_asus_z8_d18 = {
        .n_gpios = 2,
 };
 
-static struct dmi_system_id __devinitdata mux_dmi_table[] = {
+static const struct dmi_system_id mux_dmi_table[] = {
        {
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
@@ -1012,7 +1011,7 @@ static struct dmi_system_id __devinitdata mux_dmi_table[] = {
 };
 
 /* Setup multiplexing if needed */
-static int __devinit i801_add_mux(struct i801_priv *priv)
+static int i801_add_mux(struct i801_priv *priv)
 {
        struct device *dev = &priv->adapter.dev;
        const struct i801_mux_config *mux_config;
@@ -1048,13 +1047,13 @@ static int __devinit i801_add_mux(struct i801_priv *priv)
        return 0;
 }
 
-static void __devexit i801_del_mux(struct i801_priv *priv)
+static void i801_del_mux(struct i801_priv *priv)
 {
        if (priv->mux_pdev)
                platform_device_unregister(priv->mux_pdev);
 }
 
-static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
+static unsigned int i801_get_adapter_class(struct i801_priv *priv)
 {
        const struct dmi_system_id *id;
        const struct i801_mux_config *mux_config;
@@ -1084,8 +1083,7 @@ static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
 }
 #endif
 
-static int __devinit i801_probe(struct pci_dev *dev,
-                               const struct pci_device_id *id)
+static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned char temp;
        int err, i;
@@ -1226,7 +1224,7 @@ exit:
        return err;
 }
 
-static void __devexit i801_remove(struct pci_dev *dev)
+static void i801_remove(struct pci_dev *dev)
 {
        struct i801_priv *priv = pci_get_drvdata(dev);
 
@@ -1272,7 +1270,7 @@ static struct pci_driver i801_driver = {
        .name           = "i801_smbus",
        .id_table       = i801_ids,
        .probe          = i801_probe,
-       .remove         = __devexit_p(i801_remove),
+       .remove         = i801_remove,
        .suspend        = i801_suspend,
        .resume         = i801_resume,
 };
index 806e225f3de7d0ce2dfb9ff99698f9b68ba6e858..33a2abb6c0633c006a12b83ec18b9b89fbca2db6 100644 (file)
@@ -660,7 +660,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
        return (u8)((opb + 9) / 10 - 1);
 }
 
-static int __devinit iic_request_irq(struct platform_device *ofdev,
+static int iic_request_irq(struct platform_device *ofdev,
                                     struct ibm_iic_private *dev)
 {
        struct device_node *np = ofdev->dev.of_node;
@@ -691,7 +691,7 @@ static int __devinit iic_request_irq(struct platform_device *ofdev,
 /*
  * Register single IIC interface
  */
-static int __devinit iic_probe(struct platform_device *ofdev)
+static int iic_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct ibm_iic_private *dev;
@@ -781,7 +781,7 @@ error_cleanup:
 /*
  * Cleanup initialized IIC interface
  */
-static int __devexit iic_remove(struct platform_device *ofdev)
+static int iic_remove(struct platform_device *ofdev)
 {
        struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
 
@@ -812,7 +812,7 @@ static struct platform_driver ibm_iic_driver = {
                .of_match_table = ibm_iic_match,
        },
        .probe  = iic_probe,
-       .remove = __devexit_p(iic_remove),
+       .remove = iic_remove,
 };
 
 module_platform_driver(ibm_iic_driver);
index 7c28f10f95ca2f380e4c1db9469b864bdd9af26b..de3736bf64657a4da747eeb51450d78267cec54b 100644 (file)
@@ -947,7 +947,7 @@ static const struct dev_pm_ops intel_mid_i2c_pm_ops = {
  * 5. Call intel_mid_i2c_hwinit() for hardware initialization
  * 6. Register I2C adapter in i2c-core
  */
-static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
+static int intel_mid_i2c_probe(struct pci_dev *dev,
                                    const struct pci_device_id *id)
 {
        struct intel_mid_i2c_private *mrst;
@@ -1079,7 +1079,7 @@ exit:
        return err;
 }
 
-static void __devexit intel_mid_i2c_remove(struct pci_dev *dev)
+static void intel_mid_i2c_remove(struct pci_dev *dev)
 {
        struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev);
        intel_mid_i2c_disable(&mrst->adap);
@@ -1113,7 +1113,7 @@ static struct pci_driver intel_mid_i2c_driver = {
        .name           = DRIVER_NAME,
        .id_table       = intel_mid_i2c_ids,
        .probe          = intel_mid_i2c_probe,
-       .remove         = __devexit_p(intel_mid_i2c_remove),
+       .remove         = intel_mid_i2c_remove,
 };
 
 module_pci_driver(intel_mid_i2c_driver);
index f90a6057508dd7ffe0dabd6f30694ab9b06a36f4..4099f79c228066b44dcc8e47d47987dbf63db43b 100644 (file)
@@ -249,7 +249,7 @@ static struct i2c_adapter sch_adapter = {
        .algo           = &smbus_algorithm,
 };
 
-static int __devinit smbus_sch_probe(struct platform_device *dev)
+static int smbus_sch_probe(struct platform_device *dev)
 {
        struct resource *res;
        int retval;
@@ -284,7 +284,7 @@ static int __devinit smbus_sch_probe(struct platform_device *dev)
        return retval;
 }
 
-static int __devexit smbus_sch_remove(struct platform_device *pdev)
+static int smbus_sch_remove(struct platform_device *pdev)
 {
        struct resource *res;
        if (sch_smba) {
@@ -303,7 +303,7 @@ static struct platform_driver smbus_sch_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = smbus_sch_probe,
-       .remove         = __devexit_p(smbus_sch_remove),
+       .remove         = smbus_sch_remove,
 };
 
 module_platform_driver(smbus_sch_driver);
index ca86430cb4a27e1374841f454d5bb5e70ad18b79..a69459e5c3f3cab019f794e4c61b368dc245f536 100644 (file)
@@ -175,7 +175,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 }
 
 #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
-static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
+static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
        {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
        {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
        {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
@@ -196,7 +196,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
        {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
 };
 
-static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
+static int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
                                          int prescaler, u32 *real_clk)
 {
        const struct mpc_i2c_divider *div = NULL;
@@ -230,7 +230,7 @@ static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
        return (int)div->fdr;
 }
 
-static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+static void mpc_i2c_setup_52xx(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -252,7 +252,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
                         fdr);
 }
 #else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
-static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+static void mpc_i2c_setup_52xx(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -260,7 +260,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
 #endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
 
 #ifdef CONFIG_PPC_MPC512x
-static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+static void mpc_i2c_setup_512x(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -288,7 +288,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node,
        mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
 }
 #else /* CONFIG_PPC_MPC512x */
-static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+static void mpc_i2c_setup_512x(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -296,7 +296,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node,
 #endif /* CONFIG_PPC_MPC512x */
 
 #ifdef CONFIG_FSL_SOC
-static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
+static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
        {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
        {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
        {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
@@ -316,7 +316,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
        {49152, 0x011e}, {61440, 0x011f}
 };
 
-static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
+static u32 mpc_i2c_get_sec_cfg_8xxx(void)
 {
        struct device_node *node = NULL;
        u32 __iomem *reg;
@@ -345,7 +345,7 @@ static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
        return val;
 }
 
-static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
+static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
                                          u32 prescaler, u32 *real_clk)
 {
        const struct mpc_i2c_divider *div = NULL;
@@ -383,7 +383,7 @@ static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
        return div ? (int)div->fdr : -EINVAL;
 }
 
-static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+static void mpc_i2c_setup_8xxx(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -408,7 +408,7 @@ static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
 }
 
 #else /* !CONFIG_FSL_SOC */
-static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+static void mpc_i2c_setup_8xxx(struct device_node *node,
                                         struct mpc_i2c *i2c,
                                         u32 clock, u32 prescaler)
 {
@@ -615,7 +615,7 @@ static struct i2c_adapter mpc_ops = {
 };
 
 static const struct of_device_id mpc_i2c_of_match[];
-static int __devinit fsl_i2c_probe(struct platform_device *op)
+static int fsl_i2c_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
        struct mpc_i2c *i2c;
@@ -706,7 +706,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
        return result;
 };
 
-static int __devexit fsl_i2c_remove(struct platform_device *op)
+static int fsl_i2c_remove(struct platform_device *op)
 {
        struct mpc_i2c *i2c = dev_get_drvdata(&op->dev);
 
@@ -746,24 +746,24 @@ static int mpc_i2c_resume(struct device *dev)
 SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
 #endif
 
-static const struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_512x = {
        .setup = mpc_i2c_setup_512x,
 };
 
-static const struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_52xx = {
        .setup = mpc_i2c_setup_52xx,
 };
 
-static const struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8313 = {
        .setup = mpc_i2c_setup_8xxx,
 };
 
-static const struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8543 = {
        .setup = mpc_i2c_setup_8xxx,
        .prescaler = 2,
 };
 
-static const struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8544 = {
        .setup = mpc_i2c_setup_8xxx,
        .prescaler = 3,
 };
@@ -785,7 +785,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
 /* Structure for a device driver */
 static struct platform_driver mpc_i2c_driver = {
        .probe          = fsl_i2c_probe,
-       .remove         = __devexit_p(fsl_i2c_remove),
+       .remove         = fsl_i2c_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = DRV_NAME,
index 2e9d56719e997e5318246fc93c4240c7dec6c96e..8b20ef8524acb0f380defb7968d5c38751b5fd56 100644 (file)
@@ -495,7 +495,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
  *
  *****************************************************************************
  */
-static int __devinit
+static int
 mv64xxx_i2c_map_regs(struct platform_device *pd,
        struct mv64xxx_i2c_data *drv_data)
 {
@@ -530,13 +530,13 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
 }
 
 #ifdef CONFIG_OF
-static int __devinit
+static int
 mv64xxx_calc_freq(const int tclk, const int n, const int m)
 {
        return tclk / (10 * (m + 1) * (2 << n));
 }
 
-static bool __devinit
+static bool
 mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
                          u32 *best_m)
 {
@@ -560,7 +560,7 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
        return true;
 }
 
-static int __devinit
+static int
 mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
                  struct device_node *np)
 {
@@ -597,7 +597,7 @@ out:
 #endif
 }
 #else /* CONFIG_OF */
-static int __devinit
+static int
 mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
                  struct device_node *np)
 {
@@ -605,7 +605,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
 }
 #endif /* CONFIG_OF */
 
-static int __devinit
+static int
 mv64xxx_i2c_probe(struct platform_device *pd)
 {
        struct mv64xxx_i2c_data         *drv_data;
@@ -697,7 +697,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        return rc;
 }
 
-static int __devexit
+static int
 mv64xxx_i2c_remove(struct platform_device *dev)
 {
        struct mv64xxx_i2c_data         *drv_data = platform_get_drvdata(dev);
@@ -718,7 +718,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
        return rc;
 }
 
-static const struct of_device_id mv64xxx_i2c_of_match_table[] __devinitdata = {
+static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
        { .compatible = "marvell,mv64xxx-i2c", },
        {}
 };
@@ -726,7 +726,7 @@ MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
 
 static struct platform_driver mv64xxx_i2c_driver = {
        .probe  = mv64xxx_i2c_probe,
-       .remove = __devexit_p(mv64xxx_i2c_remove),
+       .remove = mv64xxx_i2c_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = MV64XXX_I2C_CTLR_NAME,
index 6ed53da9e1f4dfab4ac21bc33f91938eec13fa58..d6abaf2cf2e3535b4c7c4ad58dc9e5e772b56fee 100644 (file)
@@ -127,7 +127,7 @@ struct mxs_i2c_dev {
        struct device *dev;
        void __iomem *regs;
        struct completion cmd_complete;
-       u32 cmd_err;
+       int cmd_err;
        struct i2c_adapter adapter;
        const struct mxs_i2c_speed_config *speed;
 
@@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        if (msg->len == 0)
                return -EINVAL;
 
-       init_completion(&i2c->cmd_complete);
+       INIT_COMPLETION(i2c->cmd_complete);
        i2c->cmd_err = 0;
 
        ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
@@ -432,7 +432,7 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        return 0;
 }
 
-static int __devinit mxs_i2c_probe(struct platform_device *pdev)
+static int mxs_i2c_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct mxs_i2c_dev *i2c;
@@ -473,6 +473,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        i2c->dev = dev;
        i2c->speed = &mxs_i2c_95kHz_config;
 
+       init_completion(&i2c->cmd_complete);
+
        if (dev->of_node) {
                err = mxs_i2c_get_ofdata(i2c);
                if (err)
@@ -515,7 +517,7 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit mxs_i2c_remove(struct platform_device *pdev)
+static int mxs_i2c_remove(struct platform_device *pdev)
 {
        struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
        int ret;
@@ -546,7 +548,7 @@ static struct platform_driver mxs_i2c_driver = {
                   .owner = THIS_MODULE,
                   .of_match_table = mxs_i2c_dt_ids,
                   },
-       .remove = __devexit_p(mxs_i2c_remove),
+       .remove = mxs_i2c_remove,
 };
 
 static int __init mxs_i2c_init(void)
index 392303b4be075f643d101803f10ea6dafdb7e41f..adac8542771dffaa07702a9c93148f96694fe7dd 100644 (file)
@@ -117,7 +117,7 @@ struct nforce2_smbus {
 #define MAX_TIMEOUT    100
 
 /* We disable the second SMBus channel on these boards */
-static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
+static const struct dmi_system_id nforce2_dmi_blacklist2[] = {
        {
                .ident = "DFI Lanparty NF4 Expert",
                .matches = {
@@ -330,8 +330,8 @@ static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
 MODULE_DEVICE_TABLE (pci, nforce2_ids);
 
 
-static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
-       int alt_reg, struct nforce2_smbus *smbus, const char *name)
+static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
+                            struct nforce2_smbus *smbus, const char *name)
 {
        int error;
 
@@ -382,7 +382,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
 }
 
 
-static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct nforce2_smbus *smbuses;
        int res1, res2;
@@ -430,7 +430,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
 }
 
 
-static void __devexit nforce2_remove(struct pci_dev *dev)
+static void nforce2_remove(struct pci_dev *dev)
 {
        struct nforce2_smbus *smbuses = pci_get_drvdata(dev);
 
@@ -450,7 +450,7 @@ static struct pci_driver nforce2_driver = {
        .name           = "nForce2_smbus",
        .id_table       = nforce2_ids,
        .probe          = nforce2_probe,
-       .remove         = __devexit_p(nforce2_remove),
+       .remove         = nforce2_remove,
 };
 
 module_pci_driver(nforce2_driver);
index a23b91b0b7383829d7d6427f93e4e6dccace5069..865ee350adb363cea47f624eb4c2bb909a3b5624 100644 (file)
@@ -518,7 +518,7 @@ static const struct i2c_algorithm nuc900_i2c_algorithm = {
  * called by the bus driver when a suitable device is found
 */
 
-static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
+static int nuc900_i2c_probe(struct platform_device *pdev)
 {
        struct nuc900_i2c *i2c;
        struct nuc900_platform_i2c *pdata;
@@ -663,7 +663,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
  * called when device is removed from the bus
 */
 
-static int __devexit nuc900_i2c_remove(struct platform_device *pdev)
+static int nuc900_i2c_remove(struct platform_device *pdev)
 {
        struct nuc900_i2c *i2c = platform_get_drvdata(pdev);
 
@@ -684,7 +684,7 @@ static int __devexit nuc900_i2c_remove(struct platform_device *pdev)
 
 static struct platform_driver nuc900_i2c_driver = {
        .probe          = nuc900_i2c_probe,
-       .remove         = __devexit_p(nuc900_i2c_remove),
+       .remove         = nuc900_i2c_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "nuc900-i2c0",
index 9b35c9fbb2fea12859a178c3146e478c32861180..a873d0ad1acbc0b46fe172357052afe0fdce43cb 100644 (file)
@@ -343,7 +343,7 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
 #define ocores_i2c_of_probe(pdev,i2c) -ENODEV
 #endif
 
-static int __devinit ocores_i2c_probe(struct platform_device *pdev)
+static int ocores_i2c_probe(struct platform_device *pdev)
 {
        struct ocores_i2c *i2c;
        struct ocores_i2c_platform_data *pdata;
@@ -441,7 +441,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ocores_i2c_remove(struct platform_device *pdev)
+static int ocores_i2c_remove(struct platform_device *pdev)
 {
        struct ocores_i2c *i2c = platform_get_drvdata(pdev);
 
@@ -485,7 +485,7 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
 
 static struct platform_driver ocores_i2c_driver = {
        .probe   = ocores_i2c_probe,
-       .remove  = __devexit_p(ocores_i2c_remove),
+       .remove  = ocores_i2c_remove,
        .driver  = {
                .owner = THIS_MODULE,
                .name = "ocores-i2c",
index f44c83549fe5a4c5380eb8e18f5d19faae77c9c7..484ca771fdff2d21917adc0ce84585585ab2543a 100644 (file)
@@ -446,7 +446,7 @@ static struct i2c_adapter octeon_i2c_ops = {
 /**
  * octeon_i2c_setclock - Calculate and set clock divisors.
  */
-static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)
+static int octeon_i2c_setclock(struct octeon_i2c *i2c)
 {
        int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
        int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
@@ -489,7 +489,7 @@ static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)
        return 0;
 }
 
-static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
+static int octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
 {
        u8 status;
        int tries;
@@ -510,7 +510,7 @@ static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
        return -EIO;
 }
 
-static int __devinit octeon_i2c_probe(struct platform_device *pdev)
+static int octeon_i2c_probe(struct platform_device *pdev)
 {
        int irq, result = 0;
        struct octeon_i2c *i2c;
@@ -609,7 +609,7 @@ out:
        return result;
 };
 
-static int __devexit octeon_i2c_remove(struct platform_device *pdev)
+static int octeon_i2c_remove(struct platform_device *pdev)
 {
        struct octeon_i2c *i2c = platform_get_drvdata(pdev);
 
@@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match);
 
 static struct platform_driver octeon_i2c_driver = {
        .probe          = octeon_i2c_probe,
-       .remove         = __devexit_p(octeon_i2c_remove),
+       .remove         = octeon_i2c_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = DRV_NAME,
index 7a62acb7d2623fbb0dfd69bc3927dbc9371362e9..4cc2f0528c8869af7d96a99e913b84209530d7c4 100644 (file)
@@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev)
                        if (stat & OMAP_I2C_STAT_AL) {
                                dev_err(dev->dev, "Arbitration lost\n");
                                dev->cmd_err |= OMAP_I2C_STAT_AL;
-                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
                        }
 
                        return -EIO;
@@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                                i2c_omap_errata_i207(dev, stat);
 
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
-                       break;
+                       continue;
                }
 
                if (stat & OMAP_I2C_STAT_RRDY) {
@@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                                break;
 
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
-                       break;
+                       continue;
                }
 
                if (stat & OMAP_I2C_STAT_XRDY) {
@@ -1069,7 +1069,7 @@ MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
 #define OMAP_I2C_SCHEME_0              0
 #define OMAP_I2C_SCHEME_1              1
 
-static int __devinit
+static int
 omap_i2c_probe(struct platform_device *pdev)
 {
        struct omap_i2c_dev     *dev;
@@ -1267,7 +1267,7 @@ err_free_mem:
        return r;
 }
 
-static int __devexit omap_i2c_remove(struct platform_device *pdev)
+static int omap_i2c_remove(struct platform_device *pdev)
 {
        struct omap_i2c_dev     *dev = platform_get_drvdata(pdev);
        int ret;
@@ -1333,7 +1333,7 @@ static struct dev_pm_ops omap_i2c_pm_ops = {
 
 static struct platform_driver omap_i2c_driver = {
        .probe          = omap_i2c_probe,
-       .remove         = __devexit_p(omap_i2c_remove),
+       .remove         = omap_i2c_remove,
        .driver         = {
                .name   = "omap_i2c",
                .owner  = THIS_MODULE,
index 4b95f7a63a3b04de69618f80ea3f3a25c57273ce..aa9577881925f3d9244cd13508dfb64a733a4657 100644 (file)
@@ -135,7 +135,7 @@ static struct lineop parport_ctrl_irq = {
        .port           = PORT_CTRL,
 };
 
-static int __devinit i2c_parport_probe(struct platform_device *pdev)
+static int i2c_parport_probe(struct platform_device *pdev)
 {
        int err;
 
@@ -169,7 +169,7 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit i2c_parport_remove(struct platform_device *pdev)
+static int i2c_parport_remove(struct platform_device *pdev)
 {
        if (ara) {
                line_set(0, &parport_ctrl_irq);
@@ -191,7 +191,7 @@ static struct platform_driver i2c_parport_driver = {
                .name   = DRVNAME,
        },
        .probe          = i2c_parport_probe,
-       .remove         = __devexit_p(i2c_parport_remove),
+       .remove         = i2c_parport_remove,
 };
 
 static int __init i2c_parport_device_add(u16 address)
index 12edefd4183a4c72d0b1e26cdd7183906f5e7f53..615f632c846fffb526d4037ba62f14dd5fe09669 100644 (file)
@@ -340,7 +340,7 @@ static const struct i2c_algorithm smbus_algorithm = {
        .functionality  = pasemi_smb_func,
 };
 
-static int __devinit pasemi_smb_probe(struct pci_dev *dev,
+static int pasemi_smb_probe(struct pci_dev *dev,
                                      const struct pci_device_id *id)
 {
        struct pasemi_smbus *smbus;
@@ -392,7 +392,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
        return error;
 }
 
-static void __devexit pasemi_smb_remove(struct pci_dev *dev)
+static void pasemi_smb_remove(struct pci_dev *dev)
 {
        struct pasemi_smbus *smbus = pci_get_drvdata(dev);
 
@@ -412,7 +412,7 @@ static struct pci_driver pasemi_smb_driver = {
        .name           = "i2c-pasemi",
        .id_table       = pasemi_smb_ids,
        .probe          = pasemi_smb_probe,
-       .remove         = __devexit_p(pasemi_smb_remove),
+       .remove         = pasemi_smb_remove,
 };
 
 module_pci_driver(pasemi_smb_driver);
index 29933f87d8fa8fdc31ffdd38c4ff905fddd7774d..323f061a316378dfb827ee71af2eb5b2f578ed31 100644 (file)
@@ -119,7 +119,7 @@ static struct i2c_adapter pca_isa_ops = {
        .timeout        = HZ,
 };
 
-static int __devinit pca_isa_match(struct device *dev, unsigned int id)
+static int pca_isa_match(struct device *dev, unsigned int id)
 {
        int match = base != 0;
 
@@ -132,7 +132,7 @@ static int __devinit pca_isa_match(struct device *dev, unsigned int id)
        return match;
 }
 
-static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+static int pca_isa_probe(struct device *dev, unsigned int id)
 {
        init_waitqueue_head(&pca_wait);
 
@@ -174,7 +174,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
        return -ENODEV;
 }
 
-static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
+static int pca_isa_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pca_isa_ops);
 
@@ -190,7 +190,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
 static struct isa_driver pca_isa_driver = {
        .match          = pca_isa_match,
        .probe          = pca_isa_probe,
-       .remove         = __devexit_p(pca_isa_remove),
+       .remove         = pca_isa_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = DRIVER,
index 675878f49f76a2ad1c1235068c775abfc583ef0e..a30d2f613c038586a6c7143f2747698b16861f1f 100644 (file)
@@ -131,7 +131,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
 }
 
 
-static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
+static int i2c_pca_pf_probe(struct platform_device *pdev)
 {
        struct i2c_pca_pf_data *i2c;
        struct resource *res;
@@ -257,7 +257,7 @@ e_print:
        return ret;
 }
 
-static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
+static int i2c_pca_pf_remove(struct platform_device *pdev)
 {
        struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
        platform_set_drvdata(pdev, NULL);
@@ -279,7 +279,7 @@ static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
 
 static struct platform_driver i2c_pca_pf_driver = {
        .probe = i2c_pca_pf_probe,
-       .remove = __devexit_p(i2c_pca_pf_remove),
+       .remove = i2c_pca_pf_remove,
        .driver = {
                .name = "i2c-pca-platform",
                .owner = THIS_MODULE,
index f7216ed2f3a924e760d98f38087303d5b3988bb1..39ab78c1a02cc3a4f056a0294432ef01fbbfd165 100644 (file)
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(force_addr,
 static int srvrworks_csb5_delay;
 static struct pci_driver piix4_driver;
 
-static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
+static const struct dmi_system_id piix4_dmi_blacklist[] = {
        {
                .ident = "Sapphire AM2RD790",
                .matches = {
@@ -119,7 +119,7 @@ static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
 
 /* The IBM entry is in a separate table because we only check it
    on Intel-based systems */
-static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = {
+static const struct dmi_system_id piix4_dmi_ibm[] = {
        {
                .ident = "IBM",
                .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
@@ -131,8 +131,8 @@ struct i2c_piix4_adapdata {
        unsigned short smba;
 };
 
-static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
-                               const struct pci_device_id *id)
+static int piix4_setup(struct pci_dev *PIIX4_dev,
+                      const struct pci_device_id *id)
 {
        unsigned char temp;
        unsigned short piix4_smba;
@@ -230,8 +230,8 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
        return piix4_smba;
 }
 
-static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
-                               const struct pci_device_id *id)
+static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+                            const struct pci_device_id *id)
 {
        unsigned short piix4_smba;
        unsigned short smba_idx = 0xcd6;
@@ -294,9 +294,9 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
        return piix4_smba;
 }
 
-static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev,
-                               const struct pci_device_id *id,
-                               unsigned short base_reg_addr)
+static int piix4_setup_aux(struct pci_dev *PIIX4_dev,
+                          const struct pci_device_id *id,
+                          unsigned short base_reg_addr)
 {
        /* Set up auxiliary SMBus controllers found on some
         * AMD chipsets e.g. SP5100 (SB700 derivative) */
@@ -540,9 +540,8 @@ MODULE_DEVICE_TABLE (pci, piix4_ids);
 static struct i2c_adapter *piix4_main_adapter;
 static struct i2c_adapter *piix4_aux_adapter;
 
-static int __devinit piix4_add_adapter(struct pci_dev *dev,
-                                       unsigned short smba,
-                                       struct i2c_adapter **padap)
+static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
+                            struct i2c_adapter **padap)
 {
        struct i2c_adapter *adap;
        struct i2c_piix4_adapdata *adapdata;
@@ -588,8 +587,7 @@ static int __devinit piix4_add_adapter(struct pci_dev *dev,
        return 0;
 }
 
-static int __devinit piix4_probe(struct pci_dev *dev,
-                               const struct pci_device_id *id)
+static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int retval;
 
@@ -626,7 +624,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
        return 0;
 }
 
-static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
+static void piix4_adap_remove(struct i2c_adapter *adap)
 {
        struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
 
@@ -638,7 +636,7 @@ static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
        }
 }
 
-static void __devexit piix4_remove(struct pci_dev *dev)
+static void piix4_remove(struct pci_dev *dev)
 {
        if (piix4_main_adapter) {
                piix4_adap_remove(piix4_main_adapter);
@@ -655,7 +653,7 @@ static struct pci_driver piix4_driver = {
        .name           = "piix4_smbus",
        .id_table       = piix4_ids,
        .probe          = piix4_probe,
-       .remove         = __devexit_p(piix4_remove),
+       .remove         = piix4_remove,
 };
 
 module_pci_driver(piix4_driver);
index 3d71395ae1f763d47ea11f33ba55eeab6ef7c174..083d68cfaf0bacc501328006b2f16eb1dc2f5fcb 100644 (file)
@@ -270,7 +270,7 @@ static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
 /*
  * Probe for and register the device and return 0 if there is one.
  */
-static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+static int pmcmsptwi_probe(struct platform_device *pldev)
 {
        struct resource *res;
        int rc = -ENODEV;
@@ -368,7 +368,7 @@ ret_err:
 /*
  * Release the device and return 0 if there is one.
  */
-static int __devexit pmcmsptwi_remove(struct platform_device *pldev)
+static int pmcmsptwi_remove(struct platform_device *pldev)
 {
        struct resource *res;
 
@@ -628,7 +628,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
 
 static struct platform_driver pmcmsptwi_driver = {
        .probe  = pmcmsptwi_probe,
-       .remove = __devexit_p(pmcmsptwi_remove),
+       .remove = pmcmsptwi_remove,
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 8488bddfe46596109249edd242a3ad0ebc7cfe8b..ce4097012e978eed7fc7caff18c12c8abeede5ea 100644 (file)
@@ -619,7 +619,7 @@ static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
 #define PNX_I2C_PM     NULL
 #endif
 
-static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+static int i2c_pnx_probe(struct platform_device *pdev)
 {
        unsigned long tmp;
        int ret = 0;
@@ -765,7 +765,7 @@ err_kzalloc:
        return ret;
 }
 
-static int __devexit i2c_pnx_remove(struct platform_device *pdev)
+static int i2c_pnx_remove(struct platform_device *pdev)
 {
        struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
 
@@ -797,7 +797,7 @@ static struct platform_driver i2c_pnx_driver = {
                .pm = PNX_I2C_PM,
        },
        .probe = i2c_pnx_probe,
-       .remove = __devexit_p(i2c_pnx_remove),
+       .remove = i2c_pnx_remove,
 };
 
 static int __init i2c_adap_pnx_init(void)
index 5285f8565de4d14c1e8265fc12c5ee18b0c670ae..0dd5b334d0905c3597cfbb437c4a0250ffeb39b3 100644 (file)
@@ -210,7 +210,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
 };
 
 
-static int __devexit i2c_powermac_remove(struct platform_device *dev)
+static int i2c_powermac_remove(struct platform_device *dev)
 {
        struct i2c_adapter      *adapter = platform_get_drvdata(dev);
        int                     rc;
@@ -227,7 +227,7 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
        return 0;
 }
 
-static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
+static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
                                           struct pmac_i2c_bus *bus,
                                           struct device_node *node)
 {
@@ -255,7 +255,7 @@ static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
        return 0xffffffff;
 }
 
-static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
+static void i2c_powermac_create_one(struct i2c_adapter *adap,
                                              const char *type,
                                              u32 addr)
 {
@@ -271,7 +271,7 @@ static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
                        type);
 }
 
-static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
+static void i2c_powermac_add_missing(struct i2c_adapter *adap,
                                               struct pmac_i2c_bus *bus,
                                               bool found_onyx)
 {
@@ -297,7 +297,7 @@ static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
        }
 }
 
-static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
+static bool i2c_powermac_get_type(struct i2c_adapter *adap,
                                            struct device_node *node,
                                            u32 addr, char *type, int type_size)
 {
@@ -336,7 +336,7 @@ static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
        return false;
 }
 
-static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
+static void i2c_powermac_register_devices(struct i2c_adapter *adap,
                                                    struct pmac_i2c_bus *bus)
 {
        struct i2c_client *newdev;
@@ -403,7 +403,7 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
        i2c_powermac_add_missing(adap, bus, found_onyx);
 }
 
-static int __devinit i2c_powermac_probe(struct platform_device *dev)
+static int i2c_powermac_probe(struct platform_device *dev)
 {
        struct pmac_i2c_bus *bus = dev->dev.platform_data;
        struct device_node *parent = NULL;
@@ -467,7 +467,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
 
 static struct platform_driver i2c_powermac_driver = {
        .probe = i2c_powermac_probe,
-       .remove = __devexit_p(i2c_powermac_remove),
+       .remove = i2c_powermac_remove,
        .driver = {
                .name = "i2c-powermac",
                .bus = &platform_bus_type,
index d8515be00b98a8b325620fca2069a06905a06969..d7c512d717a780785872eca8870b30b6cd4f5b88 100644 (file)
@@ -184,7 +184,7 @@ static struct i2c_algorithm puv3_i2c_algorithm = {
 /*
  * Main initialization routine.
  */
-static int __devinit puv3_i2c_probe(struct platform_device *pdev)
+static int puv3_i2c_probe(struct platform_device *pdev)
 {
        struct i2c_adapter *adapter;
        struct resource *mem;
@@ -231,7 +231,7 @@ fail_nomem:
        return rc;
 }
 
-static int __devexit puv3_i2c_remove(struct platform_device *pdev)
+static int puv3_i2c_remove(struct platform_device *pdev)
 {
        struct i2c_adapter *adapter = platform_get_drvdata(pdev);
        struct resource *mem;
@@ -276,7 +276,7 @@ static SIMPLE_DEV_PM_OPS(puv3_i2c_pm, puv3_i2c_suspend, NULL);
 
 static struct platform_driver puv3_i2c_driver = {
        .probe          = puv3_i2c_probe,
-       .remove         = __devexit_p(puv3_i2c_remove),
+       .remove         = puv3_i2c_remove,
        .driver         = {
                .name   = "PKUnity-v3-I2C",
                .owner  = THIS_MODULE,
index 4dc9bef17d77f78fbdc92b076944fc8621f5410e..3d4985695aed7e0ed92d76aa271f2f4064afcea3 100644 (file)
@@ -94,7 +94,7 @@ out:
        return ERR_PTR(ret);
 }
 
-static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+static int ce4100_i2c_probe(struct pci_dev *dev,
                const struct pci_device_id *ent)
 {
        int ret;
@@ -135,7 +135,7 @@ err_mem:
        return ret;
 }
 
-static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
+static void ce4100_i2c_remove(struct pci_dev *dev)
 {
        struct ce4100_devices *sds;
        unsigned int i;
@@ -160,7 +160,7 @@ static struct pci_driver ce4100_i2c_driver = {
        .name           = "ce4100_i2c",
        .id_table       = ce4100_i2c_devices,
        .probe          = ce4100_i2c_probe,
-       .remove         = __devexit_p(ce4100_i2c_remove),
+       .remove         = ce4100_i2c_remove,
 };
 
 module_pci_driver(ce4100_i2c_driver);
index 72a8071a55569372f05da2907206f3528246e6f0..9bd4d73d29e3593fb86ad2bfb47161bafa68a192 100644 (file)
@@ -613,7 +613,7 @@ static const struct i2c_algorithm rcar_i2c_algo = {
        .functionality  = rcar_i2c_func,
 };
 
-static int __devinit rcar_i2c_probe(struct platform_device *pdev)
+static int rcar_i2c_probe(struct platform_device *pdev)
 {
        struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data;
        struct rcar_i2c_priv *priv;
@@ -682,7 +682,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit rcar_i2c_remove(struct platform_device *pdev)
+static int rcar_i2c_remove(struct platform_device *pdev)
 {
        struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -699,7 +699,7 @@ static struct platform_driver rcar_i2c_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rcar_i2c_probe,
-       .remove         = __devexit_p(rcar_i2c_remove),
+       .remove         = rcar_i2c_remove,
 };
 
 module_platform_driver(rcar_i2c_driver);
index b76a29d1f8e417c49a1ca1089b4c7a9333f0040d..008836409efeed631f78b16056be6199c3d703db 100644 (file)
@@ -248,7 +248,7 @@ static struct i2c_algorithm s6i2c_algorithm = {
        .functionality = s6i2c_functionality,
 };
 
-static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
+static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
 {
        u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
        if (dividend > 0xffff)
@@ -256,7 +256,7 @@ static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
        return dividend;
 }
 
-static int __devinit s6i2c_probe(struct platform_device *dev)
+static int s6i2c_probe(struct platform_device *dev)
 {
        struct s6i2c_if *iface = &s6i2c_if;
        struct i2c_adapter *p_adap;
@@ -361,7 +361,7 @@ err_out:
        return rc;
 }
 
-static int __devexit s6i2c_remove(struct platform_device *pdev)
+static int s6i2c_remove(struct platform_device *pdev)
 {
        struct s6i2c_if *iface = platform_get_drvdata(pdev);
        i2c_wr16(iface, S6_I2C_ENABLE, 0);
@@ -378,7 +378,7 @@ static int __devexit s6i2c_remove(struct platform_device *pdev)
 
 static struct platform_driver s6i2c_driver = {
        .probe          = s6i2c_probe,
-       .remove         = __devexit_p(s6i2c_remove),
+       .remove         = s6i2c_remove,
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index c0c9dffbdb12faa38fded2cfdae970dc941c91c5..3a2253e1bf59404ab7a6986cb7775b4477baf0ef 100644 (file)
@@ -390,7 +390,7 @@ static const struct i2c_algorithm sh7760_i2c_algo = {
  * iclk = mclk/(CDF + 1).  iclk must be < 20MHz.
  * scl = iclk/(SCGD*8 + 20).
  */
-static int __devinit calc_CCR(unsigned long scl_hz)
+static int calc_CCR(unsigned long scl_hz)
 {
        struct clk *mclk;
        unsigned long mck, m1, dff, odff, iclk;
@@ -430,7 +430,7 @@ static int __devinit calc_CCR(unsigned long scl_hz)
        return ((scgdm << 2) | cdfm);
 }
 
-static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
+static int sh7760_i2c_probe(struct platform_device *pdev)
 {
        struct sh7760_i2c_platdata *pd;
        struct resource *res;
@@ -536,7 +536,7 @@ out0:
        return ret;
 }
 
-static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
+static int sh7760_i2c_remove(struct platform_device *pdev)
 {
        struct cami2c *id = platform_get_drvdata(pdev);
 
@@ -557,7 +557,7 @@ static struct platform_driver sh7760_i2c_drv = {
                .owner  = THIS_MODULE,
        },
        .probe          = sh7760_i2c_probe,
-       .remove         = __devexit_p(sh7760_i2c_remove),
+       .remove         = sh7760_i2c_remove,
 };
 
 module_platform_driver(sh7760_i2c_drv);
index 9411c1b892c0b9d931f5ec7330e0bdd5baa0eda9..b6e7a83a8296e719870efb35f8c456c7caf5f94f 100644 (file)
@@ -758,7 +758,7 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
        .runtime_resume = sh_mobile_i2c_runtime_nop,
 };
 
-static const struct of_device_id sh_mobile_i2c_dt_ids[] __devinitconst = {
+static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
        { .compatible = "renesas,rmobile-iic", },
        {},
 };
index 5574a47792fb55c5bc42a5e8a892b0f3ada6e424..e03381aee34f526cc8c8c66c67293fffdde97689 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/of_i2c.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -258,7 +259,7 @@ static const struct i2c_algorithm i2c_sirfsoc_algo = {
        .functionality = i2c_sirfsoc_func,
 };
 
-static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
+static int i2c_sirfsoc_probe(struct platform_device *pdev)
 {
        struct sirfsoc_i2c *siic;
        struct i2c_adapter *adap;
@@ -328,6 +329,7 @@ static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
        adap->algo = &i2c_sirfsoc_algo;
        adap->algo_data = siic;
 
+       adap->dev.of_node = pdev->dev.of_node;
        adap->dev.parent = &pdev->dev;
        adap->nr = pdev->id;
 
@@ -371,6 +373,8 @@ static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
 
        clk_disable(clk);
 
+       of_i2c_register_devices(adap);
+
        dev_info(&pdev->dev, " I2C adapter ready to operate\n");
 
        return 0;
@@ -385,7 +389,7 @@ err_get_clk:
        return err;
 }
 
-static int __devexit i2c_sirfsoc_remove(struct platform_device *pdev)
+static int i2c_sirfsoc_remove(struct platform_device *pdev)
 {
        struct i2c_adapter *adapter = platform_get_drvdata(pdev);
        struct sirfsoc_i2c *siic = adapter->algo_data;
@@ -433,7 +437,7 @@ static const struct dev_pm_ops i2c_sirfsoc_pm_ops = {
 };
 #endif
 
-static const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = {
+static const struct of_device_id sirfsoc_i2c_of_match[] = {
        { .compatible = "sirf,prima2-i2c", },
        {},
 };
@@ -449,7 +453,7 @@ static struct platform_driver i2c_sirfsoc_driver = {
                .of_match_table = sirfsoc_i2c_of_match,
        },
        .probe = i2c_sirfsoc_probe,
-       .remove = __devexit_p(i2c_sirfsoc_remove),
+       .remove = i2c_sirfsoc_remove,
 };
 module_platform_driver(i2c_sirfsoc_driver);
 
index 87e5126d449ce4072eb263cb04b180e5c6d597f4..79fd96a043868644d855ff8585348accf74530a2 100644 (file)
@@ -142,7 +142,7 @@ static void sis5595_write(u8 reg, u8 data)
        outb(data, sis5595_base + SMB_DAT);
 }
 
-static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
+static int sis5595_setup(struct pci_dev *SIS5595_dev)
 {
        u16 a;
        u8 val;
@@ -376,7 +376,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = {
 
 MODULE_DEVICE_TABLE (pci, sis5595_ids);
 
-static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int err;
 
index 5d6723b7525ed547d0e88f6ff1d7f5b47148be6e..de6dddb9f8656eaee90259adcf7e98d688e55f9f 100644 (file)
@@ -389,7 +389,7 @@ static u32 sis630_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static int __devinit sis630_setup(struct pci_dev *sis630_dev)
+static int sis630_setup(struct pci_dev *sis630_dev)
 {
        unsigned char b;
        struct pci_dev *dummy = NULL;
@@ -480,7 +480,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
 
 MODULE_DEVICE_TABLE (pci, sis630_ids);
 
-static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        if (sis630_setup(dev)) {
                dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
@@ -496,7 +496,7 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
        return i2c_add_adapter(&sis630_adapter);
 }
 
-static void __devexit sis630_remove(struct pci_dev *dev)
+static void sis630_remove(struct pci_dev *dev)
 {
        if (acpi_base) {
                i2c_del_adapter(&sis630_adapter);
@@ -510,7 +510,7 @@ static struct pci_driver sis630_driver = {
        .name           = "sis630_smbus",
        .id_table       = sis630_ids,
        .probe          = sis630_probe,
-       .remove         = __devexit_p(sis630_remove),
+       .remove         = sis630_remove,
 };
 
 module_pci_driver(sis630_driver);
index 7b72614a9bc0adde27d469fb305622952ac56e94..b9faf9b6002bce7c09286229fd1680a212f2d11c 100644 (file)
@@ -252,7 +252,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = {
 
 MODULE_DEVICE_TABLE (pci, sis96x_ids);
 
-static int __devinit sis96x_probe(struct pci_dev *dev,
+static int sis96x_probe(struct pci_dev *dev,
                                const struct pci_device_id *id)
 {
        u16 ww = 0;
@@ -308,7 +308,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
        return retval;
 }
 
-static void __devexit sis96x_remove(struct pci_dev *dev)
+static void sis96x_remove(struct pci_dev *dev)
 {
        if (sis96x_smbus_base) {
                i2c_del_adapter(&sis96x_adapter);
@@ -321,7 +321,7 @@ static struct pci_driver sis96x_driver = {
        .name           = "sis96x_smbus",
        .id_table       = sis96x_ids,
        .probe          = sis96x_probe,
-       .remove         = __devexit_p(sis96x_remove),
+       .remove         = sis96x_remove,
 };
 
 module_pci_driver(sis96x_driver);
index dcea77bf6f50ff2cc1c198e7850bbbe138128238..7b38877ffec10ed06995b191a024871c9c1e923d 100644 (file)
@@ -642,7 +642,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 
 #if defined(CONFIG_OF)
 /* Match table for of_platform binding */
-static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+static const struct of_device_id tegra_i2c_of_match[] = {
        { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
        { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
        { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
@@ -651,7 +651,7 @@ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
 MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 #endif
 
-static int __devinit tegra_i2c_probe(struct platform_device *pdev)
+static int tegra_i2c_probe(struct platform_device *pdev)
 {
        struct tegra_i2c_dev *i2c_dev;
        struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
@@ -769,7 +769,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tegra_i2c_remove(struct platform_device *pdev)
+static int tegra_i2c_remove(struct platform_device *pdev)
 {
        struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
        i2c_del_adapter(&i2c_dev->adapter);
@@ -817,7 +817,7 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
 
 static struct platform_driver tegra_i2c_driver = {
        .probe   = tegra_i2c_probe,
-       .remove  = __devexit_p(tegra_i2c_remove),
+       .remove  = tegra_i2c_remove,
        .driver  = {
                .name  = "tegra-i2c",
                .owner = THIS_MODULE,
index 7ffee71ca19051afffde5c5f7da94dc319924020..be662511c58bf931aef8e57de31905d710952363 100644 (file)
@@ -96,7 +96,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = {
 
 MODULE_DEVICE_TABLE (pci, vt586b_ids);
 
-static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        u16 base;
        u8 rev;
@@ -146,7 +146,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
        return 0;
 }
 
-static void __devexit vt586b_remove(struct pci_dev *dev)
+static void vt586b_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&vt586b_adapter);
        release_region(I2C_DIR, IOSPACE);
@@ -158,7 +158,7 @@ static struct pci_driver vt586b_driver = {
        .name           = "vt586b_smbus",
        .id_table       = vt586b_ids,
        .probe          = vt586b_probe,
-       .remove         = __devexit_p(vt586b_remove),
+       .remove         = vt586b_remove,
 };
 
 module_pci_driver(vt586b_driver);
index 271c9a2b0fd76672f82855dcb87d40a4b9ff3ac7..b2d90e105f41c93b6a6013e6e20adcfbb6927864 100644 (file)
@@ -320,8 +320,8 @@ static struct i2c_adapter vt596_adapter = {
        .algo           = &smbus_algorithm,
 };
 
-static int __devinit vt596_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *id)
+static int vt596_probe(struct pci_dev *pdev,
+                      const struct pci_device_id *id)
 {
        unsigned char temp;
        int error;
index f5fa20dea9063f52018aeaad4eb7e2d7cb1f4ca0..f45c32c1ace698a69594ab1df95998a140bbe5e0 100644 (file)
@@ -360,7 +360,7 @@ static const struct i2c_algorithm vprbrd_algorithm = {
        .functionality  = vprbrd_i2c_func,
 };
 
-static int __devinit vprbrd_i2c_probe(struct platform_device *pdev)
+static int vprbrd_i2c_probe(struct platform_device *pdev)
 {
        struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
        struct vprbrd_i2c *vb_i2c;
@@ -418,7 +418,7 @@ error:
        return ret;
 }
 
-static int __devexit vprbrd_i2c_remove(struct platform_device *pdev)
+static int vprbrd_i2c_remove(struct platform_device *pdev)
 {
        struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev);
        int ret;
@@ -432,7 +432,7 @@ static struct platform_driver vprbrd_i2c_driver = {
        .driver.name    = "viperboard-i2c",
        .driver.owner   = THIS_MODULE,
        .probe          = vprbrd_i2c_probe,
-       .remove         = __devexit_p(vprbrd_i2c_remove),
+       .remove         = vprbrd_i2c_remove,
 };
 
 static int __init vprbrd_i2c_init(void)
index 641d0e5e33036a3643027bbd7a61b3b0c1204401..f042f6da0ace57cb60d0da99ef6bdb554db0d8b5 100644 (file)
@@ -689,7 +689,7 @@ static struct i2c_adapter xiic_adapter = {
 };
 
 
-static int __devinit xiic_i2c_probe(struct platform_device *pdev)
+static int xiic_i2c_probe(struct platform_device *pdev)
 {
        struct xiic_i2c *i2c;
        struct xiic_i2c_platform_data *pdata;
@@ -774,7 +774,7 @@ resource_missing:
        return -ENOENT;
 }
 
-static int __devexit xiic_i2c_remove(struct platform_device* pdev)
+static int xiic_i2c_remove(struct platform_device *pdev)
 {
        struct xiic_i2c *i2c = platform_get_drvdata(pdev);
        struct resource *res;
@@ -800,7 +800,7 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev)
 }
 
 #if defined(CONFIG_OF)
-static const struct of_device_id xiic_of_match[] __devinitconst = {
+static const struct of_device_id xiic_of_match[] = {
        { .compatible = "xlnx,xps-iic-2.00.a", },
        {},
 };
@@ -809,7 +809,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match);
 
 static struct platform_driver xiic_i2c_driver = {
        .probe   = xiic_i2c_probe,
-       .remove  = __devexit_p(xiic_i2c_remove),
+       .remove  = xiic_i2c_remove,
        .driver  = {
                .owner = THIS_MODULE,
                .name = DRIVER_NAME,
index 96d3fabd8883af8d8c4f967874a27090a367b717..a005265461da1d2bb7da484d61204265bc2935a6 100644 (file)
@@ -214,7 +214,7 @@ static struct i2c_algorithm xlr_i2c_algo = {
        .functionality  = xlr_func,
 };
 
-static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+static int xlr_i2c_probe(struct platform_device *pdev)
 {
        struct xlr_i2c_private  *priv;
        struct resource *res;
@@ -251,7 +251,7 @@ static int __devinit xlr_i2c_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+static int xlr_i2c_remove(struct platform_device *pdev)
 {
        struct xlr_i2c_private *priv;
 
@@ -263,7 +263,7 @@ static int __devexit xlr_i2c_remove(struct platform_device *pdev)
 
 static struct platform_driver xlr_i2c_driver = {
        .probe  = xlr_i2c_probe,
-       .remove = __devexit_p(xlr_i2c_remove),
+       .remove = xlr_i2c_remove,
        .driver = {
                .name   = "xlr-i2cbus",
                .owner  = THIS_MODULE,
index 08aab57337dd22f56fa2ff1308c0cd5af4dbc1e7..3862a953239c86c476961d101c43367f93ea4a0d 100644 (file)
@@ -389,7 +389,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = {
 static struct scx200_acb_iface *scx200_acb_list;
 static DEFINE_MUTEX(scx200_acb_list_mutex);
 
-static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
+static int scx200_acb_probe(struct scx200_acb_iface *iface)
 {
        u8 val;
 
@@ -424,7 +424,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
        return 0;
 }
 
-static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
+static struct scx200_acb_iface *scx200_create_iface(const char *text,
                struct device *dev, int index)
 {
        struct scx200_acb_iface *iface;
@@ -449,7 +449,7 @@ static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
        return iface;
 }
 
-static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
+static int scx200_acb_create(struct scx200_acb_iface *iface)
 {
        struct i2c_adapter *adapter;
        int rc;
@@ -480,7 +480,7 @@ static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
        return 0;
 }
 
-static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
+static struct scx200_acb_iface *scx200_create_dev(const char *text,
                unsigned long base, int index, struct device *dev)
 {
        struct scx200_acb_iface *iface;
@@ -508,7 +508,7 @@ static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
        return NULL;
 }
 
-static int __devinit scx200_probe(struct platform_device *pdev)
+static int scx200_probe(struct platform_device *pdev)
 {
        struct scx200_acb_iface *iface;
        struct resource *res;
@@ -530,14 +530,14 @@ static int __devinit scx200_probe(struct platform_device *pdev)
        return 0;
 }
 
-static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface)
+static void scx200_cleanup_iface(struct scx200_acb_iface *iface)
 {
        i2c_del_adapter(&iface->adapter);
        release_region(iface->base, 8);
        kfree(iface);
 }
 
-static int __devexit scx200_remove(struct platform_device *pdev)
+static int scx200_remove(struct platform_device *pdev)
 {
        struct scx200_acb_iface *iface;
 
@@ -554,7 +554,7 @@ static struct platform_driver scx200_pci_driver = {
                .owner = THIS_MODULE,
        },
        .probe = scx200_probe,
-       .remove = __devexit_p(scx200_remove),
+       .remove = scx200_remove,
 };
 
 static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = {
index 3b7bc06fe8a6888837719a16a54dfa0f573806cb..9f50ef04a4bd85f1ac7d59078e9a1c98d3f7e797 100644 (file)
@@ -53,14 +53,14 @@ static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
        return 0;
 }
 
-static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
+static int match_gpio_chip_by_label(struct gpio_chip *chip,
                                              void *data)
 {
        return !strcmp(chip->label, data);
 }
 
 #ifdef CONFIG_OF
-static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
                                        struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -125,14 +125,14 @@ static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
        return 0;
 }
 #else
-static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
                                        struct platform_device *pdev)
 {
        return 0;
 }
 #endif
 
-static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
+static int i2c_mux_gpio_probe(struct platform_device *pdev)
 {
        struct gpiomux *mux;
        struct i2c_adapter *parent;
@@ -239,7 +239,7 @@ alloc_failed:
        return ret;
 }
 
-static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
+static int i2c_mux_gpio_remove(struct platform_device *pdev)
 {
        struct gpiomux *mux = platform_get_drvdata(pdev);
        int i;
@@ -256,7 +256,7 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = {
+static const struct of_device_id i2c_mux_gpio_of_match[] = {
        { .compatible = "i2c-mux-gpio", },
        {},
 };
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
 
 static struct platform_driver i2c_mux_gpio_driver = {
        .probe  = i2c_mux_gpio_probe,
-       .remove = __devexit_p(i2c_mux_gpio_remove),
+       .remove = i2c_mux_gpio_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "i2c-mux-gpio",
index 7fa5b24b16db9a4a1c4c1a360f16dd01b018a215..a43c0ce5e3d8728918afa810842292d00efdac8c 100644 (file)
@@ -129,7 +129,7 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
 }
 #endif
 
-static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
+static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 {
        struct i2c_mux_pinctrl *mux;
        int (*deselect)(struct i2c_adapter *, void *, u32);
@@ -167,7 +167,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,
+                                  sizeof(*mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
        if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
@@ -241,7 +241,7 @@ err:
        return ret;
 }
 
-static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev)
+static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
 {
        struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
        int i;
@@ -255,7 +255,7 @@ static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static const struct of_device_id i2c_mux_pinctrl_of_match[] __devinitconst = {
+static const struct of_device_id i2c_mux_pinctrl_of_match[] = {
        { .compatible = "i2c-mux-pinctrl", },
        {},
 };
@@ -269,7 +269,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = {
                .of_match_table = of_match_ptr(i2c_mux_pinctrl_of_match),
        },
        .probe  = i2c_mux_pinctrl_probe,
-       .remove = __devexit_p(i2c_mux_pinctrl_remove),
+       .remove = i2c_mux_pinctrl_remove,
 };
 module_platform_driver(i2c_mux_pinctrl_driver);
 
index 01451940393b9b95dd9a228cdb1283884c781aa3..c7eaf20af9266d7f325ab3cb8430955c1f213cf0 100644 (file)
@@ -181,7 +181,7 @@ static const struct ide_port_ops atp86x_port_ops = {
        .cable_detect           = atp86x_cable_detect,
 };
 
-static const struct ide_port_info aec62xx_chipsets[] __devinitconst = {
+static const struct ide_port_info aec62xx_chipsets[] = {
        {       /* 0: AEC6210 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
@@ -251,7 +251,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitconst = {
  *     chips, pass a local copy of 'struct ide_port_info' down the call chain.
  */
 
-static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct chipset_bus_clock_list_entry *bus_clock;
        struct ide_port_info d;
@@ -287,7 +287,7 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
        return err;
 }
 
-static void __devexit aec62xx_remove(struct pci_dev *dev)
+static void aec62xx_remove(struct pci_dev *dev)
 {
        ide_pci_remove(dev);
        pci_disable_device(dev);
@@ -307,7 +307,7 @@ static struct pci_driver aec62xx_pci_driver = {
        .name           = "AEC62xx_IDE",
        .id_table       = aec62xx_pci_tbl,
        .probe          = aec62xx_init_one,
-       .remove         = __devexit_p(aec62xx_remove),
+       .remove         = aec62xx_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index 911a27ca356b71b406d4ff0eae80e7d4d5b51abf..36f76e28a0bfa0df067046f9def48cecb12f544e 100644 (file)
@@ -415,7 +415,7 @@ static u8 ali_cable_detect(ide_hwif_t *hwif)
  *     Sparc systems.
  */
 
-static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+static void init_hwif_ali15x3(ide_hwif_t *hwif)
 {
        u8 ideic, inmir;
        s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
@@ -464,8 +464,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
  *     Set up the DMA functionality on the ALi 15x3.
  */
 
-static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
-                                     const struct ide_port_info *d)
+static int init_dma_ali15x3(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long base = ide_pci_dma_base(hwif, d);
@@ -512,7 +511,7 @@ static const struct ide_dma_ops ali_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info ali15x3_chipset __devinitconst = {
+static const struct ide_port_info ali15x3_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_ali15x3,
        .init_hwif      = init_hwif_ali15x3,
@@ -532,7 +531,8 @@ static const struct ide_port_info ali15x3_chipset __devinitconst = {
  *     hot plug layer.
  */
  
-static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int alim15x3_init_one(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        struct ide_port_info d = ali15x3_chipset;
        u8 rev = dev->revision, idx = id->driver_data;
index 56fc99557ba28dfc24d8d5e0e06054fa8605553a..cbfe846911d19ef80764e0969889891585d88edc 100644 (file)
@@ -223,7 +223,7 @@ static const struct ide_port_ops amd_port_ops = {
                .udma_mask      = udma,                                 \
        }
 
-static const struct ide_port_info amd74xx_chipsets[] __devinitconst = {
+static const struct ide_port_info amd74xx_chipsets[] = {
        /* 0: AMD7401 */        DECLARE_AMD_DEV(0x00, ATA_UDMA2),
        /* 1: AMD7409 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
        /* 2: AMD7411/7441 */   DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
@@ -235,7 +235,7 @@ static const struct ide_port_info amd74xx_chipsets[] __devinitconst = {
        /* 6: AMD5536 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
 };
 
-static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d;
        u8 idx = id->driver_data;
index cb43480b1bd5eb34f0a345eb57e1502618e09dbb..dbd0f242ec1877ccdd3c8cde1d7c7fcebc76574d 100644 (file)
@@ -139,7 +139,7 @@ static const struct ide_port_ops atiixp_port_ops = {
        .cable_detect           = atiixp_cable_detect,
 };
 
-static const struct ide_port_info atiixp_pci_info[] __devinitconst = {
+static const struct ide_port_info atiixp_pci_info[] = {
        {       /* 0: IXP200/300/400/700 */
                .name           = DRV_NAME,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
@@ -168,7 +168,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
 
-static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
 }
index d1fc43802f5d21c9427aa1bc80cf6fc47d9302ef..b127ed60c73364f34a114a8a3033aa42c906b8ca 100644 (file)
@@ -327,7 +327,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info cmd64x_chipsets[] __devinitconst = {
+static const struct ide_port_info cmd64x_chipsets[] = {
        {       /* 0: CMD643 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
@@ -373,7 +373,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitconst = {
        }
 };
 
-static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d;
        u8 idx = id->driver_data;
index 14447621e60b7072dc3cb0d5845c81d98ed6a611..6250aee30503d0b48043a2471a33206d6e04f654 100644 (file)
@@ -94,7 +94,7 @@ static const struct ide_port_ops cs5520_port_ops = {
        .set_dma_mode           = cs5520_set_dma_mode,
 };
 
-static const struct ide_port_info cyrix_chipset __devinitconst = {
+static const struct ide_port_info cyrix_chipset = {
        .name           = DRV_NAME,
        .enablebits     = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
        .port_ops       = &cs5520_port_ops,
@@ -108,7 +108,7 @@ static const struct ide_port_info cyrix_chipset __devinitconst = {
  *     work longhand.
  */
  
-static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct ide_port_info *d = &cyrix_chipset;
        struct ide_hw hw[2], *hws[] = { NULL, NULL };
index 49b40ad59d1a71e5ad6e96b15a8c0e1c028e6636..65371599b97672673af822f05167e0647ae617a0 100644 (file)
@@ -226,7 +226,7 @@ out:
  *     performs channel-specific pre-initialization before drive probing.
  */
 
-static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
+static void init_hwif_cs5530 (ide_hwif_t *hwif)
 {
        unsigned long basereg;
        u32 d0_timings;
@@ -245,7 +245,7 @@ static const struct ide_port_ops cs5530_port_ops = {
        .udma_filter            = cs5530_udma_filter,
 };
 
-static const struct ide_port_info cs5530_chipset __devinitconst = {
+static const struct ide_port_info cs5530_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
@@ -257,7 +257,7 @@ static const struct ide_port_info cs5530_chipset __devinitconst = {
        .udma_mask      = ATA_UDMA2,
 };
 
-static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &cs5530_chipset, NULL);
 }
index 18d4c852602bfa042926d21d03dce3e231bc33eb..3bc5b9a34013b0e30ee3500961be5b2a4782b6fd 100644 (file)
@@ -170,7 +170,7 @@ static const struct ide_port_ops cs5535_port_ops = {
        .cable_detect           = cs5535_cable_detect,
 };
 
-static const struct ide_port_info cs5535_chipset __devinitconst = {
+static const struct ide_port_info cs5535_chipset = {
        .name           = DRV_NAME,
        .port_ops       = &cs5535_port_ops,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
@@ -179,8 +179,7 @@ static const struct ide_port_info cs5535_chipset __devinitconst = {
        .udma_mask      = ATA_UDMA4,
 };
 
-static int __devinit cs5535_init_one(struct pci_dev *dev,
-                                       const struct pci_device_id *id)
+static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &cs5535_chipset, NULL);
 }
index 3ffb49dab574e80929e764fd50b4a3e5f8c72fe5..f5820079a2860f217662cf5be326497d961575ed 100644 (file)
@@ -145,7 +145,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
                pci_dev_put(dev);
 }
 
-static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
+static void init_iops_cy82c693(ide_hwif_t *hwif)
 {
        static ide_hwif_t *primary;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -163,7 +163,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
        .set_dma_mode           = cy82c693_set_dma_mode,
 };
 
-static const struct ide_port_info cy82c693_chipset __devinitconst = {
+static const struct ide_port_info cy82c693_chipset = {
        .name           = DRV_NAME,
        .init_iops      = init_iops_cy82c693,
        .port_ops       = &cy82c693_port_ops,
@@ -173,7 +173,8 @@ static const struct ide_port_info cy82c693_chipset __devinitconst = {
        .mwdma_mask     = ATA_MWDMA2,
 };
 
-static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int cy82c693_init_one(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        struct pci_dev *dev2;
        int ret = -ENODEV;
@@ -190,7 +191,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
        return ret;
 }
 
-static void __devexit cy82c693_remove(struct pci_dev *dev)
+static void cy82c693_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
@@ -209,7 +210,7 @@ static struct pci_driver cy82c693_pci_driver = {
        .name           = "Cypress_IDE",
        .id_table       = cy82c693_pci_tbl,
        .probe          = cy82c693_init_one,
-       .remove         = __devexit_p(cy82c693_remove),
+       .remove         = cy82c693_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index 1e10eba62ceb7ba97568da89b24162e2b09da2d0..7e27d3295e55e06bbdbbb15ea922756bbe48b775 100644 (file)
@@ -71,8 +71,7 @@ static const struct ide_port_info delkin_cb_port_info = {
        .chipset                = ide_pci,
 };
 
-static int __devinit
-delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+static int delkin_cb_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_host *host;
        unsigned long base;
@@ -158,7 +157,7 @@ static int delkin_cb_resume(struct pci_dev *dev)
 #define delkin_cb_resume NULL
 #endif
 
-static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
+static struct pci_device_id delkin_cb_pci_tbl[] = {
        { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { 0, },
index 4aec3b87ff91aec9b1e575c9c69af1b485a60914..696b6c1ec940fce29de2dc41d5d91d6b860467bf 100644 (file)
@@ -443,7 +443,7 @@ static struct hpt_timings hpt37x_timings = {
        }
 };
 
-static const struct hpt_info hpt36x __devinitconst = {
+static const struct hpt_info hpt36x = {
        .chip_name      = "HPT36x",
        .chip_type      = HPT36x,
        .udma_mask      = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
@@ -451,7 +451,7 @@ static const struct hpt_info hpt36x __devinitconst = {
        .timings        = &hpt36x_timings
 };
 
-static const struct hpt_info hpt370 __devinitconst = {
+static const struct hpt_info hpt370 = {
        .chip_name      = "HPT370",
        .chip_type      = HPT370,
        .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -459,7 +459,7 @@ static const struct hpt_info hpt370 __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt370a __devinitconst = {
+static const struct hpt_info hpt370a = {
        .chip_name      = "HPT370A",
        .chip_type      = HPT370A,
        .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -467,7 +467,7 @@ static const struct hpt_info hpt370a __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt374 __devinitconst = {
+static const struct hpt_info hpt374 = {
        .chip_name      = "HPT374",
        .chip_type      = HPT374,
        .udma_mask      = ATA_UDMA5,
@@ -475,7 +475,7 @@ static const struct hpt_info hpt374 __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372 __devinitconst = {
+static const struct hpt_info hpt372 = {
        .chip_name      = "HPT372",
        .chip_type      = HPT372,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -483,7 +483,7 @@ static const struct hpt_info hpt372 __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372a __devinitconst = {
+static const struct hpt_info hpt372a = {
        .chip_name      = "HPT372A",
        .chip_type      = HPT372A,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -491,7 +491,7 @@ static const struct hpt_info hpt372a __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt302 __devinitconst = {
+static const struct hpt_info hpt302 = {
        .chip_name      = "HPT302",
        .chip_type      = HPT302,
        .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -499,7 +499,7 @@ static const struct hpt_info hpt302 __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt371 __devinitconst = {
+static const struct hpt_info hpt371 = {
        .chip_name      = "HPT371",
        .chip_type      = HPT371,
        .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -507,7 +507,7 @@ static const struct hpt_info hpt371 __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372n __devinitconst = {
+static const struct hpt_info hpt372n = {
        .chip_name      = "HPT372N",
        .chip_type      = HPT372N,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -515,7 +515,7 @@ static const struct hpt_info hpt372n __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt302n __devinitconst = {
+static const struct hpt_info hpt302n = {
        .chip_name      = "HPT302N",
        .chip_type      = HPT302N,
        .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -523,7 +523,7 @@ static const struct hpt_info hpt302n __devinitconst = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt371n __devinitconst = {
+static const struct hpt_info hpt371n = {
        .chip_name      = "HPT371N",
        .chip_type      = HPT371N,
        .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -1197,7 +1197,7 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
        return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
-static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+static void init_hwif_hpt366(ide_hwif_t *hwif)
 {
        struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
        u8  chip_type           = info->chip_type;
@@ -1221,7 +1221,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
        }
 }
 
-static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
+static int init_dma_hpt366(ide_hwif_t *hwif,
                                     const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -1265,7 +1265,7 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
        return 0;
 }
 
-static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
+static void hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
 {
        if (dev2->irq != dev->irq) {
                /* FIXME: we need a core pci_set_interrupt() */
@@ -1275,7 +1275,7 @@ static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
        }
 }
 
-static void __devinit hpt371_init(struct pci_dev *dev)
+static void hpt371_init(struct pci_dev *dev)
 {
        u8 mcr1 = 0;
 
@@ -1290,7 +1290,7 @@ static void __devinit hpt371_init(struct pci_dev *dev)
                pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
 }
 
-static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
+static int hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
 {
        u8 mcr1 = 0, pin1 = 0, pin2 = 0;
 
@@ -1361,7 +1361,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info hpt366_chipsets[] __devinitconst = {
+static const struct ide_port_info hpt366_chipsets[] = {
        {       /* 0: HPT36x */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt366,
@@ -1402,7 +1402,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitconst = {
  *     Called when the PCI registration layer (or the IDE initialization)
  *     finds a device matching our IDE device tables.
  */
-static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct hpt_info *info = NULL;
        struct hpt_info *dyn_info;
@@ -1499,7 +1499,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
        return ret;
 }
 
-static void __devexit hpt366_remove(struct pci_dev *dev)
+static void hpt366_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        struct ide_info *info = host->host_priv;
@@ -1510,7 +1510,7 @@ static void __devexit hpt366_remove(struct pci_dev *dev)
        kfree(info);
 }
 
-static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
+static const struct pci_device_id hpt366_pci_tbl[] = {
        { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366),  0 },
        { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372),  1 },
        { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302),  2 },
@@ -1525,7 +1525,7 @@ static struct pci_driver hpt366_pci_driver = {
        .name           = "HPT366_IDE",
        .id_table       = hpt366_pci_tbl,
        .probe          = hpt366_init_one,
-       .remove         = __devexit_p(hpt366_remove),
+       .remove         = hpt366_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index e640d0ac3af63cad4730fc370fa58bc7e5a7ac1f..9f0a48e39b8aa73c261e75b0aa0704f9efeb7d05 100644 (file)
@@ -406,8 +406,8 @@ static const struct ide_port_info icside_v5_port_info = {
        .chipset                = ide_acorn,
 };
 
-static int __devinit
-icside_register_v5(struct icside_state *state, struct expansion_card *ec)
+static int icside_register_v5(struct icside_state *state,
+                             struct expansion_card *ec)
 {
        void __iomem *base;
        struct ide_host *host;
@@ -460,8 +460,8 @@ static const struct ide_port_info icside_v6_port_info __initconst = {
        .chipset                = ide_acorn,
 };
 
-static int __devinit
-icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+static int icside_register_v6(struct icside_state *state,
+                             struct expansion_card *ec)
 {
        void __iomem *ioc_base, *easi_base;
        struct ide_host *host;
@@ -537,8 +537,7 @@ out:
        return ret;
 }
 
-static int __devinit
-icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int icside_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct icside_state *state;
        void __iomem *idmem;
@@ -604,7 +603,7 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit icside_remove(struct expansion_card *ec)
+static void icside_remove(struct expansion_card *ec)
 {
        struct icside_state *state = ecard_get_drvdata(ec);
 
@@ -666,7 +665,7 @@ static const struct ecard_id icside_ids[] = {
 
 static struct ecard_driver icside_driver = {
        .probe          = icside_probe,
-       .remove         = __devexit_p(icside_remove),
+       .remove         = icside_remove,
        .shutdown       = icside_shutdown,
        .id_table       = icside_ids,
        .drv = {
index dab5b670bfbff335b02346044f1380d262b569f5..673420db953f2f1f641e72fd399481e8eaf89750 100644 (file)
@@ -53,7 +53,7 @@ static const struct ide_port_ops netcell_port_ops = {
                .udma_mask      = ATA_UDMA6, \
        }
 
-static const struct ide_port_info generic_chipsets[] __devinitconst = {
+static const struct ide_port_info generic_chipsets[] = {
        /*  0: Unknown */
        DECLARE_GENERIC_PCI_DEV(0),
 
@@ -103,7 +103,7 @@ static const struct ide_port_info generic_chipsets[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
 
-static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct ide_port_info *d = &generic_chipsets[id->driver_data];
        int ret = -ENODEV;
index 962693b10a1cfc8dc7aa71a8439329cc79f946f3..ba4bfbead24b3f3c09e5afea8da85e739537744d 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
-static void __devinit plat_ide_setup_ports(struct ide_hw *hw,
-                                          void __iomem *base,
-                                          void __iomem *ctrl,
-                                          struct pata_platform_info *pdata,
-                                          int irq)
+static void plat_ide_setup_ports(struct ide_hw *hw, void __iomem *base,
+                                void __iomem *ctrl,
+                                struct pata_platform_info *pdata, int irq)
 {
        unsigned long port = (unsigned long)base;
        int i;
@@ -48,7 +46,7 @@ static const struct ide_port_info platform_ide_port_info = {
        .chipset                = ide_generic,
 };
 
-static int __devinit plat_ide_probe(struct platform_device *pdev)
+static int plat_ide_probe(struct platform_device *pdev)
 {
        struct resource *res_base, *res_alt, *res_irq;
        void __iomem *base, *alt_base;
@@ -115,7 +113,7 @@ out:
        return ret;
 }
 
-static int __devexit plat_ide_remove(struct platform_device *pdev)
+static int plat_ide_remove(struct platform_device *pdev)
 {
        struct ide_host *host = dev_get_drvdata(&pdev->dev);
 
@@ -130,7 +128,7 @@ static struct platform_driver platform_ide_driver = {
                .owner = THIS_MODULE,
        },
        .probe = plat_ide_probe,
-       .remove = __devexit_p(plat_ide_remove),
+       .remove = plat_ide_remove,
 };
 
 static int __init platform_ide_init(void)
index d5dd180c4b85766649ada84c63f2d67f93cdac2e..b6f674ab4fb7c0d4119fa580965d44cc4da272da 100644 (file)
@@ -115,7 +115,7 @@ static const struct ide_port_ops it8172_port_ops = {
        .set_dma_mode   = it8172_set_dma_mode,
 };
 
-static const struct ide_port_info it8172_port_info __devinitconst = {
+static const struct ide_port_info it8172_port_info = {
        .name           = DRV_NAME,
        .port_ops       = &it8172_port_ops,
        .enablebits     = { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} },
@@ -125,8 +125,7 @@ static const struct ide_port_info it8172_port_info __devinitconst = {
        .udma_mask      = ATA_UDMA2,
 };
 
-static int __devinit it8172_init_one(struct pci_dev *dev,
-                                       const struct pci_device_id *id)
+static int it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
                return -ENODEV; /* IT8172 is more than an IDE controller */
index 1847aeb5450aa7d698bc1308832f0562a1202997..6b92846682fc26553c6ced0d2954ffda4dad94e9 100644 (file)
@@ -156,7 +156,7 @@ static const struct ide_port_ops it8213_port_ops = {
        .cable_detect           = it8213_cable_detect,
 };
 
-static const struct ide_port_info it8213_chipset __devinitconst = {
+static const struct ide_port_info it8213_chipset = {
        .name           = DRV_NAME,
        .enablebits     = { {0x41, 0x80, 0x80} },
        .port_ops       = &it8213_port_ops,
@@ -177,7 +177,7 @@ static const struct ide_port_info it8213_chipset __devinitconst = {
  *     standard helper functions to do almost all the work for us.
  */
 
-static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &it8213_chipset, NULL);
 }
index c5611dbca34241dfe2f68078c3693f44a1dd4338..f01ba4606be0eb412ea6347d9f6c14ca04801710 100644 (file)
@@ -528,7 +528,7 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = {
  *     ide DMA handlers appropriately
  */
 
-static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+static void init_hwif_it821x(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct ide_host *host = pci_get_drvdata(dev);
@@ -630,7 +630,7 @@ static const struct ide_port_ops it821x_port_ops = {
        .cable_detect           = it821x_cable_detect,
 };
 
-static const struct ide_port_info it821x_chipset __devinitconst = {
+static const struct ide_port_info it821x_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_it821x,
        .init_hwif      = init_hwif_it821x,
@@ -647,7 +647,7 @@ static const struct ide_port_info it821x_chipset __devinitconst = {
  *     We then use the IDE PCI generic helper to do most of the work.
  */
 
-static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct it821x_dev *itdevs;
        int rc;
@@ -667,7 +667,7 @@ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_devic
        return rc;
 }
 
-static void __devexit it821x_remove(struct pci_dev *dev)
+static void it821x_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        struct it821x_dev *itdevs = host->host_priv;
@@ -689,7 +689,7 @@ static struct pci_driver it821x_pci_driver = {
        .name           = "ITE821x IDE",
        .id_table       = it821x_pci_tbl,
        .probe          = it821x_init_one,
-       .remove         = __devexit_p(it821x_remove),
+       .remove         = it821x_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index efddd7d9f92d9b5f983bd41f4d6eac2f564eac2a..ae6480dcbadf28e92860dd140302a864d57a5583 100644 (file)
@@ -102,7 +102,7 @@ static const struct ide_port_ops jmicron_port_ops = {
        .cable_detect           = jmicron_cable_detect,
 };
 
-static const struct ide_port_info jmicron_chipset __devinitconst = {
+static const struct ide_port_info jmicron_chipset = {
        .name           = DRV_NAME,
        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
        .port_ops       = &jmicron_port_ops,
@@ -120,7 +120,7 @@ static const struct ide_port_info jmicron_chipset __devinitconst = {
  *     We then use the IDE PCI generic helper to do most of the work.
  */
 
-static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &jmicron_chipset, NULL);
 }
index 73f78d872d551cf5be82b690672daddc7be97cb8..392fd106edf1e0f504be3e6211a2a2862755f475 100644 (file)
@@ -96,7 +96,7 @@ static const struct ide_tp_ops superio_tp_ops = {
        .output_data            = ide_output_data,
 };
 
-static void __devinit superio_init_iops(struct hwif_s *hwif)
+static void superio_init_iops(struct hwif_s *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
        u32 dma_stat;
@@ -201,7 +201,7 @@ static int ns87415_dma_end(ide_drive_t *drive)
        return (dma_stat & 7) != 4;
 }
 
-static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+static void init_hwif_ns87415 (ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned int ctrl, using_inta;
@@ -293,7 +293,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
        .dma_sff_read_status    = superio_dma_sff_read_status,
 };
 
-static const struct ide_port_info ns87415_chipset __devinitconst = {
+static const struct ide_port_info ns87415_chipset = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_ns87415,
        .tp_ops         = &ns87415_tp_ops,
@@ -302,7 +302,7 @@ static const struct ide_port_info ns87415_chipset __devinitconst = {
                          IDE_HFLAG_NO_ATAPI_DMA,
 };
 
-static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d = ns87415_chipset;
 
index 39edc66cb96cfb52b613fc481de36270b584223c..26a45007e535093a16545a2a43cb4e839a4dff68 100644 (file)
@@ -131,7 +131,7 @@ static const struct ide_port_ops opti621_port_ops = {
        .set_pio_mode           = opti621_set_pio_mode,
 };
 
-static const struct ide_port_info opti621_chipset __devinitconst = {
+static const struct ide_port_info opti621_chipset = {
        .name           = DRV_NAME,
        .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
        .port_ops       = &opti621_port_ops,
@@ -139,7 +139,7 @@ static const struct ide_port_info opti621_chipset __devinitconst = {
        .pio_mask       = ATA_PIO4,
 };
 
-static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &opti621_chipset, NULL);
 }
index 712c7904d03e5d460854cc565bf139bf29f3290e..6107cc4ee012a16b27f1e0bb75bc328fbca89445 100644 (file)
@@ -220,7 +220,7 @@ static void palm_bk3710_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
        palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
 }
 
-static void __devinit palm_bk3710_chipinit(void __iomem *base)
+static void palm_bk3710_chipinit(void __iomem *base)
 {
        /*
         * REVISIT:  the ATA reset signal needs to be managed through a
@@ -282,8 +282,7 @@ static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif)
        return ATA_CBL_PATA80;
 }
 
-static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
-                                         const struct ide_port_info *d)
+static int palm_bk3710_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
 
@@ -301,7 +300,7 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
        .cable_detect           = palm_bk3710_cable_detect,
 };
 
-static struct ide_port_info __devinitdata palm_bk3710_port_info = {
+static struct ide_port_info palm_bk3710_port_info = {
        .init_dma               = palm_bk3710_init_dma,
        .port_ops               = &palm_bk3710_ports_ops,
        .dma_ops                = &sff_dma_ops,
index 2e5ceb62fb3b38d461f2c61fa6c534e47ade22c6..df73cbd9387e89195eca1e30438cc04ae2f33be5 100644 (file)
@@ -422,7 +422,7 @@ static int init_chipset_pdcnew(struct pci_dev *dev)
        return 0;
 }
 
-static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
+static struct pci_dev *pdc20270_get_dev2(struct pci_dev *dev)
 {
        struct pci_dev *dev2;
 
@@ -465,7 +465,7 @@ static const struct ide_port_ops pdcnew_port_ops = {
                .udma_mask      = udma, \
        }
 
-static const struct ide_port_info pdcnew_chipsets[] __devinitconst = {
+static const struct ide_port_info pdcnew_chipsets[] = {
        /* 0: PDC202{68,70} */          DECLARE_PDCNEW_DEV(ATA_UDMA5),
        /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
 };
@@ -479,7 +479,7 @@ static const struct ide_port_info pdcnew_chipsets[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
  
-static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
        struct pci_dev *bridge = dev->bus->self;
@@ -514,7 +514,7 @@ static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_de
        return ide_pci_init_one(dev, d, NULL);
 }
 
-static void __devexit pdc202new_remove(struct pci_dev *dev)
+static void pdc202new_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
@@ -539,7 +539,7 @@ static struct pci_driver pdc202new_pci_driver = {
        .name           = "Promise_IDE",
        .id_table       = pdc202new_pci_tbl,
        .probe          = pdc202new_init_one,
-       .remove         = __devexit_p(pdc202new_remove),
+       .remove         = pdc202new_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index 5634510968128f499bf136959619a444328d0e2a..224ad46d6cb22494972790fc9b37e0f6e75a2fd9 100644 (file)
@@ -211,8 +211,7 @@ out:
        return 0;
 }
 
-static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
-                                          const char *name)
+static void pdc202ata4_fixup_irq(struct pci_dev *dev, const char *name)
 {
        if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
                u8 irq = 0, irq2 = 0;
@@ -270,7 +269,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
                .max_sectors    = sectors, \
        }
 
-static const struct ide_port_info pdc202xx_chipsets[] __devinitconst = {
+static const struct ide_port_info pdc202xx_chipsets[] = {
        {       /* 0: PDC20246 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_pdc202xx,
@@ -297,7 +296,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
  
-static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int pdc202xx_init_one(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        const struct ide_port_info *d;
        u8 idx = id->driver_data;
index fe0fd60cfc09040e3e47e9dadd8e455ba610f421..a671cead6ae72b7e95bbd297053e22900f6806c9 100644 (file)
@@ -297,7 +297,7 @@ static u8 piix_cable_detect(ide_hwif_t *hwif)
  *     capabilities of the hardware.
  */
 
-static void __devinit init_hwif_piix(ide_hwif_t *hwif)
+static void init_hwif_piix(ide_hwif_t *hwif)
 {
        if (!hwif->dma_base)
                return;
@@ -344,7 +344,7 @@ static const struct ide_port_ops ich_port_ops = {
                .udma_mask      = udma, \
        }
 
-static const struct ide_port_info piix_pci_info[] __devinitconst = {
+static const struct ide_port_info piix_pci_info[] = {
        /* 0: MPIIX */
        {       /*
                 * MPIIX actually has only a single IDE channel mapped to
@@ -382,7 +382,7 @@ static const struct ide_port_info piix_pci_info[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
  
-static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
 }
@@ -394,7 +394,7 @@ static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_
  *     they are found, disable use of DMA IDE
  */
 
-static void __devinit piix_check_450nx(void)
+static void piix_check_450nx(void)
 {
        struct pci_dev *pdev = NULL;
        u16 cfg;
index e944c7f705f7803ea18dbd8707b48a95f5cff52f..bf83d7bb6bc647a5ab92fb2055afe0b34ad25f8b 100644 (file)
@@ -1025,8 +1025,7 @@ static const struct ide_port_info pmac_port_info = {
  * Setup, register & probe an IDE channel driven by this driver, this is
  * called by one of the 2 probe functions (macio or PCI).
  */
-static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
-                                          struct ide_hw *hw)
+static int pmac_ide_setup_device(pmac_ide_hwif_t *pmif, struct ide_hw *hw)
 {
        struct device_node *np = pmif->node;
        const int *bidp;
@@ -1126,7 +1125,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
        return rc;
 }
 
-static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
+static void pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
 {
        int i;
 
@@ -1139,8 +1138,8 @@ static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
 /*
  * Attach to a macio probed interface
  */
-static int __devinit
-pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+static int pmac_ide_macio_attach(struct macio_dev *mdev,
+                                const struct of_device_id *match)
 {
        void __iomem *base;
        unsigned long regbase;
@@ -1262,8 +1261,8 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
 /*
  * Attach to a PCI probed interface
  */
-static int __devinit
-pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+static int pmac_ide_pci_attach(struct pci_dev *pdev,
+                              const struct pci_device_id *id)
 {
        struct device_node *np;
        pmac_ide_hwif_t *pmif;
@@ -1692,8 +1691,7 @@ static const struct ide_dma_ops pmac_dma_ops = {
  * Allocate the data structures needed for using DMA with an interface
  * and fill the proper list of functions pointers
  */
-static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
-                                      const struct ide_port_info *d)
+static int pmac_ide_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
index 48d976aad7abaf685754ea647280c21ff4c99c38..d73c3d10087c72133d5db9bd5902ea1e94758008 100644 (file)
@@ -29,8 +29,7 @@ static void rapide_setup_ports(struct ide_hw *hw, void __iomem *base,
        hw->irq = irq;
 }
 
-static int __devinit
-rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        void __iomem *base;
        struct ide_host *host;
@@ -64,7 +63,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit rapide_remove(struct expansion_card *ec)
+static void rapide_remove(struct expansion_card *ec)
 {
        struct ide_host *host = ecard_get_drvdata(ec);
 
@@ -82,7 +81,7 @@ static struct ecard_id rapide_ids[] = {
 
 static struct ecard_driver rapide_driver = {
        .probe          = rapide_probe,
-       .remove         = __devexit_p(rapide_remove),
+       .remove         = rapide_remove,
        .id_table       = rapide_ids,
        .drv = {
                .name   = "rapide",
index c04173e9fc38264326536088bd7c28aeb64adeff..f4b66f7ec9fd2153c47c45e87b73e84d9c85c161 100644 (file)
@@ -22,7 +22,7 @@
 
 #define DRV_NAME "rz1000"
 
-static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
+static int rz1000_disable_readahead(struct pci_dev *dev)
 {
        u16 reg;
 
@@ -38,12 +38,12 @@ static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
        }
 }
 
-static const struct ide_port_info rz1000_chipset __devinitconst = {
+static const struct ide_port_info rz1000_chipset = {
        .name           = DRV_NAME,
        .host_flags     = IDE_HFLAG_NO_DMA,
 };
 
-static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d = rz1000_chipset;
        int rc;
index d4758ebe77da66586f2ff16c2b06ab3d25cd5fae..a5b701818405ba6eb9b7d8fada5462cf9d1d53cb 100644 (file)
@@ -291,7 +291,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sc1200_chipset __devinitconst = {
+static const struct ide_port_info sc1200_chipset = {
        .name           = DRV_NAME,
        .port_ops       = &sc1200_port_ops,
        .dma_ops        = &sc1200_dma_ops,
@@ -303,7 +303,7 @@ static const struct ide_port_info sc1200_chipset __devinitconst = {
        .udma_mask      = ATA_UDMA2,
 };
 
-static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct sc1200_saved_state *ss = NULL;
        int rc;
index 9701038100216e03d77c113b34354c193573edb4..2a2d188b5d5b45c239bcdad5ae2361774cd97c45 100644 (file)
@@ -585,8 +585,7 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
  *     Perform the initial set up for this device.
  */
 
-static int __devinit init_setup_scc(struct pci_dev *dev,
-                                   const struct ide_port_info *d)
+static int init_setup_scc(struct pci_dev *dev, const struct ide_port_info *d)
 {
        unsigned long ctl_base;
        unsigned long dma_base;
@@ -718,7 +717,7 @@ static void scc_output_data(ide_drive_t *drive,  struct ide_cmd *cmd,
  *
  */
 
-static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+static void init_mmio_iops_scc(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct scc_ports *ports = pci_get_drvdata(dev);
@@ -738,7 +737,7 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
  *     and then do the MMIO setup.
  */
 
-static void __devinit init_iops_scc(ide_hwif_t *hwif)
+static void init_iops_scc(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
 
@@ -748,8 +747,7 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
        init_mmio_iops_scc(hwif);
 }
 
-static int __devinit scc_init_dma(ide_hwif_t *hwif,
-                                 const struct ide_port_info *d)
+static int scc_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        return ide_allocate_dma_engine(hwif);
 }
@@ -768,7 +766,7 @@ static u8 scc_cable_detect(ide_hwif_t *hwif)
  *     ide DMA handlers appropriately.
  */
 
-static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+static void init_hwif_scc(ide_hwif_t *hwif)
 {
        /* PTERADD */
        out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
@@ -811,7 +809,7 @@ static const struct ide_dma_ops scc_dma_ops = {
        .dma_sff_read_status    = scc_dma_sff_read_status,
 };
 
-static const struct ide_port_info scc_chipset __devinitconst = {
+static const struct ide_port_info scc_chipset = {
        .name           = "sccIDE",
        .init_iops      = init_iops_scc,
        .init_dma       = scc_init_dma,
@@ -834,7 +832,7 @@ static const struct ide_port_info scc_chipset __devinitconst = {
  *     We then use the IDE PCI generic helper to do most of the work.
  */
 
-static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return init_setup_scc(dev, &scc_chipset);
 }
@@ -846,7 +844,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
  *     Called by the PCI code when it removes an SCC PATA controller.
  */
 
-static void __devexit scc_remove(struct pci_dev *dev)
+static void scc_remove(struct pci_dev *dev)
 {
        struct scc_ports *ports = pci_get_drvdata(dev);
        struct ide_host *host = ports->host;
@@ -869,7 +867,7 @@ static struct pci_driver scc_pci_driver = {
        .name = "SCC IDE",
        .id_table = scc_pci_tbl,
        .probe = scc_init_one,
-       .remove = __devexit_p(scc_remove),
+       .remove = scc_remove,
 };
 
 static int __init scc_ide_init(void)
index 24d72ef23df7cd550270a78e2ff04a74c37464ab..a97affca18abe153be1ba4b3285d25390171e69c 100644 (file)
@@ -337,7 +337,7 @@ static const struct ide_port_ops svwks_port_ops = {
        .cable_detect           = svwks_cable_detect,
 };
 
-static const struct ide_port_info serverworks_chipsets[] __devinitconst = {
+static const struct ide_port_info serverworks_chipsets[] = {
        {       /* 0: OSB4 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
@@ -391,7 +391,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitconst = {
  *     finds a device matching our IDE device tables.
  */
  
-static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d;
        u8 idx = id->driver_data;
index e3ea591f66d36893e7d74ccc14f297ce673f9afd..a5ca179a83b35419e3f0f8afd8b6e17629fbcda8 100644 (file)
@@ -307,8 +307,7 @@ static u8 sgiioc4_read_status(ide_hwif_t *hwif)
 }
 
 /* Creates a DMA map for the scatter-gather list entries */
-static int __devinit ide_dma_sgiioc4(ide_hwif_t *hwif,
-                                    const struct ide_port_info *d)
+static int ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
@@ -520,7 +519,7 @@ static const struct ide_dma_ops sgiioc4_dma_ops = {
        .dma_lost_irq           = sgiioc4_dma_lost_irq,
 };
 
-static const struct ide_port_info sgiioc4_port_info __devinitconst = {
+static const struct ide_port_info sgiioc4_port_info = {
        .name                   = DRV_NAME,
        .chipset                = ide_pci,
        .init_dma               = ide_dma_sgiioc4,
@@ -532,7 +531,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitconst = {
        .mwdma_mask             = ATA_MWDMA2_ONLY,
 };
 
-static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+static int sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
 {
        unsigned long cmd_base, irqport;
        unsigned long bar0, cmd_phys_base, ctl;
@@ -581,7 +580,7 @@ req_mem_rgn_err:
        return rc;
 }
 
-static unsigned int __devinit pci_init_sgiioc4(struct pci_dev *dev)
+static unsigned int pci_init_sgiioc4(struct pci_dev *dev)
 {
        int ret;
 
@@ -601,7 +600,7 @@ out:
        return ret;
 }
 
-int __devinit ioc4_ide_attach_one(struct ioc4_driver_data *idd)
+int ioc4_ide_attach_one(struct ioc4_driver_data *idd)
 {
        /*
         * PCI-RT does not bring out IDE connection.
@@ -613,7 +612,7 @@ int __devinit ioc4_ide_attach_one(struct ioc4_driver_data *idd)
        return pci_init_sgiioc4(idd->idd_pdev);
 }
 
-static struct ioc4_submodule __devinitdata ioc4_ide_submodule = {
+static struct ioc4_submodule ioc4_ide_submodule = {
        .is_name = "IOC4_ide",
        .is_owner = THIS_MODULE,
        .is_probe = ioc4_ide_attach_one,
index 46f7e30d379038bcd47575952f02f5a61996a1f4..6a1849bb476ce1ad78e438dee2f55120cf3c8924 100644 (file)
@@ -546,7 +546,7 @@ static int init_chipset_siimage(struct pci_dev *dev)
  *     extended PRD tables. For better SI3112 support use the libata driver
  */
 
-static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+static void init_mmio_iops_siimage(ide_hwif_t *hwif)
 {
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        struct ide_host *host   = pci_get_drvdata(dev);
@@ -646,7 +646,7 @@ static void sil_quirkproc(ide_drive_t *drive)
  *     can get the iops right before using them.
  */
 
-static void __devinit init_iops_siimage(ide_hwif_t *hwif)
+static void init_iops_siimage(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct ide_host *host = pci_get_drvdata(dev);
@@ -719,7 +719,7 @@ static const struct ide_dma_ops sil_dma_ops = {
                .udma_mask      = ATA_UDMA6,            \
        }
 
-static const struct ide_port_info siimage_chipsets[] __devinitconst = {
+static const struct ide_port_info siimage_chipsets[] = {
        /* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
        /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
 };
@@ -733,8 +733,7 @@ static const struct ide_port_info siimage_chipsets[] __devinitconst = {
  *     We then use the IDE PCI generic helper to do most of the work.
  */
 
-static int __devinit siimage_init_one(struct pci_dev *dev,
-                                     const struct pci_device_id *id)
+static int siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        void __iomem *ioaddr = NULL;
        resource_size_t bar5 = pci_resource_start(dev, 5);
@@ -790,7 +789,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
        return rc;
 }
 
-static void __devexit siimage_remove(struct pci_dev *dev)
+static void siimage_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        void __iomem *ioaddr = host->host_priv;
@@ -822,7 +821,7 @@ static struct pci_driver siimage_pci_driver = {
        .name           = "SiI_IDE",
        .id_table       = siimage_pci_tbl,
        .probe          = siimage_init_one,
-       .remove         = __devexit_p(siimage_remove),
+       .remove         = siimage_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index 09e61b4c5e94f5331413ae52f56ff8a93983ed85..247853ea1368b7c0a83db3e9f1094616ac7f8b5e 100644 (file)
@@ -362,7 +362,7 @@ static u8 sis_ata133_udma_filter(ide_drive_t *drive)
        return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
 }
 
-static int __devinit sis_find_family(struct pci_dev *dev)
+static int sis_find_family(struct pci_dev *dev)
 {
        struct pci_dev *host;
        int i = 0;
@@ -563,7 +563,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
        .cable_detect           = sis_cable_detect,
 };
 
-static const struct ide_port_info sis5513_chipset __devinitconst = {
+static const struct ide_port_info sis5513_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_sis5513,
        .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
@@ -572,7 +572,7 @@ static const struct ide_port_info sis5513_chipset __devinitconst = {
        .mwdma_mask     = ATA_MWDMA2,
 };
 
-static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d = sis5513_chipset;
        u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
@@ -595,7 +595,7 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
        return ide_pci_init_one(dev, &d, NULL);
 }
 
-static void __devexit sis5513_remove(struct pci_dev *dev)
+static void sis5513_remove(struct pci_dev *dev)
 {
        ide_pci_remove(dev);
        pci_disable_device(dev);
@@ -613,7 +613,7 @@ static struct pci_driver sis5513_pci_driver = {
        .name           = "SIS_IDE",
        .id_table       = sis5513_pci_tbl,
        .probe          = sis5513_init_one,
-       .remove         = __devexit_p(sis5513_remove),
+       .remove         = sis5513_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index d051cd224bdbe363a2b43fcc3d1c87e0bc4105ba..8755df3330a06d6e0dbb18823860c95304382b84 100644 (file)
@@ -299,7 +299,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sl82c105_chipset __devinitconst = {
+static const struct ide_port_info sl82c105_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_sl82c105,
        .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
@@ -313,7 +313,7 @@ static const struct ide_port_info sl82c105_chipset __devinitconst = {
        .mwdma_mask     = ATA_MWDMA2,
 };
 
-static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct ide_port_info d = sl82c105_chipset;
        u8 rev = sl82c105_bridge_revision(dev);
index 863a5e9283ca189895f53e3f233a0b75af0777d3..8af92bbb3dcba164b44b88fdafd2dbf465aee47c 100644 (file)
@@ -132,7 +132,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
        .cable_detect           = slc90e66_cable_detect,
 };
 
-static const struct ide_port_info slc90e66_chipset __devinitconst = {
+static const struct ide_port_info slc90e66_chipset = {
        .name           = DRV_NAME,
        .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
        .port_ops       = &slc90e66_port_ops,
@@ -142,7 +142,8 @@ static const struct ide_port_info slc90e66_chipset __devinitconst = {
        .udma_mask      = ATA_UDMA4,
 };
 
-static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int slc90e66_init_one(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
 }
index 17946785ebf672c3e615b8761cb31da533e28b4e..17e6132b99bf01b4241258035a187477705e73ee 100644 (file)
@@ -144,7 +144,7 @@ static u8 tc86c001_cable_detect(ide_hwif_t *hwif)
        return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
-static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+static void init_hwif_tc86c001(ide_hwif_t *hwif)
 {
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        unsigned long sc_base   = pci_resource_start(dev, 5);
@@ -192,7 +192,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info tc86c001_chipset __devinitconst = {
+static const struct ide_port_info tc86c001_chipset = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_tc86c001,
        .port_ops       = &tc86c001_port_ops,
@@ -203,8 +203,8 @@ static const struct ide_port_info tc86c001_chipset __devinitconst = {
        .udma_mask      = ATA_UDMA4,
 };
 
-static int __devinit tc86c001_init_one(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+static int tc86c001_init_one(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        int rc;
 
@@ -232,7 +232,7 @@ out:
        return rc;
 }
 
-static void __devexit tc86c001_remove(struct pci_dev *dev)
+static void tc86c001_remove(struct pci_dev *dev)
 {
        ide_pci_remove(dev);
        pci_release_region(dev, 5);
@@ -249,7 +249,7 @@ static struct pci_driver tc86c001_pci_driver = {
        .name           = "TC86C001",
        .id_table       = tc86c001_pci_tbl,
        .probe          = tc86c001_init_one,
-       .remove         = __devexit_p(tc86c001_remove),
+       .remove         = tc86c001_remove,
 };
 
 static int __init tc86c001_ide_init(void)
index 55ce1b80efcbd861161595c2d10f55439129eb0b..7f1af9493f0efbb92fc6fa06ac6a3f7d4a59b689 100644 (file)
@@ -92,7 +92,7 @@ static const struct ide_port_ops triflex_port_ops = {
        .set_dma_mode           = triflex_set_mode,
 };
 
-static const struct ide_port_info triflex_device __devinitconst = {
+static const struct ide_port_info triflex_device = {
        .name           = DRV_NAME,
        .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
        .port_ops       = &triflex_port_ops,
@@ -101,8 +101,7 @@ static const struct ide_port_info triflex_device __devinitconst = {
        .mwdma_mask     = ATA_MWDMA2,
 };
 
-static int __devinit triflex_init_one(struct pci_dev *dev, 
-               const struct pci_device_id *id)
+static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &triflex_device, NULL);
 }
index e494a98a43a9ba2cebd5111c5839073e8130e39b..0069f6ce74cf507071119105de916de5ead8a989 100644 (file)
@@ -231,7 +231,7 @@ static void trm290_dma_host_set(ide_drive_t *drive, int on)
 {
 }
 
-static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+static void init_hwif_trm290(ide_hwif_t *hwif)
 {
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        unsigned int  cfg_base  = pci_resource_start(dev, 4);
@@ -324,7 +324,7 @@ static struct ide_dma_ops trm290_dma_ops = {
        .dma_check              = trm290_dma_check,
 };
 
-static const struct ide_port_info trm290_chipset __devinitconst = {
+static const struct ide_port_info trm290_chipset = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_trm290,
        .tp_ops         = &trm290_tp_ops,
@@ -338,7 +338,7 @@ static const struct ide_port_info trm290_chipset __devinitconst = {
                          IDE_HFLAG_NO_LBA48,
 };
 
-static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        return ide_pci_init_one(dev, &trm290_chipset, NULL);
 }
index eb7767864d10530ce2a72485823fb615ca1436d9..01464f1e233998cbb18b72e62513f353f4653eec 100644 (file)
@@ -403,7 +403,7 @@ static const struct ide_port_ops via_port_ops = {
        .cable_detect           = via82cxxx_cable_detect,
 };
 
-static const struct ide_port_info via82cxxx_chipset __devinitconst = {
+static const struct ide_port_info via82cxxx_chipset = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
@@ -416,7 +416,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitconst = {
        .mwdma_mask     = ATA_MWDMA2,
 };
 
-static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct pci_dev *isa = NULL;
        struct via_isa_bridge *via_config;
@@ -489,7 +489,7 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
        return rc;
 }
 
-static void __devexit via_remove(struct pci_dev *dev)
+static void via_remove(struct pci_dev *dev)
 {
        struct ide_host *host = pci_get_drvdata(dev);
        struct via82cxxx_dev *vdev = host->host_priv;
@@ -514,7 +514,7 @@ static struct pci_driver via_pci_driver = {
        .name           = "VIA_IDE",
        .id_table       = via_pci_tbl,
        .probe          = via_init_one,
-       .remove         = __devexit_p(via_remove),
+       .remove         = via_remove,
        .suspend        = ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
index c49c04d9c2b07b7cdb1a2372e4f383885339bcbc..2df9414a72f7169fe1fccaec285c633ca45f75d1 100644 (file)
@@ -448,8 +448,6 @@ static int intel_idle_probe(void)
        else
                on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
 
-       register_cpu_notifier(&cpu_hotplug_notifier);
-
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
@@ -506,7 +504,7 @@ static int intel_idle_cpuidle_driver_init(void)
                        if (*cpuidle_state_table[cstate].name == '\0')
                                pr_debug(PREFIX "unaware of model 0x%x"
                                        " MWAIT %d please"
-                                       " contact lenb@kernel.org",
+                                       " contact lenb@kernel.org\n",
                                boot_cpu_data.x86_model, cstate);
                        continue;
                }
@@ -612,6 +610,7 @@ static int __init intel_idle_init(void)
                        return retval;
                }
        }
+       register_cpu_notifier(&cpu_hotplug_notifier);
 
        return 0;
 }
index fe4bcd7c5b12ea9ef5e4f23b56c25169038ad570..05e996fafc9d42a8dd76031dedbfd6b1d8520d0a 100644 (file)
@@ -8,6 +8,7 @@ config HID_SENSOR_ACCEL_3D
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select HID_SENSOR_IIO_COMMON
+       select HID_SENSOR_IIO_TRIGGER
        tristate "HID Accelerometers 3D"
        help
          Say yes here to build support for the HID SENSOR
index e67bb912bd197b90de0cfccfda2a50041325c52f..0b0c3c66f6c07f8778c96ec76b513db80a16cf7a 100644 (file)
@@ -278,7 +278,7 @@ static int accel_3d_parse_report(struct platform_device *pdev,
 }
 
 /* Function to initialize the processing for usage id */
-static int __devinit hid_accel_3d_probe(struct platform_device *pdev)
+static int hid_accel_3d_probe(struct platform_device *pdev)
 {
        int ret = 0;
        static const char *name = "accel_3d";
@@ -375,7 +375,7 @@ error_ret:
 }
 
 /* Function to deinitialize the processing for usage id */
-static int __devinit hid_accel_3d_remove(struct platform_device *pdev)
+static int hid_accel_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
index a6f4fc5f8201a414f653d86db92b7ef03a9c1705..bbad9b94cd75770b136499728497ff73ce4067d9 100644 (file)
@@ -367,7 +367,7 @@ static const struct ad7266_chan_info ad7266_chan_infos[] = {
        },
 };
 
-static void __devinit ad7266_init_channels(struct iio_dev *indio_dev)
+static void ad7266_init_channels(struct iio_dev *indio_dev)
 {
        struct ad7266_state *st = iio_priv(indio_dev);
        bool is_differential, is_signed;
@@ -391,7 +391,7 @@ static const char * const ad7266_gpio_labels[] = {
        "AD0", "AD1", "AD2",
 };
 
-static int __devinit ad7266_probe(struct spi_device *spi)
+static int ad7266_probe(struct spi_device *spi)
 {
        struct ad7266_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -411,7 +411,11 @@ static int __devinit ad7266_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg;
 
-               st->vref_uv = regulator_get_voltage(st->reg);
+               ret = regulator_get_voltage(st->reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               st->vref_uv = ret;
        } else {
                /* Use internal reference */
                st->vref_uv = 2500000;
@@ -494,7 +498,7 @@ error_put_reg:
        return ret;
 }
 
-static int __devexit ad7266_remove(struct spi_device *spi)
+static int ad7266_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7266_state *st = iio_priv(indio_dev);
@@ -525,7 +529,7 @@ static struct spi_driver ad7266_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad7266_probe,
-       .remove         = __devexit_p(ad7266_remove),
+       .remove         = ad7266_remove,
        .id_table       = ad7266_id,
 };
 module_spi_driver(ad7266_driver);
index 2364807a5d6c47e358b9706a0d5d524eed161021..b34d754994d50d53f60fee694440658ba0b137dd 100644 (file)
@@ -292,7 +292,7 @@ static const struct iio_info ad7298_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad7298_probe(struct spi_device *spi)
+static int ad7298_probe(struct spi_device *spi)
 {
        struct ad7298_platform_data *pdata = spi->dev.platform_data;
        struct ad7298_state *st;
@@ -370,7 +370,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad7298_remove(struct spi_device *spi)
+static int ad7298_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7298_state *st = iio_priv(indio_dev);
@@ -398,7 +398,7 @@ static struct spi_driver ad7298_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad7298_probe,
-       .remove         = __devexit_p(ad7298_remove),
+       .remove         = ad7298_remove,
        .id_table       = ad7298_id,
 };
 module_spi_driver(ad7298_driver);
index 330248bfebaecffdf8b042738f64ff134a8a73f8..1491fa6debb2c5e2cc8be063fbf3409e7b5d0b40 100644 (file)
@@ -207,7 +207,7 @@ static const struct iio_info ad7476_info = {
        .read_raw = &ad7476_read_raw,
 };
 
-static int __devinit ad7476_probe(struct spi_device *spi)
+static int ad7476_probe(struct spi_device *spi)
 {
        struct ad7476_state *st;
        struct iio_dev *indio_dev;
@@ -277,7 +277,7 @@ error_ret:
        return ret;
 }
 
-static int __devexit ad7476_remove(struct spi_device *spi)
+static int ad7476_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7476_state *st = iio_priv(indio_dev);
@@ -322,7 +322,7 @@ static struct spi_driver ad7476_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad7476_probe,
-       .remove         = __devexit_p(ad7476_remove),
+       .remove         = ad7476_remove,
        .id_table       = ad7476_id,
 };
 module_spi_driver(ad7476_driver);
index e93740843b2b899de66b81b40834f1b607de8837..5e8d1da6887fb0de7d995f00daf6b7304f3f8860 100644 (file)
@@ -325,8 +325,8 @@ static const struct iio_info ad7791_no_filter_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad7791_setup(struct ad7791_state *st,
-       struct ad7791_platform_data *pdata)
+static int ad7791_setup(struct ad7791_state *st,
+                       struct ad7791_platform_data *pdata)
 {
        /* Set to poweron-reset default values */
        st->mode = AD7791_MODE_BUFFER;
@@ -349,7 +349,7 @@ static int __devinit ad7791_setup(struct ad7791_state *st,
                st->mode);
 }
 
-static int __devinit ad7791_probe(struct spi_device *spi)
+static int ad7791_probe(struct spi_device *spi)
 {
        struct ad7791_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -418,7 +418,7 @@ err_iio_free:
        return ret;
 }
 
-static int __devexit ad7791_remove(struct spi_device *spi)
+static int ad7791_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7791_state *st = iio_priv(indio_dev);
@@ -450,7 +450,7 @@ static struct spi_driver ad7791_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad7791_probe,
-       .remove         = __devexit_p(ad7791_remove),
+       .remove         = ad7791_remove,
        .id_table       = ad7791_spi_ids,
 };
 module_spi_driver(ad7791_driver);
index 81153fafac7a928fa4f15cff0ba8dee55da026ec..a33d5cd1a53696062596f53f8a6216c61a0c7661 100644 (file)
@@ -233,7 +233,7 @@ static const struct iio_info ad7887_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad7887_probe(struct spi_device *spi)
+static int ad7887_probe(struct spi_device *spi)
 {
        struct ad7887_platform_data *pdata = spi->dev.platform_data;
        struct ad7887_state *st;
@@ -340,7 +340,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad7887_remove(struct spi_device *spi)
+static int ad7887_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7887_state *st = iio_priv(indio_dev);
@@ -368,7 +368,7 @@ static struct spi_driver ad7887_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad7887_probe,
-       .remove         = __devexit_p(ad7887_remove),
+       .remove         = ad7887_remove,
        .id_table       = ad7887_id,
 };
 module_spi_driver(ad7887_driver);
index 03b85940f4ba373ac9f2e907418e513d9374b264..a526c0e3aaa84be092d25789d3ccaffd0d056204 100644 (file)
@@ -80,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
                *timestamp = pf->timestamp;
        }
 
-       iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
+       iio_push_to_buffers(idev, (u8 *)st->buffer);
 
        iio_trigger_notify_done(idev->trig);
 
@@ -514,7 +514,7 @@ static const struct iio_info at91_adc_info = {
        .read_raw = &at91_adc_read_raw,
 };
 
-static int __devinit at91_adc_probe(struct platform_device *pdev)
+static int at91_adc_probe(struct platform_device *pdev)
 {
        unsigned int prsc, mstrclk, ticks, adc_clk;
        int ret;
@@ -678,7 +678,7 @@ error_ret:
        return ret;
 }
 
-static int __devexit at91_adc_remove(struct platform_device *pdev)
+static int at91_adc_remove(struct platform_device *pdev)
 {
        struct iio_dev *idev = platform_get_drvdata(pdev);
        struct at91_adc_state *st = iio_priv(idev);
@@ -702,7 +702,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
 
 static struct platform_driver at91_adc_driver = {
        .probe = at91_adc_probe,
-       .remove = __devexit_p(at91_adc_remove),
+       .remove = at91_adc_remove,
        .driver = {
                   .name = "at91_adc",
                   .of_match_table = of_match_ptr(at91_adc_dt_ids),
index a93aaf0bb8415e1c6e2030269e79923d7eafdc99..72955e45e9e043bf96bd4d177abefe4d8b1e5e95 100644 (file)
@@ -193,7 +193,7 @@ static inline void lp8788_iio_map_unregister(struct iio_dev *indio_dev,
        iio_map_array_unregister(indio_dev, adc->map);
 }
 
-static int __devinit lp8788_adc_probe(struct platform_device *pdev)
+static int lp8788_adc_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        struct iio_dev *indio_dev;
@@ -236,7 +236,7 @@ err_iio_map:
        return ret;
 }
 
-static int __devexit lp8788_adc_remove(struct platform_device *pdev)
+static int lp8788_adc_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
        struct lp8788_adc *adc = iio_priv(indio_dev);
@@ -250,7 +250,7 @@ static int __devexit lp8788_adc_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_adc_driver = {
        .probe = lp8788_adc_probe,
-       .remove = __devexit_p(lp8788_adc_remove),
+       .remove = lp8788_adc_remove,
        .driver = {
                .name = LP8788_DEV_ADC,
                .owner = THIS_MODULE,
index 1e84b5b55093540435ef5a36e48f87e794dfb140..03b25b3dc71eb95703d2131230e2f11cb2dae03c 100644 (file)
@@ -1402,7 +1402,7 @@ static int max1363_initial_setup(struct max1363_state *st)
        return max1363_set_scan_mode(st);
 }
 
-static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev)
+static int max1363_alloc_scan_masks(struct iio_dev *indio_dev)
 {
        struct max1363_state *st = iio_priv(indio_dev);
        unsigned long *masks;
@@ -1525,8 +1525,8 @@ static void max1363_buffer_cleanup(struct iio_dev *indio_dev)
        iio_kfifo_free(indio_dev->buffer);
 }
 
-static int __devinit max1363_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
+static int max1363_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        int ret;
        struct max1363_state *st;
@@ -1605,26 +1605,27 @@ static int __devinit max1363_probe(struct i2c_client *client,
 
        return 0;
 error_free_irq:
-       free_irq(st->client->irq, indio_dev);
+       if (client->irq)
+               free_irq(st->client->irq, indio_dev);
 error_uninit_buffer:
        iio_buffer_unregister(indio_dev);
 error_cleanup_buffer:
        max1363_buffer_cleanup(indio_dev);
 error_free_available_scan_masks:
        kfree(indio_dev->available_scan_masks);
-error_unregister_map:
-       iio_map_array_unregister(indio_dev, client->dev.platform_data);
 error_disable_reg:
        regulator_disable(st->reg);
 error_put_reg:
        regulator_put(st->reg);
+error_unregister_map:
+       iio_map_array_unregister(indio_dev, client->dev.platform_data);
 error_free_device:
        iio_device_free(indio_dev);
 error_out:
        return ret;
 }
 
-static int __devexit max1363_remove(struct i2c_client *client)
+static int max1363_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
        struct max1363_state *st = iio_priv(indio_dev);
@@ -1635,10 +1636,8 @@ static int __devexit max1363_remove(struct i2c_client *client)
        iio_buffer_unregister(indio_dev);
        max1363_buffer_cleanup(indio_dev);
        kfree(indio_dev->available_scan_masks);
-       if (!IS_ERR(st->reg)) {
-               regulator_disable(st->reg);
-               regulator_put(st->reg);
-       }
+       regulator_disable(st->reg);
+       regulator_put(st->reg);
        iio_map_array_unregister(indio_dev, client->dev.platform_data);
        iio_device_free(indio_dev);
 
@@ -1690,7 +1689,7 @@ static struct i2c_driver max1363_driver = {
                .name = "max1363",
        },
        .probe = max1363_probe,
-       .remove = __devexit_p(max1363_remove),
+       .remove = max1363_remove,
        .id_table = max1363_id,
 };
 module_i2c_driver(max1363_driver);
index 02a43c87a8a37d7e8f8f485a030e3578cf71e4ea..cd030e100c395416e4043ad6659f7030266b9b7e 100644 (file)
@@ -136,7 +136,7 @@ static const struct iio_info tiadc_info = {
        .read_raw = &tiadc_read_raw,
 };
 
-static int __devinit tiadc_probe(struct platform_device *pdev)
+static int tiadc_probe(struct platform_device *pdev)
 {
        struct iio_dev          *indio_dev;
        struct tiadc_device     *adc_dev;
@@ -188,7 +188,7 @@ err_ret:
        return err;
 }
 
-static int __devexit tiadc_remove(struct platform_device *pdev)
+static int tiadc_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 
@@ -250,7 +250,7 @@ static struct platform_driver tiadc_driver = {
                .pm     = TIADC_PM_OPS,
        },
        .probe  = tiadc_probe,
-       .remove = __devexit_p(tiadc_remove),
+       .remove = tiadc_remove,
 };
 
 module_platform_driver(tiadc_driver);
index 10136a8b20d4a545787ca84ac3cf1787a42bc1fd..ad0261533deeded96c55bdf6ba8b7a60129c21ee 100644 (file)
@@ -116,7 +116,7 @@ static const struct iio_info vprbrd_adc_iio_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit vprbrd_adc_probe(struct platform_device *pdev)
+static int vprbrd_adc_probe(struct platform_device *pdev)
 {
        struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
        struct vprbrd_adc *adc;
@@ -154,7 +154,7 @@ error:
        return ret;
 }
 
-static int __devexit vprbrd_adc_remove(struct platform_device *pdev)
+static int vprbrd_adc_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 
@@ -170,7 +170,7 @@ static struct platform_driver vprbrd_adc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = vprbrd_adc_probe,
-       .remove         = __devexit_p(vprbrd_adc_remove),
+       .remove         = vprbrd_adc_remove,
 };
 
 module_platform_driver(vprbrd_adc_driver);
index d8281cdbfc4a0aa2520c27963797e87fa35ab43d..d6c0af23a2a74a8dae8260e88d3bd87f84ab1c27 100644 (file)
@@ -133,7 +133,7 @@ static const struct iio_chan_spec ad8366_channels[] = {
        AD8366_CHAN(1),
 };
 
-static int __devinit ad8366_probe(struct spi_device *spi)
+static int ad8366_probe(struct spi_device *spi)
 {
        struct iio_dev *indio_dev;
        struct ad8366_state *st;
@@ -182,7 +182,7 @@ error_put_reg:
        return ret;
 }
 
-static int __devexit ad8366_remove(struct spi_device *spi)
+static int ad8366_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad8366_state *st = iio_priv(indio_dev);
@@ -211,7 +211,7 @@ static struct spi_driver ad8366_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad8366_probe,
-       .remove         = __devexit_p(ad8366_remove),
+       .remove         = ad8366_remove,
        .id_table       = ad8366_id,
 };
 
index ae10778da7aa1e7b1c11b558a562e998e78cfdcb..1178121b55b032989257e3167c6724815458ec26 100644 (file)
@@ -6,7 +6,7 @@ menu "Hid Sensor IIO Common"
 config HID_SENSOR_IIO_COMMON
        tristate "Common modules for all HID Sensor IIO drivers"
        depends on HID_SENSOR_HUB
-       select IIO_TRIGGER if IIO_BUFFER
+       select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER
        help
          Say yes here to build support for HID sensor to use
          HID sensor common processing for attributes and IIO triggers.
@@ -14,6 +14,17 @@ config HID_SENSOR_IIO_COMMON
          HID sensor drivers, this module contains processing for those
          attributes.
 
+config HID_SENSOR_IIO_TRIGGER
+       tristate "Common module (trigger) for all HID Sensor IIO drivers"
+       depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON
+       select IIO_TRIGGER
+       help
+         Say yes here to build trigger support for HID sensors.
+         Triggers will be send if all requested attributes were read.
+
+         If this driver is compiled as a module, it will be named
+         hid-sensor-trigger.
+
 config HID_SENSOR_ENUM_BASE_QUIRKS
        bool "ENUM base quirks for HID Sensor IIO drivers"
        depends on HID_SENSOR_IIO_COMMON
index 1f463e00c2426b706223827afc7363614d80691f..22e7c5a82325e13c3cfbded83dc41f0de45385ae 100644 (file)
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
-hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
+obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o
+hid-sensor-iio-common-y := hid-sensor-attributes.o
index eb281a2c295b52e709585b859a9a1f3e0981ec56..2fe1d4edcb2f2b93fdc21b30fdb777d9d4bc923b 100644 (file)
@@ -424,8 +424,8 @@ static const char * const ad5064_vref_name(struct ad5064_state *st,
        return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref];
 }
 
-static int __devinit ad5064_probe(struct device *dev, enum ad5064_type type,
-       const char *name, ad5064_write_func write)
+static int ad5064_probe(struct device *dev, enum ad5064_type type,
+                       const char *name, ad5064_write_func write)
 {
        struct iio_dev *indio_dev;
        struct ad5064_state *st;
@@ -495,7 +495,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5064_remove(struct device *dev)
+static int ad5064_remove(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct ad5064_state *st = iio_priv(indio_dev);
@@ -523,7 +523,7 @@ static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd,
        return spi_write(spi, &st->data.spi, sizeof(st->data.spi));
 }
 
-static int __devinit ad5064_spi_probe(struct spi_device *spi)
+static int ad5064_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
 
@@ -531,7 +531,7 @@ static int __devinit ad5064_spi_probe(struct spi_device *spi)
                                ad5064_spi_write);
 }
 
-static int __devexit ad5064_spi_remove(struct spi_device *spi)
+static int ad5064_spi_remove(struct spi_device *spi)
 {
        return ad5064_remove(&spi->dev);
 }
@@ -563,7 +563,7 @@ static struct spi_driver ad5064_spi_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5064_spi_probe,
-       .remove = __devexit_p(ad5064_spi_remove),
+       .remove = ad5064_spi_remove,
        .id_table = ad5064_spi_ids,
 };
 
@@ -596,14 +596,14 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
        return i2c_master_send(i2c, st->data.i2c, 3);
 }
 
-static int __devinit ad5064_i2c_probe(struct i2c_client *i2c,
+static int ad5064_i2c_probe(struct i2c_client *i2c,
        const struct i2c_device_id *id)
 {
        return ad5064_probe(&i2c->dev, id->driver_data, id->name,
                                                ad5064_i2c_write);
 }
 
-static int __devexit ad5064_i2c_remove(struct i2c_client *i2c)
+static int ad5064_i2c_remove(struct i2c_client *i2c)
 {
        return ad5064_remove(&i2c->dev);
 }
@@ -625,7 +625,7 @@ static struct i2c_driver ad5064_i2c_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5064_i2c_probe,
-       .remove = __devexit_p(ad5064_i2c_remove),
+       .remove = ad5064_i2c_remove,
        .id_table = ad5064_i2c_ids,
 };
 
index 8fce84fe70b1ee98a7ccc2b9c9e5882ca03a6c8b..54b46fd3aedec8295bc4a1f182ffe01d2dc657b5 100644 (file)
@@ -433,7 +433,7 @@ static const char * const ad5360_vref_name[] = {
         "vref0", "vref1", "vref2"
 };
 
-static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev)
+static int ad5360_alloc_channels(struct iio_dev *indio_dev)
 {
        struct ad5360_state *st = iio_priv(indio_dev);
        struct iio_chan_spec *channels;
@@ -456,7 +456,7 @@ static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int __devinit ad5360_probe(struct spi_device *spi)
+static int ad5360_probe(struct spi_device *spi)
 {
        enum ad5360_type type = spi_get_device_id(spi)->driver_data;
        struct iio_dev *indio_dev;
@@ -524,7 +524,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5360_remove(struct spi_device *spi)
+static int ad5360_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5360_state *st = iio_priv(indio_dev);
@@ -560,7 +560,7 @@ static struct spi_driver ad5360_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5360_probe,
-       .remove = __devexit_p(ad5360_remove),
+       .remove = ad5360_remove,
        .id_table = ad5360_ids,
 };
 module_spi_driver(ad5360_driver);
index 14991ac55f2680ded5543eb76d436ef61cc87832..483fc379a2da9ca64a29fb13313b16f3d76d8b43 100644 (file)
@@ -338,7 +338,7 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
        },
 };
 
-static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev)
+static int ad5380_alloc_channels(struct iio_dev *indio_dev)
 {
        struct ad5380_state *st = iio_priv(indio_dev);
        struct iio_chan_spec *channels;
@@ -361,8 +361,8 @@ static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
-       enum ad5380_type type, const char *name)
+static int ad5380_probe(struct device *dev, struct regmap *regmap,
+                       enum ad5380_type type, const char *name)
 {
        struct iio_dev *indio_dev;
        struct ad5380_state *st;
@@ -406,7 +406,11 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap,
                        goto error_free_reg;
                }
 
-               st->vref = regulator_get_voltage(st->vref_reg);
+               ret = regulator_get_voltage(st->vref_reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               st->vref = ret;
        } else {
                st->vref = st->chip_info->int_vref;
                ctrl |= AD5380_CTRL_INT_VREF_EN;
@@ -441,7 +445,7 @@ error_out:
        return ret;
 }
 
-static int __devexit ad5380_remove(struct device *dev)
+static int ad5380_remove(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct ad5380_state *st = iio_priv(indio_dev);
@@ -478,7 +482,7 @@ static const struct regmap_config ad5380_regmap_config = {
 
 #if IS_ENABLED(CONFIG_SPI_MASTER)
 
-static int __devinit ad5380_spi_probe(struct spi_device *spi)
+static int ad5380_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
        struct regmap *regmap;
@@ -491,7 +495,7 @@ static int __devinit ad5380_spi_probe(struct spi_device *spi)
        return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
 }
 
-static int __devexit ad5380_spi_remove(struct spi_device *spi)
+static int ad5380_spi_remove(struct spi_device *spi)
 {
        return ad5380_remove(&spi->dev);
 }
@@ -523,7 +527,7 @@ static struct spi_driver ad5380_spi_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5380_spi_probe,
-       .remove = __devexit_p(ad5380_spi_remove),
+       .remove = ad5380_spi_remove,
        .id_table = ad5380_spi_ids,
 };
 
@@ -552,8 +556,8 @@ static inline void ad5380_spi_unregister_driver(void)
 
 #if IS_ENABLED(CONFIG_I2C)
 
-static int __devinit ad5380_i2c_probe(struct i2c_client *i2c,
-       const struct i2c_device_id *id)
+static int ad5380_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        struct regmap *regmap;
 
@@ -565,7 +569,7 @@ static int __devinit ad5380_i2c_probe(struct i2c_client *i2c,
        return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
 }
 
-static int __devexit ad5380_i2c_remove(struct i2c_client *i2c)
+static int ad5380_i2c_remove(struct i2c_client *i2c)
 {
        return ad5380_remove(&i2c->dev);
 }
@@ -597,7 +601,7 @@ static struct i2c_driver ad5380_i2c_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5380_i2c_probe,
-       .remove = __devexit_p(ad5380_i2c_remove),
+       .remove = ad5380_i2c_remove,
        .id_table = ad5380_i2c_ids,
 };
 
index cdbc5bf25c31f28f4dbc8c2f0a6b00151f194e20..43be948db83eca9eeef414050f3af8c20a5a66e9 100644 (file)
@@ -449,7 +449,7 @@ static const struct iio_info ad5421_info = {
        .driver_module =        THIS_MODULE,
 };
 
-static int __devinit ad5421_probe(struct spi_device *spi)
+static int ad5421_probe(struct spi_device *spi)
 {
        struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev);
        struct iio_dev *indio_dev;
@@ -516,7 +516,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5421_remove(struct spi_device *spi)
+static int ad5421_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -534,7 +534,7 @@ static struct spi_driver ad5421_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5421_probe,
-       .remove = __devexit_p(ad5421_remove),
+       .remove = ad5421_remove,
 };
 module_spi_driver(ad5421_driver);
 
index 3310cbbd41e772287526cb8278aba8a41b96e7b2..f5583aedfb597cf927e3e39969b80e5e0184085e 100644 (file)
@@ -212,8 +212,8 @@ static const struct iio_info ad5446_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad5446_probe(struct device *dev, const char *name,
-       const struct ad5446_chip_info *chip_info)
+static int ad5446_probe(struct device *dev, const char *name,
+                       const struct ad5446_chip_info *chip_info)
 {
        struct ad5446_state *st;
        struct iio_dev *indio_dev;
@@ -226,7 +226,11 @@ static int __devinit ad5446_probe(struct device *dev, const char *name,
                if (ret)
                        goto error_put_reg;
 
-               voltage_uv = regulator_get_voltage(reg);
+               ret = regulator_get_voltage(reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               voltage_uv = ret;
        }
 
        indio_dev = iio_device_alloc(sizeof(*st));
@@ -461,7 +465,7 @@ static const struct spi_device_id ad5446_spi_ids[] = {
 };
 MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
 
-static int __devinit ad5446_spi_probe(struct spi_device *spi)
+static int ad5446_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
 
@@ -469,7 +473,7 @@ static int __devinit ad5446_spi_probe(struct spi_device *spi)
                &ad5446_spi_chip_info[id->driver_data]);
 }
 
-static int __devexit ad5446_spi_remove(struct spi_device *spi)
+static int ad5446_spi_remove(struct spi_device *spi)
 {
        return ad5446_remove(&spi->dev);
 }
@@ -480,7 +484,7 @@ static struct spi_driver ad5446_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad5446_spi_probe,
-       .remove         = __devexit_p(ad5446_spi_remove),
+       .remove         = ad5446_spi_remove,
        .id_table       = ad5446_spi_ids,
 };
 
@@ -539,14 +543,14 @@ static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
        },
 };
 
-static int __devinit ad5446_i2c_probe(struct i2c_client *i2c,
-       const struct i2c_device_id *id)
+static int ad5446_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
        return ad5446_probe(&i2c->dev, id->name,
                &ad5446_i2c_chip_info[id->driver_data]);
 }
 
-static int __devexit ad5446_i2c_remove(struct i2c_client *i2c)
+static int ad5446_i2c_remove(struct i2c_client *i2c)
 {
        return ad5446_remove(&i2c->dev);
 }
@@ -568,7 +572,7 @@ static struct i2c_driver ad5446_i2c_driver = {
                   .owner = THIS_MODULE,
        },
        .probe = ad5446_i2c_probe,
-       .remove = __devexit_p(ad5446_i2c_remove),
+       .remove = ad5446_i2c_remove,
        .id_table = ad5446_i2c_ids,
 };
 
index 0ee6f8eeba8d4b09e1ea75d04309ad981631acbb..c4731b7b577b0670eda5d1f08ccce300f21e6f2f 100644 (file)
@@ -266,7 +266,7 @@ static const char *ad5449_vref_name(struct ad5449 *st, int n)
                return "VREFB";
 }
 
-static int __devinit ad5449_spi_probe(struct spi_device *spi)
+static int ad5449_spi_probe(struct spi_device *spi)
 {
        struct ad5449_platform_data *pdata = spi->dev.platform_data;
        const struct spi_device_id *id = spi_get_device_id(spi);
@@ -333,7 +333,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5449_spi_remove(struct spi_device *spi)
+static int ad5449_spi_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5449 *st = iio_priv(indio_dev);
@@ -366,7 +366,7 @@ static struct spi_driver ad5449_spi_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ad5449_spi_probe,
-       .remove = __devexit_p(ad5449_spi_remove),
+       .remove = ad5449_spi_remove,
        .id_table = ad5449_spi_ids,
 };
 module_spi_driver(ad5449_spi_driver);
index 242bdc7d004492616e20cff52c98702ec5b928d0..0661829f27737ed4f70e1a29137c6c8a18169457 100644 (file)
@@ -277,7 +277,7 @@ static const struct iio_chan_spec ad5504_channels[] = {
        AD5504_CHANNEL(3),
 };
 
-static int __devinit ad5504_probe(struct spi_device *spi)
+static int ad5504_probe(struct spi_device *spi)
 {
        struct ad5504_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -296,7 +296,11 @@ static int __devinit ad5504_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg;
 
-               voltage_uv = regulator_get_voltage(reg);
+               ret = regulator_get_voltage(reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               voltage_uv = ret;
        }
 
        spi_set_drvdata(spi, indio_dev);
@@ -352,7 +356,7 @@ error_ret:
        return ret;
 }
 
-static int __devexit ad5504_remove(struct spi_device *spi)
+static int ad5504_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5504_state *st = iio_priv(indio_dev);
@@ -383,7 +387,7 @@ static struct spi_driver ad5504_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = ad5504_probe,
-       .remove = __devexit_p(ad5504_remove),
+       .remove = ad5504_remove,
        .id_table = ad5504_id,
 };
 module_spi_driver(ad5504_driver);
index 6a7d6a48cc6ddf0d57969822a1bab28e9c8b8400..f6e116627b714e044569c1ef5e85fff59dfc5c20 100644 (file)
@@ -220,7 +220,7 @@ static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
        },
 };
 
-static int __devinit ad5624r_probe(struct spi_device *spi)
+static int ad5624r_probe(struct spi_device *spi)
 {
        struct ad5624r_state *st;
        struct iio_dev *indio_dev;
@@ -238,7 +238,11 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg;
 
-               voltage_uv = regulator_get_voltage(st->reg);
+               ret = regulator_get_voltage(st->reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               voltage_uv = ret;
        }
 
        spi_set_drvdata(spi, indio_dev);
@@ -282,7 +286,7 @@ error_ret:
        return ret;
 }
 
-static int __devexit ad5624r_remove(struct spi_device *spi)
+static int ad5624r_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5624r_state *st = iio_priv(indio_dev);
@@ -314,7 +318,7 @@ static struct spi_driver ad5624r_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = ad5624r_probe,
-       .remove = __devexit_p(ad5624r_remove),
+       .remove = ad5624r_remove,
        .id_table = ad5624r_id,
 };
 module_spi_driver(ad5624r_driver);
index bc92ff9309c2b6012c0cfd25ac36bb8f54898690..ca9609d7a15c256a78b058a26c9191542e06a8f3 100644 (file)
@@ -313,7 +313,7 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
 };
 
 
-static int __devinit ad5686_probe(struct spi_device *spi)
+static int ad5686_probe(struct spi_device *spi)
 {
        struct ad5686_state *st;
        struct iio_dev *indio_dev;
@@ -332,7 +332,11 @@ static int __devinit ad5686_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg;
 
-               voltage_uv = regulator_get_voltage(st->reg);
+               ret = regulator_get_voltage(st->reg);
+               if (ret < 0)
+                       goto error_disable_reg;
+
+               voltage_uv = ret;
        }
 
        st->chip_info =
@@ -379,7 +383,7 @@ error_put_reg:
        return ret;
 }
 
-static int __devexit ad5686_remove(struct spi_device *spi)
+static int ad5686_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5686_state *st = iio_priv(indio_dev);
@@ -408,7 +412,7 @@ static struct spi_driver ad5686_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = ad5686_probe,
-       .remove = __devexit_p(ad5686_remove),
+       .remove = ad5686_remove,
        .id_table = ad5686_id,
 };
 module_spi_driver(ad5686_driver);
index 5db3506034c50a7a07dad98d0634d9ab498a8bdd..0869bbd27d30e67d724621ee95d7cdf315286caa 100644 (file)
@@ -447,8 +447,8 @@ static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode)
        }
 }
 
-static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev,
-       const struct ad5755_platform_data *pdata)
+static int ad5755_setup_pdata(struct iio_dev *indio_dev,
+                             const struct ad5755_platform_data *pdata)
 {
        struct ad5755_state *st = iio_priv(indio_dev);
        unsigned int val;
@@ -503,7 +503,7 @@ static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev,
        return 0;
 }
 
-static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode)
+static bool ad5755_is_voltage_mode(enum ad5755_mode mode)
 {
        switch (mode) {
        case AD5755_MODE_VOLTAGE_0V_5V:
@@ -516,8 +516,8 @@ static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode)
        }
 }
 
-static int __devinit ad5755_init_channels(struct iio_dev *indio_dev,
-       const struct ad5755_platform_data *pdata)
+static int ad5755_init_channels(struct iio_dev *indio_dev,
+                               const struct ad5755_platform_data *pdata)
 {
        struct ad5755_state *st = iio_priv(indio_dev);
        struct iio_chan_spec *channels = st->channels;
@@ -562,7 +562,7 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
        },
 };
 
-static int __devinit ad5755_probe(struct spi_device *spi)
+static int ad5755_probe(struct spi_device *spi)
 {
        enum ad5755_type type = spi_get_device_id(spi)->driver_data;
        const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev);
@@ -614,7 +614,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5755_remove(struct spi_device *spi)
+static int ad5755_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -640,7 +640,7 @@ static struct spi_driver ad5755_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ad5755_probe,
-       .remove = __devexit_p(ad5755_remove),
+       .remove = ad5755_remove,
        .id_table = ad5755_id,
 };
 module_spi_driver(ad5755_driver);
index ffce30447445d50f14079f5d47ec46805bf92581..7f9045e6daa4c863bf6075a85319b1bdd12a1fe1 100644 (file)
@@ -273,7 +273,7 @@ static const struct iio_info ad5764_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad5764_probe(struct spi_device *spi)
+static int ad5764_probe(struct spi_device *spi)
 {
        enum ad5764_type type = spi_get_device_id(spi)->driver_data;
        struct iio_dev *indio_dev;
@@ -340,7 +340,7 @@ error_free:
        return ret;
 }
 
-static int __devexit ad5764_remove(struct spi_device *spi)
+static int ad5764_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5764_state *st = iio_priv(indio_dev);
@@ -372,7 +372,7 @@ static struct spi_driver ad5764_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ad5764_probe,
-       .remove = __devexit_p(ad5764_remove),
+       .remove = ad5764_remove,
        .id_table = ad5764_ids,
 };
 module_spi_driver(ad5764_driver);
index 2bd2e37280ff87b54151aa0edd0454f8db52924d..6407b5407dddec57fe53ca20f9cba3e5bf90358e 100644 (file)
@@ -346,7 +346,7 @@ static const struct iio_info ad5791_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit ad5791_probe(struct spi_device *spi)
+static int ad5791_probe(struct spi_device *spi)
 {
        struct ad5791_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -365,7 +365,11 @@ static int __devinit ad5791_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg_pos;
 
-               pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
+               ret = regulator_get_voltage(st->reg_vdd);
+               if (ret < 0)
+                       goto error_disable_reg_pos;
+
+               pos_voltage_uv = ret;
        }
 
        st->reg_vss = regulator_get(&spi->dev, "vss");
@@ -374,7 +378,11 @@ static int __devinit ad5791_probe(struct spi_device *spi)
                if (ret)
                        goto error_put_reg_neg;
 
-               neg_voltage_uv = regulator_get_voltage(st->reg_vss);
+               ret = regulator_get_voltage(st->reg_vss);
+               if (ret < 0)
+                       goto error_disable_reg_neg;
+
+               neg_voltage_uv = ret;
        }
 
        st->pwr_down = true;
@@ -428,6 +436,7 @@ error_put_reg_neg:
        if (!IS_ERR(st->reg_vss))
                regulator_put(st->reg_vss);
 
+error_disable_reg_pos:
        if (!IS_ERR(st->reg_vdd))
                regulator_disable(st->reg_vdd);
 error_put_reg_pos:
@@ -439,7 +448,7 @@ error_ret:
        return ret;
 }
 
-static int __devexit ad5791_remove(struct spi_device *spi)
+static int ad5791_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5791_state *st = iio_priv(indio_dev);
@@ -475,7 +484,7 @@ static struct spi_driver ad5791_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = ad5791_probe,
-       .remove = __devexit_p(ad5791_remove),
+       .remove = ad5791_remove,
        .id_table = ad5791_id,
 };
 module_spi_driver(ad5791_driver);
index c3d748c25939ca834ce44a6670e32cbb4d5e8eaa..352abe2004a4cd46a4542439c40659feb9b61f9f 100644 (file)
@@ -156,7 +156,7 @@ static const struct iio_chan_spec max517_channels[] = {
        MAX517_CHANNEL(1)
 };
 
-static int __devinit max517_probe(struct i2c_client *client,
+static int max517_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct max517_data *data;
@@ -210,7 +210,7 @@ exit:
        return err;
 }
 
-static int __devexit max517_remove(struct i2c_client *client)
+static int max517_remove(struct i2c_client *client)
 {
        iio_device_unregister(i2c_get_clientdata(client));
        iio_device_free(i2c_get_clientdata(client));
@@ -232,7 +232,7 @@ static struct i2c_driver max517_driver = {
                .pm             = MAX517_PM_OPS,
        },
        .probe          = max517_probe,
-       .remove         =  __devexit_p(max517_remove),
+       .remove         = max517_remove,
        .id_table       = max517_id,
 };
 module_i2c_driver(max517_driver);
index e0e168bd5b459a3dad00064335054447e62af6b8..8f88cc4059a2a95620681edc30116db75dd06f8b 100644 (file)
@@ -141,8 +141,8 @@ static const struct iio_info mcp4725_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit mcp4725_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int mcp4725_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct mcp4725_data *data;
        struct iio_dev *indio_dev;
@@ -195,7 +195,7 @@ exit:
        return err;
 }
 
-static int __devexit mcp4725_remove(struct i2c_client *client)
+static int mcp4725_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -217,7 +217,7 @@ static struct i2c_driver mcp4725_driver = {
                .pm     = MCP4725_PM_OPS,
        },
        .probe          = mcp4725_probe,
-       .remove         = __devexit_p(mcp4725_remove),
+       .remove         = mcp4725_remove,
        .id_table       = mcp4725_id,
 };
 module_i2c_driver(mcp4725_driver);
index b737c64a402dab345c7f0c1d6f254d4877198bf1..80307473e3a99b387750decac19272ecb1844db1 100644 (file)
@@ -959,7 +959,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int __devinit ad9523_probe(struct spi_device *spi)
+static int ad9523_probe(struct spi_device *spi)
 {
        struct ad9523_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -1020,7 +1020,7 @@ error_put_reg:
        return ret;
 }
 
-static int __devexit ad9523_remove(struct spi_device *spi)
+static int ad9523_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad9523_state *st = iio_priv(indio_dev);
@@ -1049,7 +1049,7 @@ static struct spi_driver ad9523_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ad9523_probe,
-       .remove         = __devexit_p(ad9523_remove),
+       .remove         = ad9523_remove,
        .id_table       = ad9523_id,
 };
 module_spi_driver(ad9523_driver);
index e35bb8f6fe7597e8823527772b119cd3b579377d..a884252ac66b477db3a0fce966b40fb76ae456b2 100644 (file)
@@ -173,7 +173,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
                        } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt);
                } while (r_cnt == 0);
 
-               tmp = freq * (u64)st->r1_mod + (st->fpfd > 1);
+               tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1);
                do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */
                st->r0_fract = do_div(tmp, st->r1_mod);
                st->r0_int = tmp;
@@ -355,7 +355,7 @@ static const struct iio_info adf4350_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit adf4350_probe(struct spi_device *spi)
+static int adf4350_probe(struct spi_device *spi)
 {
        struct adf4350_platform_data *pdata = spi->dev.platform_data;
        struct iio_dev *indio_dev;
@@ -440,7 +440,7 @@ error_put_reg:
        return ret;
 }
 
-static int __devexit adf4350_remove(struct spi_device *spi)
+static int adf4350_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct adf4350_state *st = iio_priv(indio_dev);
@@ -476,7 +476,7 @@ static struct spi_driver adf4350_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = adf4350_probe,
-       .remove         = __devexit_p(adf4350_remove),
+       .remove         = adf4350_remove,
        .id_table       = adf4350_id,
 };
 module_spi_driver(adf4350_driver);
index 48ed1483ff27260e8ac24634cc670acf32f33172..96b68f63a902580c6a45c7265641397ffdda9d52 100644 (file)
@@ -17,6 +17,7 @@ config HID_SENSOR_GYRO_3D
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select HID_SENSOR_IIO_COMMON
+       select HID_SENSOR_IIO_TRIGGER
        tristate "HID Gyroscope 3D"
        help
          Say yes here to build support for the HID SENSOR
index 4c8b158e40e18d508d4dfd53d7108249e2f2a455..06e7cc35450c633a9e08e55450907f6e00241518 100644 (file)
@@ -278,7 +278,7 @@ static int gyro_3d_parse_report(struct platform_device *pdev,
 }
 
 /* Function to initialize the processing for usage id */
-static int __devinit hid_gyro_3d_probe(struct platform_device *pdev)
+static int hid_gyro_3d_probe(struct platform_device *pdev)
 {
        int ret = 0;
        static const char *name = "gyro_3d";
@@ -375,7 +375,7 @@ error_ret:
 }
 
 /* Function to deinitialize the processing for usage id */
-static int __devinit hid_gyro_3d_remove(struct platform_device *pdev)
+static int hid_gyro_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
index 1763c9bcb98ae19817086c4713a6067552d9e74c..dbf80abc834fd3f848a7945b9ddbf38da5a968d7 100644 (file)
@@ -47,6 +47,7 @@ config HID_SENSOR_ALS
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select HID_SENSOR_IIO_COMMON
+       select HID_SENSOR_IIO_TRIGGER
        tristate "HID ALS"
        help
          Say yes here to build support for the HID SENSOR
index 36d210a06b28feb3284e67031ee60455b23b394b..d5b9d39d95b2aeecfbe07d28edf88b30494d648a 100644 (file)
@@ -286,8 +286,8 @@ static const struct iio_info adjd_s311_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit adjd_s311_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int adjd_s311_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct adjd_s311_data *data;
        struct iio_dev *indio_dev;
@@ -330,7 +330,7 @@ exit:
        return err;
 }
 
-static int __devexit adjd_s311_remove(struct i2c_client *client)
+static int adjd_s311_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
        struct adjd_s311_data *data = iio_priv(indio_dev);
@@ -354,7 +354,7 @@ static struct i2c_driver adjd_s311_driver = {
                .name   = ADJD_S311_DRV_NAME,
        },
        .probe          = adjd_s311_probe,
-       .remove         = __devexit_p(adjd_s311_remove),
+       .remove         = adjd_s311_remove,
        .id_table       = adjd_s311_id,
 };
 module_i2c_driver(adjd_s311_driver);
index 23eeeef64e84b93e656ccb07a21dfd57c90a8190..e2d042f2a544b0b55bcdbee9bf84e6ed5430a252 100644 (file)
@@ -245,7 +245,7 @@ static int als_parse_report(struct platform_device *pdev,
 }
 
 /* Function to initialize the processing for usage id */
-static int __devinit hid_als_probe(struct platform_device *pdev)
+static int hid_als_probe(struct platform_device *pdev)
 {
        int ret = 0;
        static const char *name = "als";
@@ -341,7 +341,7 @@ error_ret:
 }
 
 /* Function to deinitialize the processing for usage id */
-static int __devinit hid_als_remove(struct platform_device *pdev)
+static int hid_als_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
index e45712a921ce600cee7c10aa2d8a4dcbc46fccba..7503012ce9333ddc98ecbd8f25eecaf11345c379 100644 (file)
@@ -718,8 +718,7 @@ static struct attribute_group lm3533_als_attribute_group = {
        .attrs = lm3533_als_attributes
 };
 
-static int __devinit lm3533_als_set_input_mode(struct lm3533_als *als,
-                                                               bool pwm_mode)
+static int lm3533_als_set_input_mode(struct lm3533_als *als, bool pwm_mode)
 {
        u8 mask = LM3533_ALS_INPUT_MODE_MASK;
        u8 val;
@@ -740,7 +739,7 @@ static int __devinit lm3533_als_set_input_mode(struct lm3533_als *als,
        return 0;
 }
 
-static int __devinit lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
+static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
 {
        int ret;
 
@@ -756,8 +755,8 @@ static int __devinit lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
        return 0;
 }
 
-static int __devinit lm3533_als_setup(struct lm3533_als *als,
-                                       struct lm3533_als_platform_data *pdata)
+static int lm3533_als_setup(struct lm3533_als *als,
+                           struct lm3533_als_platform_data *pdata)
 {
        int ret;
 
@@ -775,7 +774,7 @@ static int __devinit lm3533_als_setup(struct lm3533_als *als,
        return 0;
 }
 
-static int __devinit lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
+static int lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
 {
        u8 mask = LM3533_ALS_INT_ENABLE_MASK;
        int ret;
@@ -799,7 +798,7 @@ static int __devinit lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
        return 0;
 }
 
-static int __devinit lm3533_als_enable(struct lm3533_als *als)
+static int lm3533_als_enable(struct lm3533_als *als)
 {
        u8 mask = LM3533_ALS_ENABLE_MASK;
        int ret;
@@ -830,7 +829,7 @@ static const struct iio_info lm3533_als_info = {
        .read_raw       = &lm3533_als_read_raw,
 };
 
-static int __devinit lm3533_als_probe(struct platform_device *pdev)
+static int lm3533_als_probe(struct platform_device *pdev)
 {
        struct lm3533 *lm3533;
        struct lm3533_als_platform_data *pdata;
@@ -901,7 +900,7 @@ err_free_dev:
        return ret;
 }
 
-static int __devexit lm3533_als_remove(struct platform_device *pdev)
+static int lm3533_als_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
        struct lm3533_als *als = iio_priv(indio_dev);
@@ -922,7 +921,7 @@ static struct platform_driver lm3533_als_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = lm3533_als_probe,
-       .remove         = __devexit_p(lm3533_als_remove),
+       .remove         = lm3533_als_remove,
 };
 module_platform_driver(lm3533_als_driver);
 
index e49cb9784a6ff26060fd6617a08ad5e1c17688b8..2aa748fbdc0ed4fc5b9d230cb28e648a5a6c46cf 100644 (file)
@@ -150,8 +150,8 @@ static const struct iio_info vcnl4000_info = {
        .driver_module = THIS_MODULE,
 };
 
-static int __devinit vcnl4000_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
+static int vcnl4000_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct vcnl4000_data *data;
        struct iio_dev *indio_dev;
@@ -190,7 +190,7 @@ error_free_dev:
        return ret;
 }
 
-static int __devexit vcnl4000_remove(struct i2c_client *client)
+static int vcnl4000_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -206,7 +206,7 @@ static struct i2c_driver vcnl4000_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = vcnl4000_probe,
-       .remove = __devexit_p(vcnl4000_remove),
+       .remove = vcnl4000_remove,
        .id_table = vcnl4000_id,
 };
 
index c1f0cdd57037ee863e0ba12d639c4bc536a80a5d..ff11d68225cfb6d2e8f819345eb15907857601d4 100644 (file)
@@ -8,6 +8,7 @@ config HID_SENSOR_MAGNETOMETER_3D
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select HID_SENSOR_IIO_COMMON
+       select HID_SENSOR_IIO_TRIGGER
        tristate "HID Magenetometer 3D"
        help
          Say yes here to build support for the HID SENSOR
index 8e75eb76ccd992729785c340e7eaea801026ec89..7ac2c7483ba8ae51f95243311929cc028110aea2 100644 (file)
@@ -279,7 +279,7 @@ static int magn_3d_parse_report(struct platform_device *pdev,
 }
 
 /* Function to initialize the processing for usage id */
-static int __devinit hid_magn_3d_probe(struct platform_device *pdev)
+static int hid_magn_3d_probe(struct platform_device *pdev)
 {
        int ret = 0;
        static char *name = "magn_3d";
@@ -376,7 +376,7 @@ error_ret:
 }
 
 /* Function to deinitialize the processing for usage id */
-static int __devinit hid_magn_3d_remove(struct platform_device *pdev)
+static int hid_magn_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
index 5ce7b9e8bff64cce52c6e3c111fff35f457d9dbf..7275e727e0f56e49f8a4671cd3935d44e40b9fe8 100644 (file)
@@ -920,8 +920,7 @@ static struct net_device *c2_devinit(struct c2_dev *c2dev,
        return netdev;
 }
 
-static int __devinit c2_probe(struct pci_dev *pcidev,
-                             const struct pci_device_id *ent)
+static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
 {
        int ret = 0, i;
        unsigned long reg0_start, reg0_flags, reg0_len;
@@ -1191,7 +1190,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
        return ret;
 }
 
-static void __devexit c2_remove(struct pci_dev *pcidev)
+static void c2_remove(struct pci_dev *pcidev)
 {
        struct c2_dev *c2dev = pci_get_drvdata(pcidev);
        struct net_device *netdev = c2dev->netdev;
@@ -1236,7 +1235,7 @@ static struct pci_driver c2_pci_driver = {
        .name = DRV_NAME,
        .id_table = c2_pci_table,
        .probe = c2_probe,
-       .remove = __devexit_p(c2_remove),
+       .remove = c2_remove,
 };
 
 static int __init c2_init_module(void)
index 6ae698e68775c984992d01fffec0d4bfe1ea31a8..ba7a1208ff9e708c25c59e09aeed4219f93da506 100644 (file)
@@ -498,16 +498,16 @@ extern int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                        struct ib_send_wr **bad_wr);
 extern int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
                           struct ib_recv_wr **bad_wr);
-extern void __devinit c2_init_qp_table(struct c2_dev *c2dev);
-extern void __devexit c2_cleanup_qp_table(struct c2_dev *c2dev);
+extern void c2_init_qp_table(struct c2_dev *c2dev);
+extern void c2_cleanup_qp_table(struct c2_dev *c2dev);
 extern void c2_set_qp_state(struct c2_qp *, int);
 extern struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn);
 
 /* PDs */
 extern int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd);
 extern void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd);
-extern int __devinit c2_init_pd_table(struct c2_dev *c2dev);
-extern void __devexit c2_cleanup_pd_table(struct c2_dev *c2dev);
+extern int c2_init_pd_table(struct c2_dev *c2dev);
+extern void c2_cleanup_pd_table(struct c2_dev *c2dev);
 
 /* CQs */
 extern int c2_init_cq(struct c2_dev *c2dev, int entries,
index 161f2a285351a7c41ad5352318d63a91ec775197..f3e81dc357bb0edce790c1cce0e4b9ca3bb38bd1 100644 (file)
@@ -70,7 +70,7 @@ void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd)
        spin_unlock(&c2dev->pd_table.lock);
 }
 
-int __devinit c2_init_pd_table(struct c2_dev *c2dev)
+int c2_init_pd_table(struct c2_dev *c2dev)
 {
 
        c2dev->pd_table.last = 0;
@@ -84,7 +84,7 @@ int __devinit c2_init_pd_table(struct c2_dev *c2dev)
        return 0;
 }
 
-void __devexit c2_cleanup_pd_table(struct c2_dev *c2dev)
+void c2_cleanup_pd_table(struct c2_dev *c2dev)
 {
        kfree(c2dev->pd_table.table);
 }
index 0d7b6f23caffdc7857da68b23fd2f12fd2a58aec..28cd5cb51859629edb9cffcb1f162832fee91ea6 100644 (file)
@@ -1010,13 +1010,13 @@ out:
        return err;
 }
 
-void __devinit c2_init_qp_table(struct c2_dev *c2dev)
+void c2_init_qp_table(struct c2_dev *c2dev)
 {
        spin_lock_init(&c2dev->qp_table.lock);
        idr_init(&c2dev->qp_table.idr);
 }
 
-void __devexit c2_cleanup_qp_table(struct c2_dev *c2dev)
+void c2_cleanup_qp_table(struct c2_dev *c2dev)
 {
        idr_destroy(&c2dev->qp_table.idr);
 }
index e4a73158fc7fc0392d9308146f2c695936b80532..b7c986990053da3f379bd013e7ed9a3bf1d893db 100644 (file)
@@ -442,7 +442,7 @@ static int c2_rnic_close(struct c2_dev *c2dev)
  * involves initializing the various limits and resource pools that
  * comprise the RNIC instance.
  */
-int __devinit c2_rnic_init(struct c2_dev *c2dev)
+int c2_rnic_init(struct c2_dev *c2dev)
 {
        int err;
        u32 qsize, msgsize;
@@ -611,7 +611,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
 /*
  * Called by c2_remove to cleanup the RNIC resources.
  */
-void __devexit c2_rnic_term(struct c2_dev *c2dev)
+void c2_rnic_term(struct c2_dev *c2dev)
 {
 
        /* Close the open adapter instance */
index 5de86968379d265e1c1046b6742efb6c36978328..c13745cde7facf26056f1d2e2ad3a25a1a428483 100644 (file)
 #include <linux/inetdevice.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/if_vlan.h>
 
 #include <net/neighbour.h>
 #include <net/netevent.h>
 #include <net/route.h>
+#include <net/tcp.h>
 
 #include "iw_cxgb4.h"
 
@@ -61,6 +63,14 @@ static char *states[] = {
        NULL,
 };
 
+static int nocong;
+module_param(nocong, int, 0644);
+MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)");
+
+static int enable_ecn;
+module_param(enable_ecn, int, 0644);
+MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)");
+
 static int dack_mode = 1;
 module_param(dack_mode, int, 0644);
 MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
@@ -265,6 +275,7 @@ void _c4iw_free_ep(struct kref *kref)
                cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
                dst_release(ep->dst);
                cxgb4_l2t_release(ep->l2t);
+               remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
        }
        kfree(ep);
 }
@@ -441,6 +452,50 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
+#define VLAN_NONE 0xfff
+#define FILTER_SEL_VLAN_NONE 0xffff
+#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
+#define FILTER_SEL_WIDTH_VIN_P_FC \
+       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
+#define FILTER_SEL_WIDTH_TAG_P_FC \
+       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
+#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
+
+static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
+                                 struct l2t_entry *l2t)
+{
+       unsigned int ntuple = 0;
+       u32 viid;
+
+       switch (dev->rdev.lldi.filt_mode) {
+
+       /* default filter mode */
+       case HW_TPL_FR_MT_PR_IV_P_FC:
+               if (l2t->vlan == VLAN_NONE)
+                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
+               else {
+                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
+                       ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+               }
+               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+               break;
+       case HW_TPL_FR_MT_PR_OV_P_FC: {
+               viid = cxgb4_port_viid(l2t->neigh->dev);
+
+               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
+               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
+               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
+               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
+                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
+               break;
+       }
+       default:
+               break;
+       }
+       return ntuple;
+}
+
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -463,7 +518,8 @@ static int send_connect(struct c4iw_ep *ep)
 
        cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
        wscale = compute_wscale(rcv_win);
-       opt0 = KEEP_ALIVE(1) |
+       opt0 = (nocong ? NO_CONG(1) : 0) |
+              KEEP_ALIVE(1) |
               DELACK(1) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
@@ -474,6 +530,7 @@ static int send_connect(struct c4iw_ep *ep)
               ULP_MODE(ULP_MODE_TCPDDP) |
               RCV_BUFSIZ(rcv_win>>10);
        opt2 = RX_CHANNEL(0) |
+              CCTRL_ECN(enable_ecn) |
               RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
        if (enable_tcp_timestamps)
                opt2 |= TSTAMPS_EN(1);
@@ -492,8 +549,9 @@ static int send_connect(struct c4iw_ep *ep)
        req->local_ip = ep->com.local_addr.sin_addr.s_addr;
        req->peer_ip = ep->com.remote_addr.sin_addr.s_addr;
        req->opt0 = cpu_to_be64(opt0);
-       req->params = 0;
+       req->params = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, ep->l2t));
        req->opt2 = cpu_to_be32(opt2);
+       set_bit(ACT_OPEN_REQ, &ep->com.history);
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
@@ -770,6 +828,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
        /* setup the hwtid for this connection */
        ep->hwtid = tid;
        cxgb4_insert_tid(t, ep, tid);
+       insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid);
 
        ep->snd_seq = be32_to_cpu(req->snd_isn);
        ep->rcv_seq = be32_to_cpu(req->rcv_isn);
@@ -777,7 +836,9 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
        set_emss(ep, ntohs(req->tcp_opt));
 
        /* dealloc the atid */
+       remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid);
        cxgb4_free_atid(t, atid);
+       set_bit(ACT_ESTAB, &ep->com.history);
 
        /* start MPA negotiation */
        send_flowc(ep, NULL);
@@ -803,6 +864,7 @@ static void close_complete_upcall(struct c4iw_ep *ep)
                ep->com.cm_id->rem_ref(ep->com.cm_id);
                ep->com.cm_id = NULL;
                ep->com.qp = NULL;
+               set_bit(CLOSE_UPCALL, &ep->com.history);
        }
 }
 
@@ -811,6 +873,7 @@ static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        close_complete_upcall(ep);
        state_set(&ep->com, ABORTING);
+       set_bit(ABORT_CONN, &ep->com.history);
        return send_abort(ep, skb, gfp);
 }
 
@@ -825,6 +888,7 @@ static void peer_close_upcall(struct c4iw_ep *ep)
                PDBG("peer close delivered ep %p cm_id %p tid %u\n",
                     ep, ep->com.cm_id, ep->hwtid);
                ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+               set_bit(DISCONN_UPCALL, &ep->com.history);
        }
 }
 
@@ -843,6 +907,7 @@ static void peer_abort_upcall(struct c4iw_ep *ep)
                ep->com.cm_id->rem_ref(ep->com.cm_id);
                ep->com.cm_id = NULL;
                ep->com.qp = NULL;
+               set_bit(ABORT_UPCALL, &ep->com.history);
        }
 }
 
@@ -875,6 +940,7 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
 
        PDBG("%s ep %p tid %u status %d\n", __func__, ep,
             ep->hwtid, status);
+       set_bit(CONN_RPL_UPCALL, &ep->com.history);
        ep->com.cm_id->event_handler(ep->com.cm_id, &event);
 
        if (status < 0) {
@@ -915,6 +981,7 @@ static void connect_request_upcall(struct c4iw_ep *ep)
                                                ep->parent_ep->com.cm_id,
                                                &event);
        }
+       set_bit(CONNREQ_UPCALL, &ep->com.history);
        c4iw_put_ep(&ep->parent_ep->com);
        ep->parent_ep = NULL;
 }
@@ -931,6 +998,7 @@ static void established_upcall(struct c4iw_ep *ep)
        if (ep->com.cm_id) {
                PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
                ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+               set_bit(ESTAB_UPCALL, &ep->com.history);
        }
 }
 
@@ -1316,6 +1384,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        unsigned int dlen = ntohs(hdr->len);
        unsigned int tid = GET_TID(hdr);
        struct tid_info *t = dev->rdev.lldi.tids;
+       __u8 status = hdr->status;
 
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen);
@@ -1338,9 +1407,9 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        case MPA_REP_SENT:
                break;
        default:
-               printk(KERN_ERR MOD "%s Unexpected streaming data."
-                      " ep %p state %d tid %u\n",
-                      __func__, ep, state_read(&ep->com), ep->hwtid);
+               pr_err("%s Unexpected streaming data." \
+                      " ep %p state %d tid %u status %d\n",
+                      __func__, ep, state_read(&ep->com), ep->hwtid, status);
 
                /*
                 * The ep will timeout and inform the ULP of the failure.
@@ -1383,6 +1452,63 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        return 0;
 }
 
+static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
+{
+       struct sk_buff *skb;
+       struct fw_ofld_connection_wr *req;
+       unsigned int mtu_idx;
+       int wscale;
+
+       skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+       req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req));
+       memset(req, 0, sizeof(*req));
+       req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
+       req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
+       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+                                    ep->l2t));
+       req->le.lport = ep->com.local_addr.sin_port;
+       req->le.pport = ep->com.remote_addr.sin_port;
+       req->le.u.ipv4.lip = ep->com.local_addr.sin_addr.s_addr;
+       req->le.u.ipv4.pip = ep->com.remote_addr.sin_addr.s_addr;
+       req->tcb.t_state_to_astid =
+                       htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_SENT) |
+                       V_FW_OFLD_CONNECTION_WR_ASTID(atid));
+       req->tcb.cplrxdataack_cplpassacceptrpl =
+                       htons(F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK);
+       req->tcb.tx_max = jiffies;
+       req->tcb.rcv_adv = htons(1);
+       cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
+       wscale = compute_wscale(rcv_win);
+       req->tcb.opt0 = TCAM_BYPASS(1) |
+               (nocong ? NO_CONG(1) : 0) |
+               KEEP_ALIVE(1) |
+               DELACK(1) |
+               WND_SCALE(wscale) |
+               MSS_IDX(mtu_idx) |
+               L2T_IDX(ep->l2t->idx) |
+               TX_CHAN(ep->tx_chan) |
+               SMAC_SEL(ep->smac_idx) |
+               DSCP(ep->tos) |
+               ULP_MODE(ULP_MODE_TCPDDP) |
+               RCV_BUFSIZ(rcv_win >> 10);
+       req->tcb.opt2 = PACE(1) |
+               TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) |
+               RX_CHANNEL(0) |
+               CCTRL_ECN(enable_ecn) |
+               RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
+       if (enable_tcp_timestamps)
+               req->tcb.opt2 |= TSTAMPS_EN(1);
+       if (enable_tcp_sack)
+               req->tcb.opt2 |= SACK_EN(1);
+       if (wscale && enable_tcp_window_scaling)
+               req->tcb.opt2 |= WND_SCALE_EN(1);
+       req->tcb.opt0 = cpu_to_be64(req->tcb.opt0);
+       req->tcb.opt2 = cpu_to_be32(req->tcb.opt2);
+       set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx);
+       set_bit(ACT_OFLD_CONN, &ep->com.history);
+       c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+}
+
 /*
  * Return whether a failed active open has allocated a TID
  */
@@ -1392,6 +1518,111 @@ static inline int act_open_has_tid(int status)
               status != CPL_ERR_ARP_MISS;
 }
 
+#define ACT_OPEN_RETRY_COUNT 2
+
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+       int err = 0;
+       struct rtable *rt;
+       struct port_info *pi;
+       struct net_device *pdev;
+       int step;
+       struct neighbour *neigh;
+
+       PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+       init_timer(&ep->timer);
+
+       /*
+        * Allocate an active TID to initiate a TCP connection.
+        */
+       ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+       if (ep->atid == -1) {
+               pr_err("%s - cannot alloc atid.\n", __func__);
+               err = -ENOMEM;
+               goto fail2;
+       }
+       insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid);
+
+       /* find a route */
+       rt = find_route(ep->com.dev,
+                       ep->com.cm_id->local_addr.sin_addr.s_addr,
+                       ep->com.cm_id->remote_addr.sin_addr.s_addr,
+                       ep->com.cm_id->local_addr.sin_port,
+                       ep->com.cm_id->remote_addr.sin_port, 0);
+       if (!rt) {
+               pr_err("%s - cannot find route.\n", __func__);
+               err = -EHOSTUNREACH;
+               goto fail3;
+       }
+       ep->dst = &rt->dst;
+
+       neigh = dst_neigh_lookup(ep->dst,
+                       &ep->com.cm_id->remote_addr.sin_addr.s_addr);
+       /* get a l2t entry */
+       if (neigh->dev->flags & IFF_LOOPBACK) {
+               PDBG("%s LOOPBACK\n", __func__);
+               pdev = ip_dev_find(&init_net,
+                               ep->com.cm_id->remote_addr.sin_addr.s_addr);
+               ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+                               neigh, pdev, 0);
+               pi = (struct port_info *)netdev_priv(pdev);
+               ep->mtu = pdev->mtu;
+               ep->tx_chan = cxgb4_port_chan(pdev);
+               ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+               dev_put(pdev);
+       } else {
+               ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+                               neigh, neigh->dev, 0);
+               pi = (struct port_info *)netdev_priv(neigh->dev);
+               ep->mtu = dst_mtu(ep->dst);
+               ep->tx_chan = cxgb4_port_chan(neigh->dev);
+               ep->smac_idx = (cxgb4_port_viid(neigh->dev) &
+                               0x7F) << 1;
+       }
+
+       step = ep->com.dev->rdev.lldi.ntxq / ep->com.dev->rdev.lldi.nchan;
+       ep->txq_idx = pi->port_id * step;
+       ep->ctrlq_idx = pi->port_id;
+       step = ep->com.dev->rdev.lldi.nrxq / ep->com.dev->rdev.lldi.nchan;
+       ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[pi->port_id * step];
+
+       if (!ep->l2t) {
+               pr_err("%s - cannot alloc l2e.\n", __func__);
+               err = -ENOMEM;
+               goto fail4;
+       }
+
+       PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+            __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+            ep->l2t->idx);
+
+       state_set(&ep->com, CONNECTING);
+       ep->tos = 0;
+
+       /* send connect request to rnic */
+       err = send_connect(ep);
+       if (!err)
+               goto out;
+
+       cxgb4_l2t_release(ep->l2t);
+fail4:
+       dst_release(ep->dst);
+fail3:
+       remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
+       cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+       /*
+        * remember to send notification to upper layer.
+        * We are in here so the upper layer is not aware that this is
+        * re-connect attempt and so, upper layer is still waiting for
+        * response of 1st connect request.
+        */
+       connect_reply_upcall(ep, -ECONNRESET);
+       c4iw_put_ep(&ep->com);
+out:
+       return err;
+}
+
 static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 {
        struct c4iw_ep *ep;
@@ -1412,6 +1643,8 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                return 0;
        }
 
+       set_bit(ACT_OPEN_RPL, &ep->com.history);
+
        /*
         * Log interesting failures.
         */
@@ -1419,6 +1652,29 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        case CPL_ERR_CONN_RESET:
        case CPL_ERR_CONN_TIMEDOUT:
                break;
+       case CPL_ERR_TCAM_FULL:
+               if (dev->rdev.lldi.enable_fw_ofld_conn) {
+                       mutex_lock(&dev->rdev.stats.lock);
+                       dev->rdev.stats.tcam_full++;
+                       mutex_unlock(&dev->rdev.stats.lock);
+                       send_fw_act_open_req(ep,
+                                            GET_TID_TID(GET_AOPEN_ATID(
+                                            ntohl(rpl->atid_status))));
+                       return 0;
+               }
+               break;
+       case CPL_ERR_CONN_EXIST:
+               if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
+                       set_bit(ACT_RETRY_INUSE, &ep->com.history);
+                       remove_handle(ep->com.dev, &ep->com.dev->atid_idr,
+                                       atid);
+                       cxgb4_free_atid(t, atid);
+                       dst_release(ep->dst);
+                       cxgb4_l2t_release(ep->l2t);
+                       c4iw_reconnect(ep);
+                       return 0;
+               }
+               break;
        default:
                printk(KERN_INFO MOD "Active open failure - "
                       "atid %u status %u errno %d %pI4:%u->%pI4:%u\n",
@@ -1436,6 +1692,7 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        if (status && act_open_has_tid(status))
                cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl));
 
+       remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid);
        cxgb4_free_atid(t, atid);
        dst_release(ep->dst);
        cxgb4_l2t_release(ep->l2t);
@@ -1452,13 +1709,14 @@ static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_listen_ep *ep = lookup_stid(t, stid);
 
        if (!ep) {
-               printk(KERN_ERR MOD "stid %d lookup failure!\n", stid);
-               return 0;
+               PDBG("%s stid %d lookup failure!\n", __func__, stid);
+               goto out;
        }
        PDBG("%s ep %p status %d error %d\n", __func__, ep,
             rpl->status, status2errno(rpl->status));
        c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
 
+out:
        return 0;
 }
 
@@ -1510,14 +1768,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb,
        skb_get(skb);
        cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
        wscale = compute_wscale(rcv_win);
-       opt0 = KEEP_ALIVE(1) |
+       opt0 = (nocong ? NO_CONG(1) : 0) |
+              KEEP_ALIVE(1) |
               DELACK(1) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
               L2T_IDX(ep->l2t->idx) |
               TX_CHAN(ep->tx_chan) |
               SMAC_SEL(ep->smac_idx) |
-              DSCP(ep->tos) |
+              DSCP(ep->tos >> 2) |
               ULP_MODE(ULP_MODE_TCPDDP) |
               RCV_BUFSIZ(rcv_win>>10);
        opt2 = RX_CHANNEL(0) |
@@ -1529,6 +1788,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb,
                opt2 |= SACK_EN(1);
        if (wscale && enable_tcp_window_scaling)
                opt2 |= WND_SCALE_EN(1);
+       if (enable_ecn) {
+               const struct tcphdr *tcph;
+               u32 hlen = ntohl(req->hdr_len);
+
+               tcph = (const void *)(req + 1) + G_ETH_HDR_LEN(hlen) +
+                       G_IP_HDR_LEN(hlen);
+               if (tcph->ece && tcph->cwr)
+                       opt2 |= CCTRL_ECN(1);
+       }
 
        rpl = cplhdr(skb);
        INIT_TP_WR(rpl, ep->hwtid);
@@ -1645,22 +1913,30 @@ out:
 
 static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
 {
-       struct c4iw_ep *child_ep, *parent_ep;
+       struct c4iw_ep *child_ep = NULL, *parent_ep;
        struct cpl_pass_accept_req *req = cplhdr(skb);
        unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int hwtid = GET_TID(req);
        struct dst_entry *dst;
        struct rtable *rt;
-       __be32 local_ip, peer_ip;
+       __be32 local_ip, peer_ip = 0;
        __be16 local_port, peer_port;
        int err;
+       u16 peer_mss = ntohs(req->tcpopt.mss);
 
        parent_ep = lookup_stid(t, stid);
-       PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
-
+       if (!parent_ep) {
+               PDBG("%s connect request on invalid stid %d\n", __func__, stid);
+               goto reject;
+       }
        get_4tuple(req, &local_ip, &peer_ip, &local_port, &peer_port);
 
+       PDBG("%s parent ep %p hwtid %u laddr 0x%x raddr 0x%x lport %d " \
+            "rport %d peer_mss %d\n", __func__, parent_ep, hwtid,
+            ntohl(local_ip), ntohl(peer_ip), ntohs(local_port),
+            ntohs(peer_port), peer_mss);
+
        if (state_read(&parent_ep->com) != LISTEN) {
                printk(KERN_ERR "%s - listening ep not in LISTEN\n",
                       __func__);
@@ -1694,6 +1970,9 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
 
+       if (peer_mss && child_ep->mtu > (peer_mss + 40))
+               child_ep->mtu = peer_mss + 40;
+
        state_set(&child_ep->com, CONNECTING);
        child_ep->com.dev = dev;
        child_ep->com.cm_id = NULL;
@@ -1715,6 +1994,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
        init_timer(&child_ep->timer);
        cxgb4_insert_tid(t, child_ep, hwtid);
        accept_cr(child_ep, peer_ip, skb, req);
+       set_bit(PASS_ACCEPT_REQ, &child_ep->com.history);
        goto out;
 reject:
        reject_cr(dev, hwtid, peer_ip, skb);
@@ -1734,12 +2014,17 @@ static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb)
        ep->snd_seq = be32_to_cpu(req->snd_isn);
        ep->rcv_seq = be32_to_cpu(req->rcv_isn);
 
+       PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid,
+            ntohs(req->tcp_opt));
+
        set_emss(ep, ntohs(req->tcp_opt));
+       insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid);
 
        dst_confirm(ep->dst);
        state_set(&ep->com, MPA_REQ_WAIT);
        start_ep_timer(ep);
        send_flowc(ep, skb);
+       set_bit(PASS_ESTAB, &ep->com.history);
 
        return 0;
 }
@@ -1759,6 +2044,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        dst_confirm(ep->dst);
 
+       set_bit(PEER_CLOSE, &ep->com.history);
        mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case MPA_REQ_WAIT:
@@ -1838,74 +2124,6 @@ static int is_neg_adv_abort(unsigned int status)
               status == CPL_ERR_PERSIST_NEG_ADVICE;
 }
 
-static int c4iw_reconnect(struct c4iw_ep *ep)
-{
-       struct rtable *rt;
-       int err = 0;
-
-       PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
-       init_timer(&ep->timer);
-
-       /*
-        * Allocate an active TID to initiate a TCP connection.
-        */
-       ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
-       if (ep->atid == -1) {
-               printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
-               err = -ENOMEM;
-               goto fail2;
-       }
-
-       /* find a route */
-       rt = find_route(ep->com.dev,
-                       ep->com.cm_id->local_addr.sin_addr.s_addr,
-                       ep->com.cm_id->remote_addr.sin_addr.s_addr,
-                       ep->com.cm_id->local_addr.sin_port,
-                       ep->com.cm_id->remote_addr.sin_port, 0);
-       if (!rt) {
-               printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
-               err = -EHOSTUNREACH;
-               goto fail3;
-       }
-       ep->dst = &rt->dst;
-
-       err = import_ep(ep, ep->com.cm_id->remote_addr.sin_addr.s_addr,
-                       ep->dst, ep->com.dev, false);
-       if (err) {
-               printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
-               goto fail4;
-       }
-
-       PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
-            __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
-            ep->l2t->idx);
-
-       state_set(&ep->com, CONNECTING);
-       ep->tos = 0;
-
-       /* send connect request to rnic */
-       err = send_connect(ep);
-       if (!err)
-               goto out;
-
-       cxgb4_l2t_release(ep->l2t);
-fail4:
-       dst_release(ep->dst);
-fail3:
-       cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
-fail2:
-       /*
-        * remember to send notification to upper layer.
-        * We are in here so the upper layer is not aware that this is
-        * re-connect attempt and so, upper layer is still waiting for
-        * response of 1st connect request.
-        */
-       connect_reply_upcall(ep, -ECONNRESET);
-       c4iw_put_ep(&ep->com);
-out:
-       return err;
-}
-
 static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 {
        struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1926,6 +2144,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
        }
        PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
             ep->com.state);
+       set_bit(PEER_ABORT, &ep->com.history);
 
        /*
         * Wake up any threads in rdma_init() or rdma_fini().
@@ -2140,6 +2359,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
                c4iw_put_ep(&ep->com);
                return -ECONNRESET;
        }
+       set_bit(ULP_REJECT, &ep->com.history);
        BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
        if (mpa_rev == 0)
                abort_connection(ep, NULL, GFP_KERNEL);
@@ -2169,6 +2389,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
        BUG_ON(!qp);
 
+       set_bit(ULP_ACCEPT, &ep->com.history);
        if ((conn_param->ord > c4iw_max_read_depth) ||
            (conn_param->ird > c4iw_max_read_depth)) {
                abort_connection(ep, NULL, GFP_KERNEL);
@@ -2292,6 +2513,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                err = -ENOMEM;
                goto fail2;
        }
+       insert_handle(dev, &dev->atid_idr, ep, ep->atid);
 
        PDBG("%s saddr 0x%x sport 0x%x raddr 0x%x rport 0x%x\n", __func__,
             ntohl(cm_id->local_addr.sin_addr.s_addr),
@@ -2337,6 +2559,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 fail4:
        dst_release(ep->dst);
 fail3:
+       remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
        cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
 fail2:
        cm_id->rem_ref(cm_id);
@@ -2351,7 +2574,6 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        struct c4iw_dev *dev = to_c4iw_dev(cm_id->device);
        struct c4iw_listen_ep *ep;
 
-
        might_sleep();
 
        ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
@@ -2370,30 +2592,54 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, PF_INET, ep);
+       if (dev->rdev.lldi.enable_fw_ofld_conn)
+               ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, PF_INET, ep);
+       else
+               ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, PF_INET, ep);
+
        if (ep->stid == -1) {
                printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__);
                err = -ENOMEM;
                goto fail2;
        }
-
+       insert_handle(dev, &dev->stid_idr, ep, ep->stid);
        state_set(&ep->com, LISTEN);
-       c4iw_init_wr_wait(&ep->com.wr_wait);
-       err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], ep->stid,
-                                 ep->com.local_addr.sin_addr.s_addr,
-                                 ep->com.local_addr.sin_port,
-                                 ep->com.dev->rdev.lldi.rxq_ids[0]);
-       if (err)
-               goto fail3;
-
-       /* wait for pass_open_rpl */
-       err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
-                                 __func__);
+       if (dev->rdev.lldi.enable_fw_ofld_conn) {
+               do {
+                       err = cxgb4_create_server_filter(
+                               ep->com.dev->rdev.lldi.ports[0], ep->stid,
+                               ep->com.local_addr.sin_addr.s_addr,
+                               ep->com.local_addr.sin_port,
+                               0,
+                               ep->com.dev->rdev.lldi.rxq_ids[0],
+                               0,
+                               0);
+                       if (err == -EBUSY) {
+                               set_current_state(TASK_UNINTERRUPTIBLE);
+                               schedule_timeout(usecs_to_jiffies(100));
+                       }
+               } while (err == -EBUSY);
+       } else {
+               c4iw_init_wr_wait(&ep->com.wr_wait);
+               err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0],
+                               ep->stid, ep->com.local_addr.sin_addr.s_addr,
+                               ep->com.local_addr.sin_port,
+                               0,
+                               ep->com.dev->rdev.lldi.rxq_ids[0]);
+               if (!err)
+                       err = c4iw_wait_for_reply(&ep->com.dev->rdev,
+                                                 &ep->com.wr_wait,
+                                                 0, 0, __func__);
+       }
        if (!err) {
                cm_id->provider_data = ep;
                goto out;
        }
-fail3:
+       pr_err("%s cxgb4_create_server/filter failed err %d " \
+              "stid %d laddr %08x lport %d\n", \
+              __func__, err, ep->stid,
+              ntohl(ep->com.local_addr.sin_addr.s_addr),
+              ntohs(ep->com.local_addr.sin_port));
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET);
 fail2:
        cm_id->rem_ref(cm_id);
@@ -2412,12 +2658,19 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id)
 
        might_sleep();
        state_set(&ep->com, DEAD);
-       c4iw_init_wr_wait(&ep->com.wr_wait);
-       err = listen_stop(ep);
-       if (err)
-               goto done;
-       err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
-                                 __func__);
+       if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn) {
+               err = cxgb4_remove_server_filter(
+                       ep->com.dev->rdev.lldi.ports[0], ep->stid,
+                       ep->com.dev->rdev.lldi.rxq_ids[0], 0);
+       } else {
+               c4iw_init_wr_wait(&ep->com.wr_wait);
+               err = listen_stop(ep);
+               if (err)
+                       goto done;
+               err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait,
+                                         0, 0, __func__);
+       }
+       remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid);
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET);
 done:
        cm_id->rem_ref(cm_id);
@@ -2481,10 +2734,13 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
 
        if (close) {
                if (abrupt) {
+                       set_bit(EP_DISC_ABORT, &ep->com.history);
                        close_complete_upcall(ep);
                        ret = send_abort(ep, NULL, gfp);
-               } else
+               } else {
+                       set_bit(EP_DISC_CLOSE, &ep->com.history);
                        ret = send_halfclose(ep, gfp);
+               }
                if (ret)
                        fatal = 1;
        }
@@ -2494,10 +2750,323 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
        return ret;
 }
 
-static int async_event(struct c4iw_dev *dev, struct sk_buff *skb)
+static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb,
+                       struct cpl_fw6_msg_ofld_connection_wr_rpl *req)
+{
+       struct c4iw_ep *ep;
+       int atid = be32_to_cpu(req->tid);
+
+       ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, req->tid);
+       if (!ep)
+               return;
+
+       switch (req->retval) {
+       case FW_ENOMEM:
+               set_bit(ACT_RETRY_NOMEM, &ep->com.history);
+               if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
+                       send_fw_act_open_req(ep, atid);
+                       return;
+               }
+       case FW_EADDRINUSE:
+               set_bit(ACT_RETRY_INUSE, &ep->com.history);
+               if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
+                       send_fw_act_open_req(ep, atid);
+                       return;
+               }
+               break;
+       default:
+               pr_info("%s unexpected ofld conn wr retval %d\n",
+                      __func__, req->retval);
+               break;
+       }
+       pr_err("active ofld_connect_wr failure %d atid %d\n",
+              req->retval, atid);
+       mutex_lock(&dev->rdev.stats.lock);
+       dev->rdev.stats.act_ofld_conn_fails++;
+       mutex_unlock(&dev->rdev.stats.lock);
+       connect_reply_upcall(ep, status2errno(req->retval));
+       state_set(&ep->com, DEAD);
+       remove_handle(dev, &dev->atid_idr, atid);
+       cxgb4_free_atid(dev->rdev.lldi.tids, atid);
+       dst_release(ep->dst);
+       cxgb4_l2t_release(ep->l2t);
+       c4iw_put_ep(&ep->com);
+}
+
+static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb,
+                       struct cpl_fw6_msg_ofld_connection_wr_rpl *req)
+{
+       struct sk_buff *rpl_skb;
+       struct cpl_pass_accept_req *cpl;
+       int ret;
+
+       rpl_skb = (struct sk_buff *)cpu_to_be64(req->cookie);
+       BUG_ON(!rpl_skb);
+       if (req->retval) {
+               PDBG("%s passive open failure %d\n", __func__, req->retval);
+               mutex_lock(&dev->rdev.stats.lock);
+               dev->rdev.stats.pas_ofld_conn_fails++;
+               mutex_unlock(&dev->rdev.stats.lock);
+               kfree_skb(rpl_skb);
+       } else {
+               cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb);
+               OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ,
+                                                     htonl(req->tid)));
+               ret = pass_accept_req(dev, rpl_skb);
+               if (!ret)
+                       kfree_skb(rpl_skb);
+       }
+       return;
+}
+
+static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
 {
        struct cpl_fw6_msg *rpl = cplhdr(skb);
-       c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+       struct cpl_fw6_msg_ofld_connection_wr_rpl *req;
+
+       switch (rpl->type) {
+       case FW6_TYPE_CQE:
+               c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+               break;
+       case FW6_TYPE_OFLD_CONNECTION_WR_RPL:
+               req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data;
+               switch (req->t_state) {
+               case TCP_SYN_SENT:
+                       active_ofld_conn_reply(dev, skb, req);
+                       break;
+               case TCP_SYN_RECV:
+                       passive_ofld_conn_reply(dev, skb, req);
+                       break;
+               default:
+                       pr_err("%s unexpected ofld conn wr state %d\n",
+                              __func__, req->t_state);
+                       break;
+               }
+               break;
+       }
+       return 0;
+}
+
+static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
+{
+       u32 l2info;
+       u16 vlantag, len, hdr_len;
+       u8 intf;
+       struct cpl_rx_pkt *cpl = cplhdr(skb);
+       struct cpl_pass_accept_req *req;
+       struct tcp_options_received tmp_opt;
+
+       /* Store values from cpl_rx_pkt in temporary location. */
+       vlantag = cpl->vlan;
+       len = cpl->len;
+       l2info  = cpl->l2info;
+       hdr_len = cpl->hdr_len;
+       intf = cpl->iff;
+
+       __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header));
+
+       /*
+        * We need to parse the TCP options from SYN packet.
+        * to generate cpl_pass_accept_req.
+        */
+       memset(&tmp_opt, 0, sizeof(tmp_opt));
+       tcp_clear_options(&tmp_opt);
+       tcp_parse_options(skb, &tmp_opt, 0, 0, NULL);
+
+       req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
+       memset(req, 0, sizeof(*req));
+       req->l2info = cpu_to_be16(V_SYN_INTF(intf) |
+                        V_SYN_MAC_IDX(G_RX_MACIDX(htonl(l2info))) |
+                        F_SYN_XACT_MATCH);
+       req->hdr_len = cpu_to_be32(V_SYN_RX_CHAN(G_RX_CHAN(htonl(l2info))) |
+                               V_TCP_HDR_LEN(G_RX_TCPHDR_LEN(htons(hdr_len))) |
+                               V_IP_HDR_LEN(G_RX_IPHDR_LEN(htons(hdr_len))) |
+                               V_ETH_HDR_LEN(G_RX_ETHHDR_LEN(htonl(l2info))));
+       req->vlan = vlantag;
+       req->len = len;
+       req->tos_stid = cpu_to_be32(PASS_OPEN_TID(stid) |
+                                   PASS_OPEN_TOS(tos));
+       req->tcpopt.mss = htons(tmp_opt.mss_clamp);
+       if (tmp_opt.wscale_ok)
+               req->tcpopt.wsf = tmp_opt.snd_wscale;
+       req->tcpopt.tstamp = tmp_opt.saw_tstamp;
+       if (tmp_opt.sack_ok)
+               req->tcpopt.sack = 1;
+       OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0));
+       return;
+}
+
+static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb,
+                                 __be32 laddr, __be16 lport,
+                                 __be32 raddr, __be16 rport,
+                                 u32 rcv_isn, u32 filter, u16 window,
+                                 u32 rss_qid, u8 port_id)
+{
+       struct sk_buff *req_skb;
+       struct fw_ofld_connection_wr *req;
+       struct cpl_pass_accept_req *cpl = cplhdr(skb);
+
+       req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL);
+       req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req));
+       memset(req, 0, sizeof(*req));
+       req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL(1));
+       req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
+       req->le.version_cpl = htonl(F_FW_OFLD_CONNECTION_WR_CPL);
+       req->le.filter = filter;
+       req->le.lport = lport;
+       req->le.pport = rport;
+       req->le.u.ipv4.lip = laddr;
+       req->le.u.ipv4.pip = raddr;
+       req->tcb.rcv_nxt = htonl(rcv_isn + 1);
+       req->tcb.rcv_adv = htons(window);
+       req->tcb.t_state_to_astid =
+                htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_RECV) |
+                       V_FW_OFLD_CONNECTION_WR_RCV_SCALE(cpl->tcpopt.wsf) |
+                       V_FW_OFLD_CONNECTION_WR_ASTID(
+                       GET_PASS_OPEN_TID(ntohl(cpl->tos_stid))));
+
+       /*
+        * We store the qid in opt2 which will be used by the firmware
+        * to send us the wr response.
+        */
+       req->tcb.opt2 = htonl(V_RSS_QUEUE(rss_qid));
+
+       /*
+        * We initialize the MSS index in TCB to 0xF.
+        * So that when driver sends cpl_pass_accept_rpl
+        * TCB picks up the correct value. If this was 0
+        * TP will ignore any value > 0 for MSS index.
+        */
+       req->tcb.opt0 = cpu_to_be64(V_MSS_IDX(0xF));
+       req->cookie = cpu_to_be64((u64)skb);
+
+       set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id);
+       cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
+}
+
+/*
+ * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt
+ * messages when a filter is being used instead of server to
+ * redirect a syn packet. When packets hit filter they are redirected
+ * to the offload queue and driver tries to establish the connection
+ * using firmware work request.
+ */
+static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+       int stid;
+       unsigned int filter;
+       struct ethhdr *eh = NULL;
+       struct vlan_ethhdr *vlan_eh = NULL;
+       struct iphdr *iph;
+       struct tcphdr *tcph;
+       struct rss_header *rss = (void *)skb->data;
+       struct cpl_rx_pkt *cpl = (void *)skb->data;
+       struct cpl_pass_accept_req *req = (void *)(rss + 1);
+       struct l2t_entry *e;
+       struct dst_entry *dst;
+       struct rtable *rt;
+       struct c4iw_ep *lep;
+       u16 window;
+       struct port_info *pi;
+       struct net_device *pdev;
+       u16 rss_qid;
+       int step;
+       u32 tx_chan;
+       struct neighbour *neigh;
+
+       /* Drop all non-SYN packets */
+       if (!(cpl->l2info & cpu_to_be32(F_RXF_SYN)))
+               goto reject;
+
+       /*
+        * Drop all packets which did not hit the filter.
+        * Unlikely to happen.
+        */
+       if (!(rss->filter_hit && rss->filter_tid))
+               goto reject;
+
+       /*
+        * Calculate the server tid from filter hit index from cpl_rx_pkt.
+        */
+       stid = cpu_to_be32(rss->hash_val) - dev->rdev.lldi.tids->sftid_base
+                                         + dev->rdev.lldi.tids->nstids;
+
+       lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
+       if (!lep) {
+               PDBG("%s connect request on invalid stid %d\n", __func__, stid);
+               goto reject;
+       }
+
+       if (G_RX_ETHHDR_LEN(ntohl(cpl->l2info)) == ETH_HLEN) {
+               eh = (struct ethhdr *)(req + 1);
+               iph = (struct iphdr *)(eh + 1);
+       } else {
+               vlan_eh = (struct vlan_ethhdr *)(req + 1);
+               iph = (struct iphdr *)(vlan_eh + 1);
+               skb->vlan_tci = ntohs(cpl->vlan);
+       }
+
+       if (iph->version != 0x4)
+               goto reject;
+
+       tcph = (struct tcphdr *)(iph + 1);
+       skb_set_network_header(skb, (void *)iph - (void *)rss);
+       skb_set_transport_header(skb, (void *)tcph - (void *)rss);
+       skb_get(skb);
+
+       PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__,
+            ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr),
+            ntohs(tcph->source), iph->tos);
+
+       rt = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source,
+                       iph->tos);
+       if (!rt) {
+               pr_err("%s - failed to find dst entry!\n",
+                      __func__);
+               goto reject;
+       }
+       dst = &rt->dst;
+       neigh = dst_neigh_lookup_skb(dst, skb);
+
+       if (neigh->dev->flags & IFF_LOOPBACK) {
+               pdev = ip_dev_find(&init_net, iph->daddr);
+               e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,
+                                   pdev, 0);
+               pi = (struct port_info *)netdev_priv(pdev);
+               tx_chan = cxgb4_port_chan(pdev);
+               dev_put(pdev);
+       } else {
+               e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,
+                                       neigh->dev, 0);
+               pi = (struct port_info *)netdev_priv(neigh->dev);
+               tx_chan = cxgb4_port_chan(neigh->dev);
+       }
+       if (!e) {
+               pr_err("%s - failed to allocate l2t entry!\n",
+                      __func__);
+               goto free_dst;
+       }
+
+       step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
+       rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step];
+       window = htons(tcph->window);
+
+       /* Calcuate filter portion for LE region. */
+       filter = cpu_to_be32(select_ntuple(dev, dst, e));
+
+       /*
+        * Synthesize the cpl_pass_accept_req. We have everything except the
+        * TID. Once firmware sends a reply with TID we update the TID field
+        * in cpl and pass it through the regular cpl_pass_accept_req path.
+        */
+       build_cpl_pass_accept_req(skb, stid, iph->tos);
+       send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr,
+                             tcph->source, ntohl(tcph->seq), filter, window,
+                             rss_qid, pi->port_id);
+       cxgb4_l2t_release(e);
+free_dst:
+       dst_release(dst);
+reject:
        return 0;
 }
 
@@ -2520,7 +3089,8 @@ static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = {
        [CPL_CLOSE_CON_RPL] = close_con_rpl,
        [CPL_RDMA_TERMINATE] = terminate,
        [CPL_FW4_ACK] = fw4_ack,
-       [CPL_FW6_MSG] = async_event
+       [CPL_FW6_MSG] = deferred_fw6_msg,
+       [CPL_RX_PKT] = rx_pkt
 };
 
 static void process_timeout(struct c4iw_ep *ep)
@@ -2531,6 +3101,7 @@ static void process_timeout(struct c4iw_ep *ep)
        mutex_lock(&ep->com.mutex);
        PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
             ep->com.state);
+       set_bit(TIMEDOUT, &ep->com.history);
        switch (ep->com.state) {
        case MPA_REQ_SENT:
                __state_set(&ep->com, ABORTING);
@@ -2651,7 +3222,7 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
        PDBG("%s type %u\n", __func__, rpl->type);
 
        switch (rpl->type) {
-       case 1:
+       case FW6_TYPE_WR_RPL:
                ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
                wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
                PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
@@ -2659,7 +3230,8 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
                        c4iw_wake_up(wr_waitp, ret ? -ret : 0);
                kfree_skb(skb);
                break;
-       case 2:
+       case FW6_TYPE_CQE:
+       case FW6_TYPE_OFLD_CONNECTION_WR_RPL:
                sched(dev, skb);
                break;
        default:
@@ -2722,7 +3294,8 @@ c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = {
        [CPL_RDMA_TERMINATE] = sched,
        [CPL_FW4_ACK] = sched,
        [CPL_SET_TCB_RPL] = set_tcb_rpl,
-       [CPL_FW6_MSG] = fw6_msg
+       [CPL_FW6_MSG] = fw6_msg,
+       [CPL_RX_PKT] = sched
 };
 
 int __init c4iw_cm_init(void)
index cb4ecd7837005c823ca06841f5d3c2ac19510d6c..ba11c76c0b5acab8eb498dc31fa6a674096726ef 100644 (file)
@@ -279,6 +279,11 @@ static int stats_show(struct seq_file *seq, void *v)
        seq_printf(seq, " DB State: %s Transitions %llu\n",
                   db_state_str[dev->db_state],
                   dev->rdev.stats.db_state_transitions);
+       seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full);
+       seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n",
+                  dev->rdev.stats.act_ofld_conn_fails);
+       seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
+                  dev->rdev.stats.pas_ofld_conn_fails);
        return 0;
 }
 
@@ -309,6 +314,9 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
        dev->rdev.stats.db_empty = 0;
        dev->rdev.stats.db_drop = 0;
        dev->rdev.stats.db_state_transitions = 0;
+       dev->rdev.stats.tcam_full = 0;
+       dev->rdev.stats.act_ofld_conn_fails = 0;
+       dev->rdev.stats.pas_ofld_conn_fails = 0;
        mutex_unlock(&dev->rdev.stats.lock);
        return count;
 }
@@ -322,6 +330,113 @@ static const struct file_operations stats_debugfs_fops = {
        .write   = stats_clear,
 };
 
+static int dump_ep(int id, void *p, void *data)
+{
+       struct c4iw_ep *ep = p;
+       struct c4iw_debugfs_data *epd = data;
+       int space;
+       int cc;
+
+       space = epd->bufsize - epd->pos - 1;
+       if (space == 0)
+               return 1;
+
+       cc = snprintf(epd->buf + epd->pos, space,
+                       "ep %p cm_id %p qp %p state %d flags 0x%lx history 0x%lx "
+                       "hwtid %d atid %d %pI4:%d <-> %pI4:%d\n",
+                       ep, ep->com.cm_id, ep->com.qp, (int)ep->com.state,
+                       ep->com.flags, ep->com.history, ep->hwtid, ep->atid,
+                       &ep->com.local_addr.sin_addr.s_addr,
+                       ntohs(ep->com.local_addr.sin_port),
+                       &ep->com.remote_addr.sin_addr.s_addr,
+                       ntohs(ep->com.remote_addr.sin_port));
+       if (cc < space)
+               epd->pos += cc;
+       return 0;
+}
+
+static int dump_listen_ep(int id, void *p, void *data)
+{
+       struct c4iw_listen_ep *ep = p;
+       struct c4iw_debugfs_data *epd = data;
+       int space;
+       int cc;
+
+       space = epd->bufsize - epd->pos - 1;
+       if (space == 0)
+               return 1;
+
+       cc = snprintf(epd->buf + epd->pos, space,
+                       "ep %p cm_id %p state %d flags 0x%lx stid %d backlog %d "
+                       "%pI4:%d\n", ep, ep->com.cm_id, (int)ep->com.state,
+                       ep->com.flags, ep->stid, ep->backlog,
+                       &ep->com.local_addr.sin_addr.s_addr,
+                       ntohs(ep->com.local_addr.sin_port));
+       if (cc < space)
+               epd->pos += cc;
+       return 0;
+}
+
+static int ep_release(struct inode *inode, struct file *file)
+{
+       struct c4iw_debugfs_data *epd = file->private_data;
+       if (!epd) {
+               pr_info("%s null qpd?\n", __func__);
+               return 0;
+       }
+       vfree(epd->buf);
+       kfree(epd);
+       return 0;
+}
+
+static int ep_open(struct inode *inode, struct file *file)
+{
+       struct c4iw_debugfs_data *epd;
+       int ret = 0;
+       int count = 1;
+
+       epd = kmalloc(sizeof(*epd), GFP_KERNEL);
+       if (!epd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       epd->devp = inode->i_private;
+       epd->pos = 0;
+
+       spin_lock_irq(&epd->devp->lock);
+       idr_for_each(&epd->devp->hwtid_idr, count_idrs, &count);
+       idr_for_each(&epd->devp->atid_idr, count_idrs, &count);
+       idr_for_each(&epd->devp->stid_idr, count_idrs, &count);
+       spin_unlock_irq(&epd->devp->lock);
+
+       epd->bufsize = count * 160;
+       epd->buf = vmalloc(epd->bufsize);
+       if (!epd->buf) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       spin_lock_irq(&epd->devp->lock);
+       idr_for_each(&epd->devp->hwtid_idr, dump_ep, epd);
+       idr_for_each(&epd->devp->atid_idr, dump_ep, epd);
+       idr_for_each(&epd->devp->stid_idr, dump_listen_ep, epd);
+       spin_unlock_irq(&epd->devp->lock);
+
+       file->private_data = epd;
+       goto out;
+err1:
+       kfree(epd);
+out:
+       return ret;
+}
+
+static const struct file_operations ep_debugfs_fops = {
+       .owner   = THIS_MODULE,
+       .open    = ep_open,
+       .release = ep_release,
+       .read    = debugfs_read,
+};
+
 static int setup_debugfs(struct c4iw_dev *devp)
 {
        struct dentry *de;
@@ -344,6 +459,11 @@ static int setup_debugfs(struct c4iw_dev *devp)
        if (de && de->d_inode)
                de->d_inode->i_size = 4096;
 
+       de = debugfs_create_file("eps", S_IWUSR, devp->debugfs_root,
+                       (void *)devp, &ep_debugfs_fops);
+       if (de && de->d_inode)
+               de->d_inode->i_size = 4096;
+
        return 0;
 }
 
@@ -475,6 +595,9 @@ static void c4iw_dealloc(struct uld_ctx *ctx)
        idr_destroy(&ctx->dev->cqidr);
        idr_destroy(&ctx->dev->qpidr);
        idr_destroy(&ctx->dev->mmidr);
+       idr_destroy(&ctx->dev->hwtid_idr);
+       idr_destroy(&ctx->dev->stid_idr);
+       idr_destroy(&ctx->dev->atid_idr);
        iounmap(ctx->dev->rdev.oc_mw_kva);
        ib_dealloc_device(&ctx->dev->ibdev);
        ctx->dev = NULL;
@@ -532,6 +655,9 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
        idr_init(&devp->cqidr);
        idr_init(&devp->qpidr);
        idr_init(&devp->mmidr);
+       idr_init(&devp->hwtid_idr);
+       idr_init(&devp->stid_idr);
+       idr_init(&devp->atid_idr);
        spin_lock_init(&devp->lock);
        mutex_init(&devp->rdev.stats.lock);
        mutex_init(&devp->db_mutex);
@@ -577,14 +703,76 @@ out:
        return ctx;
 }
 
+static inline struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl,
+                                                const __be64 *rsp,
+                                                u32 pktshift)
+{
+       struct sk_buff *skb;
+
+       /*
+        * Allocate space for cpl_pass_accept_req which will be synthesized by
+        * driver. Once the driver synthesizes the request the skb will go
+        * through the regular cpl_pass_accept_req processing.
+        * The math here assumes sizeof cpl_pass_accept_req >= sizeof
+        * cpl_rx_pkt.
+        */
+       skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req) +
+                       sizeof(struct rss_header) - pktshift, GFP_ATOMIC);
+       if (unlikely(!skb))
+               return NULL;
+
+        __skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req) +
+                  sizeof(struct rss_header) - pktshift);
+
+       /*
+        * This skb will contain:
+        *   rss_header from the rspq descriptor (1 flit)
+        *   cpl_rx_pkt struct from the rspq descriptor (2 flits)
+        *   space for the difference between the size of an
+        *      rx_pkt and pass_accept_req cpl (1 flit)
+        *   the packet data from the gl
+        */
+       skb_copy_to_linear_data(skb, rsp, sizeof(struct cpl_pass_accept_req) +
+                               sizeof(struct rss_header));
+       skb_copy_to_linear_data_offset(skb, sizeof(struct rss_header) +
+                                      sizeof(struct cpl_pass_accept_req),
+                                      gl->va + pktshift,
+                                      gl->tot_len - pktshift);
+       return skb;
+}
+
+static inline int recv_rx_pkt(struct c4iw_dev *dev, const struct pkt_gl *gl,
+                          const __be64 *rsp)
+{
+       unsigned int opcode = *(u8 *)rsp;
+       struct sk_buff *skb;
+
+       if (opcode != CPL_RX_PKT)
+               goto out;
+
+       skb = copy_gl_to_skb_pkt(gl , rsp, dev->rdev.lldi.sge_pktshift);
+       if (skb == NULL)
+               goto out;
+
+       if (c4iw_handlers[opcode] == NULL) {
+               pr_info("%s no handler opcode 0x%x...\n", __func__,
+                      opcode);
+               kfree_skb(skb);
+               goto out;
+       }
+       c4iw_handlers[opcode](dev, skb);
+       return 1;
+out:
+       return 0;
+}
+
 static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
                        const struct pkt_gl *gl)
 {
        struct uld_ctx *ctx = handle;
        struct c4iw_dev *dev = ctx->dev;
        struct sk_buff *skb;
-       const struct cpl_act_establish *rpl;
-       unsigned int opcode;
+       u8 opcode;
 
        if (gl == NULL) {
                /* omit RSS and rsp_ctrl at end of descriptor */
@@ -600,6 +788,18 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
 
                u32 qid = be32_to_cpu(rc->pldbuflen_qid);
                c4iw_ev_handler(dev, qid);
+               return 0;
+       } else if (unlikely(*(u8 *)rsp != *(u8 *)gl->va)) {
+               if (recv_rx_pkt(dev, gl, rsp))
+                       return 0;
+
+               pr_info("%s: unexpected FL contents at %p, " \
+                      "RSS %#llx, FL %#llx, len %u\n",
+                      pci_name(ctx->lldi.pdev), gl->va,
+                      (unsigned long long)be64_to_cpu(*rsp),
+                      (unsigned long long)be64_to_cpu(*(u64 *)gl->va),
+                      gl->tot_len);
+
                return 0;
        } else {
                skb = cxgb4_pktgl_to_skb(gl, 128, 128);
@@ -607,13 +807,11 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
                        goto nomem;
        }
 
-       rpl = cplhdr(skb);
-       opcode = rpl->ot.opcode;
-
+       opcode = *(u8 *)rsp;
        if (c4iw_handlers[opcode])
                c4iw_handlers[opcode](dev, skb);
        else
-               printk(KERN_INFO "%s no handler opcode 0x%x...\n", __func__,
+               pr_info("%s no handler opcode 0x%x...\n", __func__,
                       opcode);
 
        return 0;
index 9beb3a9f0336fd55a8e2b709be7a62131c5d9d0a..9c1644fb02599e04a0a468f3ddeda6d776dab722 100644 (file)
@@ -130,6 +130,9 @@ struct c4iw_stats {
        u64  db_empty;
        u64  db_drop;
        u64  db_state_transitions;
+       u64  tcam_full;
+       u64  act_ofld_conn_fails;
+       u64  pas_ofld_conn_fails;
 };
 
 struct c4iw_rdev {
@@ -223,6 +226,9 @@ struct c4iw_dev {
        struct dentry *debugfs_root;
        enum db_state db_state;
        int qpcnt;
+       struct idr hwtid_idr;
+       struct idr atid_idr;
+       struct idr stid_idr;
 };
 
 static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
@@ -712,6 +718,31 @@ enum c4iw_ep_flags {
        CLOSE_SENT              = 3,
 };
 
+enum c4iw_ep_history {
+       ACT_OPEN_REQ            = 0,
+       ACT_OFLD_CONN           = 1,
+       ACT_OPEN_RPL            = 2,
+       ACT_ESTAB               = 3,
+       PASS_ACCEPT_REQ         = 4,
+       PASS_ESTAB              = 5,
+       ABORT_UPCALL            = 6,
+       ESTAB_UPCALL            = 7,
+       CLOSE_UPCALL            = 8,
+       ULP_ACCEPT              = 9,
+       ULP_REJECT              = 10,
+       TIMEDOUT                = 11,
+       PEER_ABORT              = 12,
+       PEER_CLOSE              = 13,
+       CONNREQ_UPCALL          = 14,
+       ABORT_CONN              = 15,
+       DISCONN_UPCALL          = 16,
+       EP_DISC_CLOSE           = 17,
+       EP_DISC_ABORT           = 18,
+       CONN_RPL_UPCALL         = 19,
+       ACT_RETRY_NOMEM         = 20,
+       ACT_RETRY_INUSE         = 21
+};
+
 struct c4iw_ep_common {
        struct iw_cm_id *cm_id;
        struct c4iw_qp *qp;
@@ -723,6 +754,7 @@ struct c4iw_ep_common {
        struct sockaddr_in remote_addr;
        struct c4iw_wr_wait wr_wait;
        unsigned long flags;
+       unsigned long history;
 };
 
 struct c4iw_listen_ep {
@@ -760,6 +792,7 @@ struct c4iw_ep {
        u8 tos;
        u8 retry_with_mpa_v1;
        u8 tried_with_mpa_v1;
+       unsigned int retry_count;
 };
 
 static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
index 832e7a7d0aeeaaf1d4b213120532de26d6465065..f8a62918a88d58ef8609899ce06629175c0775bd 100644 (file)
@@ -713,8 +713,8 @@ static struct attribute_group ehca_dev_attr_grp = {
        .attrs = ehca_dev_attrs
 };
 
-static int __devinit ehca_probe(struct platform_device *dev,
-                               const struct of_device_id *id)
+static int ehca_probe(struct platform_device *dev,
+                     const struct of_device_id *id)
 {
        struct ehca_shca *shca;
        const u64 *handle;
@@ -879,7 +879,7 @@ probe1:
        return -EINVAL;
 }
 
-static int __devexit ehca_remove(struct platform_device *dev)
+static int ehca_remove(struct platform_device *dev)
 {
        struct ehca_shca *shca = dev_get_drvdata(&dev->dev);
        unsigned long flags;
index bfca37b2432f44fa3fa5d577aafd352759c68547..7b371f545ece7b6d817c44ea1486a124e798d6c3 100644 (file)
@@ -127,9 +127,8 @@ const char *ipath_ibcstatus_str[] = {
        "LTState1C", "LTState1D", "LTState1E", "LTState1F"
 };
 
-static void __devexit ipath_remove_one(struct pci_dev *);
-static int __devinit ipath_init_one(struct pci_dev *,
-                                   const struct pci_device_id *);
+static void ipath_remove_one(struct pci_dev *);
+static int ipath_init_one(struct pci_dev *, const struct pci_device_id *);
 
 /* Only needed for registration, nothing else needs this info */
 #define PCI_VENDOR_ID_PATHSCALE 0x1fc1
@@ -148,7 +147,7 @@ MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
 static struct pci_driver ipath_driver = {
        .name = IPATH_DRV_NAME,
        .probe = ipath_init_one,
-       .remove = __devexit_p(ipath_remove_one),
+       .remove = ipath_remove_one,
        .id_table = ipath_pci_tbl,
        .driver = {
                .groups = ipath_driver_attr_groups,
@@ -392,8 +391,7 @@ done:
 
 static void cleanup_device(struct ipath_devdata *dd);
 
-static int __devinit ipath_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret, len, j;
        struct ipath_devdata *dd;
@@ -737,7 +735,7 @@ static void cleanup_device(struct ipath_devdata *dd)
        kfree(tmp);
 }
 
-static void __devexit ipath_remove_one(struct pci_dev *pdev)
+static void ipath_remove_one(struct pci_dev *pdev)
 {
        struct ipath_devdata *dd = pci_get_drvdata(pdev);
 
index aa12a533ae9e426c4d4dc66d5ca255a0d2e2e6a4..87897b95666d2216cb49f9387f8942d5e4142eb9 100644 (file)
@@ -130,7 +130,7 @@ static int log_mtts_per_seg = ilog2(MTHCA_MTT_SEG_SIZE / 8);
 module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
 MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
 
-static char mthca_version[] __devinitdata =
+static char mthca_version[] =
        DRV_NAME ": Mellanox InfiniBand HCA driver v"
        DRV_VERSION " (" DRV_RELDATE ")\n";
 
@@ -1139,8 +1139,7 @@ int __mthca_restart_one(struct pci_dev *pdev)
        return __mthca_init_one(pdev, hca_type);
 }
 
-static int __devinit mthca_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
+static int mthca_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int ret;
 
@@ -1162,7 +1161,7 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
        return ret;
 }
 
-static void __devexit mthca_remove_one(struct pci_dev *pdev)
+static void mthca_remove_one(struct pci_dev *pdev)
 {
        mutex_lock(&mthca_device_mutex);
        __mthca_remove_one(pdev);
@@ -1199,7 +1198,7 @@ static struct pci_driver mthca_driver = {
        .name           = DRV_NAME,
        .id_table       = mthca_pci_table,
        .probe          = mthca_init_one,
-       .remove         = __devexit_p(mthca_remove_one)
+       .remove         = mthca_remove_one,
 };
 
 static void __init __mthca_check_profile_val(const char *name, int *pval,
index 748db2d3e465b9aa0b472bab32e9dbd22ca33ec4..5b152a366dffd550e6b149a8bc56f841db9c1c6b 100644 (file)
@@ -444,7 +444,7 @@ static irqreturn_t nes_interrupt(int irq, void *dev_id)
 /**
  * nes_probe - Device initialization
  */
-static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
+static int nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
 {
        struct net_device *netdev = NULL;
        struct nes_device *nesdev = NULL;
@@ -749,7 +749,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i
 /**
  * nes_remove - unload from kernel
  */
-static void __devexit nes_remove(struct pci_dev *pcidev)
+static void nes_remove(struct pci_dev *pcidev)
 {
        struct nes_device *nesdev = pci_get_drvdata(pcidev);
        struct net_device *netdev;
@@ -810,7 +810,7 @@ static struct pci_driver nes_pci_driver = {
        .name = DRV_NAME,
        .id_table = nes_pci_table,
        .probe = nes_probe,
-       .remove = __devexit_p(nes_remove),
+       .remove = nes_remove,
 };
 
 static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf)
index 4443adfcd9eed58a4a3917e20a020f5866e8f32b..ddf066d9abb6018ef167fbe4e1e25b4c487d7ab2 100644 (file)
@@ -1134,9 +1134,8 @@ void qib_disable_after_error(struct qib_devdata *dd)
                *dd->devstatusp |= QIB_STATUS_HWERROR;
 }
 
-static void __devexit qib_remove_one(struct pci_dev *);
-static int __devinit qib_init_one(struct pci_dev *,
-                                 const struct pci_device_id *);
+static void qib_remove_one(struct pci_dev *);
+static int qib_init_one(struct pci_dev *, const struct pci_device_id *);
 
 #define DRIVER_LOAD_MSG "QLogic " QIB_DRV_NAME " loaded: "
 #define PFX QIB_DRV_NAME ": "
@@ -1153,7 +1152,7 @@ MODULE_DEVICE_TABLE(pci, qib_pci_tbl);
 struct pci_driver qib_driver = {
        .name = QIB_DRV_NAME,
        .probe = qib_init_one,
-       .remove = __devexit_p(qib_remove_one),
+       .remove = qib_remove_one,
        .id_table = qib_pci_tbl,
        .err_handler = &qib_pci_err_handler,
 };
@@ -1342,8 +1341,7 @@ static void qib_postinit_cleanup(struct qib_devdata *dd)
        qib_free_devdata(dd);
 }
 
-static int __devinit qib_init_one(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret, j, pidx, initfail;
        struct qib_devdata *dd = NULL;
@@ -1448,7 +1446,7 @@ bail:
        return ret;
 }
 
-static void __devexit qib_remove_one(struct pci_dev *pdev)
+static void qib_remove_one(struct pci_dev *pdev)
 {
        struct qib_devdata *dd = pci_get_drvdata(pdev);
        int ret;
index 4850d03870c297667e65c96b50d5ccec50b5aa01..35275099cafd660cd2fc20ab865d08c417f51735 100644 (file)
@@ -263,20 +263,15 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
                struct qib_qp __rcu **qpp;
 
                qpp = &dev->qp_table[n];
-               q = rcu_dereference_protected(*qpp,
-                       lockdep_is_held(&dev->qpt_lock));
-               for (; q; qpp = &q->next) {
+               for (; (q = rcu_dereference_protected(*qpp,
+                               lockdep_is_held(&dev->qpt_lock))) != NULL;
+                               qpp = &q->next)
                        if (q == qp) {
                                atomic_dec(&qp->refcount);
                                *qpp = qp->next;
                                rcu_assign_pointer(qp->next, NULL);
-                               q = rcu_dereference_protected(*qpp,
-                                       lockdep_is_held(&dev->qpt_lock));
                                break;
                        }
-                       q = rcu_dereference_protected(*qpp,
-                               lockdep_is_held(&dev->qpt_lock));
-               }
        }
 
        spin_unlock_irqrestore(&dev->qpt_lock, flags);
index 72ae63f0072d45fd931377e4a6f354b271c4b261..67b0c1d23678d26565981cf9815993027c0a1b5e 100644 (file)
@@ -741,6 +741,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
 
        tx_req->mapping = addr;
 
+       skb_orphan(skb);
+       skb_dst_drop(skb);
+
        rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
                       addr, skb->len);
        if (unlikely(rc)) {
index f10221f40803959198a3b85e21b8b57ce01ea60a..2cfa76f5d99eac87bf788eb41bb2a7c3815ec700 100644 (file)
@@ -600,6 +600,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                netif_stop_queue(dev);
        }
 
+       skb_orphan(skb);
+       skb_dst_drop(skb);
+
        rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
                       address->ah, qpn, tx_req, phead, hlen);
        if (unlikely(rc)) {
@@ -615,8 +618,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
 
                address->last_send = priv->tx_head;
                ++priv->tx_head;
-               skb_orphan(skb);
-
        }
 
        if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
index ce01332f7b3a8c770b1c31875b4d555dd38e56a3..c0446992892533b24d3853d043cf088451db5662 100644 (file)
@@ -1785,12 +1785,13 @@ static void devm_input_device_release(struct device *dev, void *res)
  * its driver (or binding fails). Once managed input device is allocated,
  * it is ready to be set up and registered in the same fashion as regular
  * input device. There are no special devm_input_device_[un]register()
- * variants, regular ones work with both managed and unmanaged devices.
+ * variants, regular ones work with both managed and unmanaged devices,
+ * should you need them. In most cases however, managed input device need
+ * not be explicitly unregistered or freed.
  *
  * NOTE: the owner device is set up as parent of input device and users
  * should not override it.
  */
-
 struct input_dev *devm_input_allocate_device(struct device *dev)
 {
        struct input_dev *input;
@@ -2004,6 +2005,17 @@ static void devm_input_device_unregister(struct device *dev, void *res)
  * Once device has been successfully registered it can be unregistered
  * with input_unregister_device(); input_free_device() should not be
  * called in this case.
+ *
+ * Note that this function is also used to register managed input devices
+ * (ones allocated with devm_input_allocate_device()). Such managed input
+ * devices need not be explicitly unregistered or freed, their tear down
+ * is controlled by the devres infrastructure. It is also worth noting
+ * that tear down of managed input devices is internally a 2-step process:
+ * registered managed input device is first unregistered, but stays in
+ * memory and can still handle input_event() calls (although events will
+ * not be delivered anywhere). The freeing of managed input device will
+ * happen later, when devres stack is unwound to the point where device
+ * allocation was made.
  */
 int input_register_device(struct input_dev *dev)
 {
index 358cd7ee905b7ff4f9a7498e277341037437bf19..7cd74e29cbc87a6495277ecd74d7135ebcd75ad3 100644 (file)
@@ -162,7 +162,7 @@ static unsigned int get_time_pit(void)
 #define GET_TIME(x)    do { x = get_cycles(); } while (0)
 #define DELTA(x,y)     ((y)-(x))
 #define TIME_NAME      "PCC"
-#elif defined(CONFIG_MN10300)
+#elif defined(CONFIG_MN10300) || defined(CONFIG_TILE)
 #define GET_TIME(x)    do { x = get_cycles(); } while (0)
 #define DELTA(x, y)    ((x) - (y))
 #define TIME_NAME      "TSC"
index d327f5a2bb0eadb3884c9dc42ce518cd29be2ebd..b29ca651a3951e568527e4c7a041f101bba06c3a 100644 (file)
@@ -602,6 +602,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
 
        i = 0;
        for_each_child_of_node(node, pp) {
+               int gpio;
                enum of_gpio_flags flags;
 
                if (!of_find_property(pp, "gpios", NULL)) {
@@ -610,9 +611,19 @@ gpio_keys_get_devtree_pdata(struct device *dev)
                        continue;
                }
 
+               gpio = of_get_gpio_flags(pp, 0, &flags);
+               if (gpio < 0) {
+                       error = gpio;
+                       if (error != -EPROBE_DEFER)
+                               dev_err(dev,
+                                       "Failed to get gpio flags, error: %d\n",
+                                       error);
+                       goto err_free_pdata;
+               }
+
                button = &pdata->buttons[i++];
 
-               button->gpio = of_get_gpio_flags(pp, 0, &flags);
+               button->gpio = gpio;
                button->active_low = flags & OF_GPIO_ACTIVE_LOW;
 
                if (of_property_read_u32(pp, "linux,code", &button->code)) {
index f686fd970553afb12b7d829fa6756c60c5598ee4..21147164874d8592227d92a96a5c97f59e217ca5 100644 (file)
@@ -135,6 +135,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 
        i = 0;
        for_each_child_of_node(node, pp) {
+               int gpio;
                enum of_gpio_flags flags;
 
                if (!of_find_property(pp, "gpios", NULL)) {
@@ -143,9 +144,19 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
                        continue;
                }
 
+               gpio = of_get_gpio_flags(pp, 0, &flags);
+               if (gpio < 0) {
+                       error = gpio;
+                       if (error != -EPROBE_DEFER)
+                               dev_err(dev,
+                                       "Failed to get gpio flags, error: %d\n",
+                                       error);
+                       goto err_free_pdata;
+               }
+
                button = &pdata->buttons[i++];
 
-               button->gpio = of_get_gpio_flags(pp, 0, &flags);
+               button->gpio = gpio;
                button->active_low = flags & OF_GPIO_ACTIVE_LOW;
 
                if (of_property_read_u32(pp, "linux,code", &button->code)) {
index 93c812662134392aa973d9dcff4ffec97b601205..0de23f41b2d316364b8a0f50b8b1b72ca5c9555b 100644 (file)
@@ -398,7 +398,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm)
                        lm8323_configure(lm);
                }
                for (i = 0; i < LM8323_NUM_PWMS; i++) {
-                       if (ints & (1 << (INT_PWM1 + i))) {
+                       if (ints & (INT_PWM1 << i)) {
                                dev_vdbg(&lm->client->dev,
                                         "pwm%d engine completed\n", i);
                                pwm_done(&lm->pwm[i]);
index 50e9c5e195e110e2f287568841cc5d9b4ff606ed..a34cc6714e5bc765315039bf3d3bb43a60820766 100644 (file)
@@ -384,7 +384,7 @@ static const struct i2c_device_id tca8418_id[] = {
 MODULE_DEVICE_TABLE(i2c, tca8418_id);
 
 #ifdef CONFIG_OF
-static const struct of_device_id tca8418_dt_ids[] __devinitconst = {
+static const struct of_device_id tca8418_dt_ids[] = {
        { .compatible = "ti,tca8418", },
        { }
 };
index e582922bacf7d5715cf0f70216c3dd8a4d299eeb..cc7e0d4a8f93a1e5e32031478d87643d396f9a18 100644 (file)
@@ -791,7 +791,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
                        fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y);
                        fsp_set_slot(dev, 1, false, 0, 0);
                }
-               if (fgrs > 0) {
+               if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) {
                        input_report_abs(dev, ABS_X, abs_x);
                        input_report_abs(dev, ABS_Y, abs_y);
                }
index f92d34f45a1cc6ad13af95f42440021f3bafe2bf..aaf23aeae2ea428b4a26ea0cd99f20eeac32c964 100644 (file)
@@ -553,10 +553,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
        if (!rep_data)
                return error;
 
-       rep_data[0] = report_id;
-       rep_data[1] = mode;
-
        do {
+               rep_data[0] = report_id;
+               rep_data[1] = mode;
+
                error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
                                         report_id, rep_data, length, 1);
                if (error >= 0)
index c1c74e030a58df6ea1020cec05c0f01acb14fb76..d33eaaf783ad571378d8125e66c243054eb6065c 100644 (file)
@@ -4017,10 +4017,10 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
 
                        index -= count - 1;
 
+                       cfg->remapped         = 1;
                        irte_info             = &cfg->irq_2_iommu;
                        irte_info->sub_handle = devid;
                        irte_info->irte_index = index;
-                       irte_info->iommu      = (void *)cfg;
 
                        goto out;
                }
@@ -4127,9 +4127,9 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
        index = attr->ioapic_pin;
 
        /* Setup IRQ remapping info */
+       cfg->remapped         = 1;
        irte_info->sub_handle = devid;
        irte_info->irte_index = index;
-       irte_info->iommu      = (void *)cfg;
 
        /* Setup IRTE for IOMMU */
        irte.val                = 0;
@@ -4288,9 +4288,9 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
        devid           = get_device_id(&pdev->dev);
        irte_info       = &cfg->irq_2_iommu;
 
+       cfg->remapped         = 1;
        irte_info->sub_handle = devid;
        irte_info->irte_index = index + offset;
-       irte_info->iommu      = (void *)cfg;
 
        return 0;
 }
@@ -4314,9 +4314,9 @@ static int setup_hpet_msi(unsigned int irq, unsigned int id)
        if (index < 0)
                return index;
 
+       cfg->remapped         = 1;
        irte_info->sub_handle = devid;
        irte_info->irte_index = index;
-       irte_info->iommu      = (void *)cfg;
 
        return 0;
 }
index 81837b0710a9ba0240b1eba3c1b3f8b51d997e2f..faf10ba1ed9ad1dcfcd00dabc26c725cf7e9ad00 100644 (file)
@@ -974,6 +974,38 @@ static void __init free_iommu_all(void)
        }
 }
 
+/*
+ * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations)
+ * Workaround:
+ *     BIOS should disable L2B micellaneous clock gating by setting
+ *     L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b
+ */
+static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
+{
+       u32 value;
+
+       if ((boot_cpu_data.x86 != 0x15) ||
+           (boot_cpu_data.x86_model < 0x10) ||
+           (boot_cpu_data.x86_model > 0x1f))
+               return;
+
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+       pci_read_config_dword(iommu->dev, 0xf4, &value);
+
+       if (value & BIT(2))
+               return;
+
+       /* Select NB indirect register 0x90 and enable writing */
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8));
+
+       pci_write_config_dword(iommu->dev, 0xf4, value | 0x4);
+       pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n",
+               dev_name(&iommu->dev->dev));
+
+       /* Clear the enable writing bit */
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+}
+
 /*
  * This function clues the initialization function for one IOMMU
  * together and also allocates the command buffer and programs the
@@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)
                        iommu->stored_l2[i] = iommu_read_l2(iommu, i);
        }
 
+       amd_iommu_erratum_746_workaround(iommu);
+
        return pci_enable_device(iommu->dev);
 }
 
index 86e2f4a62b9a95fed887dda18b6bd5bdd2cdacda..174bb654453de7e4ece57f1e0807a48bd85122e5 100644 (file)
@@ -41,6 +41,8 @@
 #include <asm/irq_remapping.h>
 #include <asm/iommu_table.h>
 
+#include "irq_remapping.h"
+
 /* No locks are needed as DMA remapping hardware unit
  * list is constructed at boot time and hotplug of
  * these units are not supported by the architecture.
index c2c07a4a7f21c5f57d9eca2884933dd99088b60a..43d5c8b8e7ad05681e758d23727fa680595c62f3 100644 (file)
@@ -46,6 +46,8 @@
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
 
+#include "irq_remapping.h"
+
 #define ROOT_SIZE              VTD_PAGE_SIZE
 #define CONTEXT_SIZE           VTD_PAGE_SIZE
 
@@ -4234,7 +4236,22 @@ static struct iommu_ops intel_iommu_ops = {
        .pgsize_bitmap  = INTEL_IOMMU_PGSIZES,
 };
 
-static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
+static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
+{
+       /* G4x/GM45 integrated gfx dmar support is totally busted. */
+       printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+       dmar_map_gfx = 0;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
+
+static void quirk_iommu_rwbf(struct pci_dev *dev)
 {
        /*
         * Mobile 4 Series Chipset neglects to set RWBF capability,
@@ -4242,12 +4259,6 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
         */
        printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
        rwbf_quirk = 1;
-
-       /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
-       if (dev->revision == 0x07) {
-               printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
-               dmar_map_gfx = 0;
-       }
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
@@ -4262,7 +4273,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
 #define GGC_MEMORY_SIZE_3M_VT  (0xa << 8)
 #define GGC_MEMORY_SIZE_4M_VT  (0xb << 8)
 
-static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
+static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
 {
        unsigned short ggc;
 
index af8904de1d44e63ca35be4a58320889b2bab7a8b..f3b8f23b5d8f1d89cd5dea093faa9441061ca00c 100644 (file)
@@ -68,6 +68,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
 {
        struct ir_table *table = iommu->ir_table;
        struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+       struct irq_cfg *cfg = irq_get_chip_data(irq);
        u16 index, start_index;
        unsigned int mask = 0;
        unsigned long flags;
@@ -115,6 +116,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
        for (i = index; i < index + count; i++)
                table->base[i].present = 1;
 
+       cfg->remapped = 1;
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index =  index;
        irq_iommu->sub_handle = 0;
@@ -155,6 +157,7 @@ static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
 static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
        struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+       struct irq_cfg *cfg = irq_get_chip_data(irq);
        unsigned long flags;
 
        if (!irq_iommu)
@@ -162,6 +165,7 @@ static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subha
 
        raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
+       cfg->remapped = 1;
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index = index;
        irq_iommu->sub_handle = subhandle;
@@ -425,11 +429,22 @@ static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode)
 
        /* Enable interrupt-remapping */
        iommu->gcmd |= DMA_GCMD_IRE;
+       iommu->gcmd &= ~DMA_GCMD_CFI;  /* Block compatibility-format MSIs */
        writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 
        IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
                      readl, (sts & DMA_GSTS_IRES), sts);
 
+       /*
+        * With CFI clear in the Global Command register, we should be
+        * protected from dangerous (i.e. compatibility) interrupts
+        * regardless of x2apic status.  Check just to be sure.
+        */
+       if (sts & DMA_GSTS_CFIS)
+               WARN(1, KERN_WARNING
+                       "Compatibility-format IRQs enabled despite intr remapping;\n"
+                       "you are vulnerable to IRQ injection.\n");
+
        raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
@@ -526,20 +541,24 @@ static int __init intel_irq_remapping_supported(void)
 static int __init intel_enable_irq_remapping(void)
 {
        struct dmar_drhd_unit *drhd;
+       bool x2apic_present;
        int setup = 0;
        int eim = 0;
 
+       x2apic_present = x2apic_supported();
+
        if (parse_ioapics_under_ir() != 1) {
                printk(KERN_INFO "Not enable interrupt remapping\n");
-               return -1;
+               goto error;
        }
 
-       if (x2apic_supported()) {
+       if (x2apic_present) {
                eim = !dmar_x2apic_optout();
-               WARN(!eim, KERN_WARNING
-                          "Your BIOS is broken and requested that x2apic be disabled\n"
-                          "This will leave your machine vulnerable to irq-injection attacks\n"
-                          "Use 'intremap=no_x2apic_optout' to override BIOS request\n");
+               if (!eim)
+                       printk(KERN_WARNING
+                               "Your BIOS is broken and requested that x2apic be disabled.\n"
+                               "This will slightly decrease performance.\n"
+                               "Use 'intremap=no_x2apic_optout' to override BIOS request.\n");
        }
 
        for_each_drhd_unit(drhd) {
@@ -578,7 +597,7 @@ static int __init intel_enable_irq_remapping(void)
                if (eim && !ecap_eim_support(iommu->ecap)) {
                        printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
                               " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
-                       return -1;
+                       goto error;
                }
        }
 
@@ -594,7 +613,7 @@ static int __init intel_enable_irq_remapping(void)
                        printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
                               " invalidation, ecap %Lx, ret %d\n",
                               drhd->reg_base_addr, iommu->ecap, ret);
-                       return -1;
+                       goto error;
                }
        }
 
@@ -617,6 +636,14 @@ static int __init intel_enable_irq_remapping(void)
                goto error;
 
        irq_remapping_enabled = 1;
+
+       /*
+        * VT-d has a different layout for IO-APIC entries when
+        * interrupt remapping is enabled. So it needs a special routine
+        * to print IO-APIC entries for debugging purposes too.
+        */
+       x86_io_apic_ops.print_entries = intel_ir_io_apic_print_entries;
+
        pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
 
        return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
@@ -625,6 +652,11 @@ error:
        /*
         * handle error condition gracefully here!
         */
+
+       if (x2apic_present)
+               WARN(1, KERN_WARNING
+                       "Failed to enable irq remapping.  You are vulnerable to irq-injection attacks.\n");
+
        return -1;
 }
 
index faf85d6e33fe0bb3dde0c229570fac156d9e9798..d56f8c17c5fe4dcc2e4db23085d4914b977c0fd0 100644 (file)
@@ -1,11 +1,18 @@
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/cpumask.h>
 #include <linux/errno.h>
 #include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
 
 #include <asm/hw_irq.h>
 #include <asm/irq_remapping.h>
+#include <asm/processor.h>
+#include <asm/x86_init.h>
+#include <asm/apic.h>
 
 #include "irq_remapping.h"
 
@@ -17,6 +24,152 @@ int no_x2apic_optout;
 
 static struct irq_remap_ops *remap_ops;
 
+static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
+static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+                                 int index, int sub_handle);
+static int set_remapped_irq_affinity(struct irq_data *data,
+                                    const struct cpumask *mask,
+                                    bool force);
+
+static bool irq_remapped(struct irq_cfg *cfg)
+{
+       return (cfg->remapped == 1);
+}
+
+static void irq_remapping_disable_io_apic(void)
+{
+       /*
+        * With interrupt-remapping, for now we will use virtual wire A
+        * mode, as virtual wire B is little complex (need to configure
+        * both IOAPIC RTE as well as interrupt-remapping table entry).
+        * As this gets called during crash dump, keep this simple for
+        * now.
+        */
+       if (cpu_has_apic || apic_from_smp_config())
+               disconnect_bsp_APIC(0);
+}
+
+static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
+{
+       int node, ret, sub_handle, index = 0;
+       unsigned int irq;
+       struct msi_desc *msidesc;
+
+       nvec = __roundup_pow_of_two(nvec);
+
+       WARN_ON(!list_is_singular(&dev->msi_list));
+       msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+       WARN_ON(msidesc->irq);
+       WARN_ON(msidesc->msi_attrib.multiple);
+
+       node = dev_to_node(&dev->dev);
+       irq = __create_irqs(get_nr_irqs_gsi(), nvec, node);
+       if (irq == 0)
+               return -ENOSPC;
+
+       msidesc->msi_attrib.multiple = ilog2(nvec);
+       for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
+               if (!sub_handle) {
+                       index = msi_alloc_remapped_irq(dev, irq, nvec);
+                       if (index < 0) {
+                               ret = index;
+                               goto error;
+                       }
+               } else {
+                       ret = msi_setup_remapped_irq(dev, irq + sub_handle,
+                                                    index, sub_handle);
+                       if (ret < 0)
+                               goto error;
+               }
+               ret = setup_msi_irq(dev, msidesc, irq, sub_handle);
+               if (ret < 0)
+                       goto error;
+       }
+       return 0;
+
+error:
+       destroy_irqs(irq, nvec);
+
+       /*
+        * Restore altered MSI descriptor fields and prevent just destroyed
+        * IRQs from tearing down again in default_teardown_msi_irqs()
+        */
+       msidesc->irq = 0;
+       msidesc->msi_attrib.multiple = 0;
+
+       return ret;
+}
+
+static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
+{
+       int node, ret, sub_handle, index = 0;
+       struct msi_desc *msidesc;
+       unsigned int irq;
+
+       node            = dev_to_node(&dev->dev);
+       irq             = get_nr_irqs_gsi();
+       sub_handle      = 0;
+
+       list_for_each_entry(msidesc, &dev->msi_list, list) {
+
+               irq = create_irq_nr(irq, node);
+               if (irq == 0)
+                       return -1;
+
+               if (sub_handle == 0)
+                       ret = index = msi_alloc_remapped_irq(dev, irq, nvec);
+               else
+                       ret = msi_setup_remapped_irq(dev, irq, index, sub_handle);
+
+               if (ret < 0)
+                       goto error;
+
+               ret = setup_msi_irq(dev, msidesc, irq, 0);
+               if (ret < 0)
+                       goto error;
+
+               sub_handle += 1;
+               irq        += 1;
+       }
+
+       return 0;
+
+error:
+       destroy_irq(irq);
+       return ret;
+}
+
+static int irq_remapping_setup_msi_irqs(struct pci_dev *dev,
+                                       int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSI)
+               return do_setup_msi_irqs(dev, nvec);
+       else
+               return do_setup_msix_irqs(dev, nvec);
+}
+
+void eoi_ioapic_pin_remapped(int apic, int pin, int vector)
+{
+       /*
+        * Intr-remapping uses pin number as the virtual vector
+        * in the RTE. Actual vector is programmed in
+        * intr-remapping table entry. Hence for the io-apic
+        * EOI we use the pin number.
+        */
+       io_apic_eoi(apic, pin);
+}
+
+static void __init irq_remapping_modify_x86_ops(void)
+{
+       x86_io_apic_ops.disable         = irq_remapping_disable_io_apic;
+       x86_io_apic_ops.set_affinity    = set_remapped_irq_affinity;
+       x86_io_apic_ops.setup_entry     = setup_ioapic_remapped_entry;
+       x86_io_apic_ops.eoi_ioapic_pin  = eoi_ioapic_pin_remapped;
+       x86_msi.setup_msi_irqs          = irq_remapping_setup_msi_irqs;
+       x86_msi.setup_hpet_msi          = setup_hpet_msi_remapped;
+       x86_msi.compose_msi_msg         = compose_remapped_msi_msg;
+}
+
 static __init int setup_nointremap(char *str)
 {
        disable_irq_remap = 1;
@@ -79,15 +232,24 @@ int __init irq_remapping_prepare(void)
 
 int __init irq_remapping_enable(void)
 {
+       int ret;
+
        if (!remap_ops || !remap_ops->enable)
                return -ENODEV;
 
-       return remap_ops->enable();
+       ret = remap_ops->enable();
+
+       if (irq_remapping_enabled)
+               irq_remapping_modify_x86_ops();
+
+       return ret;
 }
 
 void irq_remapping_disable(void)
 {
-       if (!remap_ops || !remap_ops->disable)
+       if (!irq_remapping_enabled ||
+           !remap_ops ||
+           !remap_ops->disable)
                return;
 
        remap_ops->disable();
@@ -95,7 +257,9 @@ void irq_remapping_disable(void)
 
 int irq_remapping_reenable(int mode)
 {
-       if (!remap_ops || !remap_ops->reenable)
+       if (!irq_remapping_enabled ||
+           !remap_ops ||
+           !remap_ops->reenable)
                return 0;
 
        return remap_ops->reenable(mode);
@@ -103,6 +267,9 @@ int irq_remapping_reenable(int mode)
 
 int __init irq_remap_enable_fault_handling(void)
 {
+       if (!irq_remapping_enabled)
+               return 0;
+
        if (!remap_ops || !remap_ops->enable_faulting)
                return -ENODEV;
 
@@ -133,23 +300,28 @@ int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
 
 void free_remapped_irq(int irq)
 {
+       struct irq_cfg *cfg = irq_get_chip_data(irq);
+
        if (!remap_ops || !remap_ops->free_irq)
                return;
 
-       remap_ops->free_irq(irq);
+       if (irq_remapped(cfg))
+               remap_ops->free_irq(irq);
 }
 
 void compose_remapped_msi_msg(struct pci_dev *pdev,
                              unsigned int irq, unsigned int dest,
                              struct msi_msg *msg, u8 hpet_id)
 {
-       if (!remap_ops || !remap_ops->compose_msi_msg)
-               return;
+       struct irq_cfg *cfg = irq_get_chip_data(irq);
 
-       remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
+       if (!irq_remapped(cfg))
+               native_compose_msi_msg(pdev, irq, dest, msg, hpet_id);
+       else if (remap_ops && remap_ops->compose_msi_msg)
+               remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
 }
 
-int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
+static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
 {
        if (!remap_ops || !remap_ops->msi_alloc_irq)
                return -ENODEV;
@@ -157,8 +329,8 @@ int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
        return remap_ops->msi_alloc_irq(pdev, irq, nvec);
 }
 
-int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
-                          int index, int sub_handle)
+static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
+                                 int index, int sub_handle)
 {
        if (!remap_ops || !remap_ops->msi_setup_irq)
                return -ENODEV;
@@ -173,3 +345,42 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
 
        return remap_ops->setup_hpet_msi(irq, id);
 }
+
+void panic_if_irq_remap(const char *msg)
+{
+       if (irq_remapping_enabled)
+               panic(msg);
+}
+
+static void ir_ack_apic_edge(struct irq_data *data)
+{
+       ack_APIC_irq();
+}
+
+static void ir_ack_apic_level(struct irq_data *data)
+{
+       ack_APIC_irq();
+       eoi_ioapic_irq(data->irq, data->chip_data);
+}
+
+static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
+{
+       seq_printf(p, " IR-%s", data->chip->name);
+}
+
+void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+       chip->irq_print_chip = ir_print_prefix;
+       chip->irq_ack = ir_ack_apic_edge;
+       chip->irq_eoi = ir_ack_apic_level;
+       chip->irq_set_affinity = x86_io_apic_ops.set_affinity;
+}
+
+bool setup_remapped_irq(int irq, struct irq_cfg *cfg, struct irq_chip *chip)
+{
+       if (!irq_remapped(cfg))
+               return false;
+       irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
+       irq_remap_modify_chip_defaults(chip);
+       return true;
+}
index 95363acb583fe3613a7d82bbbf7255ea1455c6eb..ecb63767040553b16fa8c469f48a10799c6e8e18 100644 (file)
@@ -34,6 +34,7 @@ struct msi_msg;
 extern int disable_irq_remap;
 extern int disable_sourceid_checking;
 extern int no_x2apic_optout;
+extern int irq_remapping_enabled;
 
 struct irq_remap_ops {
        /* Check whether Interrupt Remapping is supported */
index 18108c1405e2ae433646f1f1de6d3878e30fcb29..d33c980e9c205a3158dec5993ab9b80327690325 100644 (file)
@@ -934,7 +934,7 @@ static void omap_iommu_detach(struct omap_iommu *obj)
 /*
  *     OMAP Device MMU(IOMMU) detection
  */
-static int __devinit omap_iommu_probe(struct platform_device *pdev)
+static int omap_iommu_probe(struct platform_device *pdev)
 {
        int err = -ENODEV;
        int irq;
@@ -1003,7 +1003,7 @@ err_mem:
        return err;
 }
 
-static int __devexit omap_iommu_remove(struct platform_device *pdev)
+static int omap_iommu_remove(struct platform_device *pdev)
 {
        int irq;
        struct resource *res;
@@ -1028,7 +1028,7 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_iommu_driver = {
        .probe  = omap_iommu_probe,
-       .remove = __devexit_p(omap_iommu_remove),
+       .remove = omap_iommu_remove,
        .driver = {
                .name   = "omap-iommu",
        },
index 4c9db62814ffde1c2f3cc513eda788490cb000f4..8219f1d596ee8d339562f6d4122b47f20545ab46 100644 (file)
@@ -431,7 +431,7 @@ const struct dev_pm_ops tegra_gart_pm_ops = {
 };
 
 #ifdef CONFIG_OF
-static struct of_device_id tegra_gart_of_match[] __devinitdata = {
+static struct of_device_id tegra_gart_of_match[] = {
        { .compatible = "nvidia,tegra20-gart", },
        { },
 };
@@ -449,7 +449,7 @@ static struct platform_driver tegra_gart_driver = {
        },
 };
 
-static int __devinit tegra_gart_init(void)
+static int tegra_gart_init(void)
 {
        return platform_driver_register(&tegra_gart_driver);
 }
index 25c1210c0832b05fc36033969573af27c39e25cc..fc178893789a444ee9ac0267c4993fc3ba152e49 100644 (file)
@@ -1255,7 +1255,7 @@ const struct dev_pm_ops tegra_smmu_pm_ops = {
 };
 
 #ifdef CONFIG_OF
-static struct of_device_id tegra_smmu_of_match[] __devinitdata = {
+static struct of_device_id tegra_smmu_of_match[] = {
        { .compatible = "nvidia,tegra30-smmu", },
        { },
 };
@@ -1273,7 +1273,7 @@ static struct platform_driver tegra_smmu_driver = {
        },
 };
 
-static int __devinit tegra_smmu_init(void)
+static int tegra_smmu_init(void)
 {
        return platform_driver_register(&tegra_smmu_driver);
 }
index 68452b768da23dc31c5409b113446802476886c2..03a0a01a405451c8a85e0e9b83647c105a710f53 100644 (file)
@@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag,
                CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l,
                CAPIMSG_CONTROL(data));
        l -= 12;
+       if (l <= 0)
+               return;
        dbgline = kmalloc(3 * l, GFP_ATOMIC);
        if (!dbgline)
                return;
index b305e6b2b8ee24d5948fc0a30142b8b9f1a03a1c..ac4863c2ecbc6a18a86bf62008fcde2aa216c0a2 100644 (file)
@@ -299,8 +299,8 @@ static void b1pciv4_remove(struct pci_dev *pdev)
 
 #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
 
-static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int b1pci_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct capicardparams param;
        int retval;
@@ -344,7 +344,7 @@ static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
        return retval;
 }
 
-static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
+static void b1pci_pci_remove(struct pci_dev *pdev)
 {
 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
        avmcard *card = pci_get_drvdata(pdev);
@@ -362,7 +362,7 @@ static struct pci_driver b1pci_pci_driver = {
        .name           = "b1pci",
        .id_table       = b1pci_pci_tbl,
        .probe          = b1pci_pci_probe,
-       .remove         = __devexit_p(b1pci_pci_remove),
+       .remove         = b1pci_pci_remove,
 };
 
 static struct capi_driver capi_driver_b1pci = {
index 98f18812441de3d7158e945ee583b153f4470241..1d7fc44e3eeffcbf5137592a270b31ad02de43fb 100644 (file)
@@ -1249,8 +1249,7 @@ err:
 
 /* ------------------------------------------------------------- */
 
-static int __devinit c4_probe(struct pci_dev *dev,
-                             const struct pci_device_id *ent)
+static int c4_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        int nr = ent->driver_data;
        int retval = 0;
index cb9a30427bd2e2123f981c898589824f829c6547..2180b168569128dbeb264774071ab478c0aa4ca2 100644 (file)
@@ -187,8 +187,7 @@ static char *t1pci_procinfo(struct capi_ctr *ctrl)
 
 /* ------------------------------------------------------------- */
 
-static int __devinit t1pci_probe(struct pci_dev *dev,
-                                const struct pci_device_id *ent)
+static int t1pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct capicardparams param;
        int retval;
index ca6d276bb2562ac4b481db11da7c9e35d81dc3da..52377b4bf039e0cbe19249ee3361acbd6ce85014 100644 (file)
@@ -150,12 +150,12 @@ MODULE_DEVICE_TABLE(pci, divas_pci_tbl);
 
 static int divas_init_one(struct pci_dev *pdev,
                          const struct pci_device_id *ent);
-static void __devexit divas_remove_one(struct pci_dev *pdev);
+static void divas_remove_one(struct pci_dev *pdev);
 
 static struct pci_driver diva_pci_driver = {
        .name     = "divas",
        .probe    = divas_init_one,
-       .remove   = __devexit_p(divas_remove_one),
+       .remove   = divas_remove_one,
        .id_table = divas_pci_tbl,
 };
 
@@ -688,8 +688,7 @@ static int __init divas_register_chrdev(void)
 /* --------------------------------------------------------------------------
    PCI driver section
    -------------------------------------------------------------------------- */
-static int __devinit divas_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int divas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        void *pdiva = NULL;
        u8 pci_latency;
@@ -749,7 +748,7 @@ static int __devinit divas_init_one(struct pci_dev *pdev,
        return (0);
 }
 
-static void __devexit divas_remove_one(struct pci_dev *pdev)
+static void divas_remove_one(struct pci_dev *pdev)
 {
        void *pdiva = pci_get_drvdata(pdev);
 
index dceaec821b0e5324cbfa2d92bdb7334845bf9262..292991c90c0248948190fbebe818fd19ecc289cb 100644 (file)
@@ -1034,7 +1034,7 @@ release_card(struct fritzcard *card)
        AVM_cnt--;
 }
 
-static int __devinit
+static int
 setup_instance(struct fritzcard *card)
 {
        int i, err;
@@ -1096,7 +1096,7 @@ error:
        return err;
 }
 
-static int __devinit
+static int
 fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -ENOMEM;
@@ -1130,7 +1130,7 @@ fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit
+static void
 fritz_remove_pci(struct pci_dev *pdev)
 {
        struct fritzcard *card = pci_get_drvdata(pdev);
@@ -1142,7 +1142,7 @@ fritz_remove_pci(struct pci_dev *pdev)
                        pr_info("%s: drvdata already removed\n", __func__);
 }
 
-static struct pci_device_id fcpci_ids[] __devinitdata = {
+static struct pci_device_id fcpci_ids[] = {
        { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID,
          0, 0, (unsigned long) "Fritz!Card PCI"},
        { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
@@ -1154,7 +1154,7 @@ MODULE_DEVICE_TABLE(pci, fcpci_ids);
 static struct pci_driver fcpci_driver = {
        .name = "fcpci",
        .probe = fritzpci_probe,
-       .remove = __devexit_p(fritz_remove_pci),
+       .remove = fritz_remove_pci,
        .id_table = fcpci_ids,
 };
 
index f02794203bb193b41291efc3bc6d8457b2043883..28543d7951886e17026303c66e765b0077062efc 100644 (file)
@@ -5274,7 +5274,7 @@ free_card:
        return ret_err;
 }
 
-static void __devexit hfc_remove_pci(struct pci_dev *pdev)
+static void hfc_remove_pci(struct pci_dev *pdev)
 {
        struct hfc_multi        *card = pci_get_drvdata(pdev);
        u_long                  flags;
@@ -5351,7 +5351,7 @@ static const struct hm_map hfcm_map[] = {
 
 #undef H
 #define H(x)   ((unsigned long)&hfcm_map[x])
-static struct pci_device_id hfmultipci_ids[] __devinitdata = {
+static struct pci_device_id hfmultipci_ids[] = {
 
        /* Cards with HFC-4S Chip */
        { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
@@ -5472,7 +5472,7 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static struct pci_driver hfcmultipci_driver = {
        .name           = "hfc_multi",
        .probe          = hfcmulti_probe,
-       .remove         = __devexit_p(hfc_remove_pci),
+       .remove         = hfc_remove_pci,
        .id_table       = hfmultipci_ids,
 };
 
index 6e99d73563b8abbe8b5c6931b741ab15a5536a33..a7e4939787c957a0f7975c4ea3d8aaaa390e6d2b 100644 (file)
@@ -2215,7 +2215,7 @@ static struct pci_device_id hfc_ids[] =
        {},
 };
 
-static int __devinit
+static int
 hfc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int             err = -ENOMEM;
@@ -2246,7 +2246,7 @@ hfc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit
+static void
 hfc_remove_pci(struct pci_dev *pdev)
 {
        struct hfc_pci  *card = pci_get_drvdata(pdev);
@@ -2263,7 +2263,7 @@ hfc_remove_pci(struct pci_dev *pdev)
 static struct pci_driver hfc_driver = {
        .name = "hfcpci",
        .probe = hfc_probe,
-       .remove = __devexit_p(hfc_remove_pci),
+       .remove = hfc_remove_pci,
        .id_table = hfc_ids,
 };
 
index 631eb3fa63cf1558d3c044a3e1d3a26f5567f2b8..c1493f4162fbca4b6c6343e19035758f13ddbc68 100644 (file)
@@ -125,7 +125,7 @@ struct inf_hw {
 #define PCI_SUBVENDOR_SEDLBAUER_PCI     0x53
 #define PCI_SUB_ID_SEDLBAUER            0x01
 
-static struct pci_device_id infineon_ids[] __devinitdata = {
+static struct pci_device_id infineon_ids[] = {
        { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 },
        { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U },
        { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 },
@@ -603,7 +603,7 @@ inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
        return ret;
 }
 
-static int __devinit
+static int
 init_irq(struct inf_hw *hw)
 {
        int     ret, cnt = 3;
@@ -662,7 +662,7 @@ release_io(struct inf_hw *hw)
        }
 }
 
-static int __devinit
+static int
 setup_io(struct inf_hw *hw)
 {
        int err = 0;
@@ -896,7 +896,7 @@ release_card(struct inf_hw *card) {
        inf_cnt--;
 }
 
-static int __devinit
+static int
 setup_instance(struct inf_hw *card)
 {
        int err;
@@ -1060,7 +1060,7 @@ static const struct inf_cinfo inf_card_info[] = {
        }
 };
 
-static const struct inf_cinfo * __devinit
+static const struct inf_cinfo *
 get_card_info(enum inf_types typ)
 {
        const struct inf_cinfo *ci = inf_card_info;
@@ -1073,7 +1073,7 @@ get_card_info(enum inf_types typ)
        return NULL;
 }
 
-static int __devinit
+static int
 inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -ENOMEM;
@@ -1135,7 +1135,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit
+static void
 inf_remove(struct pci_dev *pdev)
 {
        struct inf_hw   *card = pci_get_drvdata(pdev);
@@ -1149,7 +1149,7 @@ inf_remove(struct pci_dev *pdev)
 static struct pci_driver infineon_driver = {
        .name = "ISDN Infineon pci",
        .probe = inf_probe,
-       .remove = __devexit_p(inf_remove),
+       .remove = inf_remove,
        .id_table = infineon_ids,
 };
 
index 9bcade59eb73bdf24f72e8fa5a6e08e4be641f1c..8e2944784e0004e4fc933d691607c4e822c3bf66 100644 (file)
@@ -1008,7 +1008,7 @@ nj_setup(struct tiger_hw *card)
 }
 
 
-static int __devinit
+static int
 setup_instance(struct tiger_hw *card)
 {
        int i, err;
@@ -1059,7 +1059,7 @@ error:
        return err;
 }
 
-static int __devinit
+static int
 nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -ENOMEM;
@@ -1124,7 +1124,7 @@ nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 }
 
 
-static void __devexit nj_remove(struct pci_dev *pdev)
+static void nj_remove(struct pci_dev *pdev)
 {
        struct tiger_hw *card = pci_get_drvdata(pdev);
 
@@ -1137,7 +1137,7 @@ static void __devexit nj_remove(struct pci_dev *pdev)
 /* We cannot select cards with PCI_SUB... IDs, since here are cards with
  * SUB IDs set to PCI_ANY_ID, so we need to match all and reject
  * known other cards which not work with this driver - see probe function */
-static struct pci_device_id nj_pci_ids[] __devinitdata = {
+static struct pci_device_id nj_pci_ids[] = {
        { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { }
@@ -1147,7 +1147,7 @@ MODULE_DEVICE_TABLE(pci, nj_pci_ids);
 static struct pci_driver nj_driver = {
        .name = "netjet",
        .probe = nj_probe,
-       .remove = __devexit_p(nj_remove),
+       .remove = nj_remove,
        .id_table = nj_pci_ids,
 };
 
index 93f344d74e546ea3063bb1f1b1d23d5cb6071ec8..9815bb4eec9c747a6f285377622ca004b2ea0373 100644 (file)
@@ -282,7 +282,7 @@ sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        return err;
 }
 
-static int __devinit
+static int
 init_card(struct sfax_hw *sf)
 {
        int     ret, cnt = 3;
@@ -321,7 +321,7 @@ init_card(struct sfax_hw *sf)
 }
 
 
-static int __devinit
+static int
 setup_speedfax(struct sfax_hw *sf)
 {
        u_long flags;
@@ -371,7 +371,7 @@ release_card(struct sfax_hw *card) {
        sfax_cnt--;
 }
 
-static int __devinit
+static int
 setup_instance(struct sfax_hw *card)
 {
        const struct firmware *firmware;
@@ -451,7 +451,7 @@ error_fw:
        return err;
 }
 
-static int __devinit
+static int
 sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -ENOMEM;
@@ -480,7 +480,7 @@ sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit
+static void
 sfax_remove_pci(struct pci_dev *pdev)
 {
        struct sfax_hw  *card = pci_get_drvdata(pdev);
@@ -491,7 +491,7 @@ sfax_remove_pci(struct pci_dev *pdev)
                pr_debug("%s: drvdata already removed\n", __func__);
 }
 
-static struct pci_device_id sfaxpci_ids[] __devinitdata = {
+static struct pci_device_id sfaxpci_ids[] = {
        { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
          PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
          0, 0, (unsigned long) "Pyramid Speedfax + PCI"
@@ -507,7 +507,7 @@ MODULE_DEVICE_TABLE(pci, sfaxpci_ids);
 static struct pci_driver sfaxpci_driver = {
        .name = "speedfax+ pci",
        .probe = sfaxpci_probe,
-       .remove = __devexit_p(sfax_remove_pci),
+       .remove = sfax_remove_pci,
        .id_table = sfaxpci_ids,
 };
 
index 335fe6455002c708cfb0be66318b2473f4cdfcc7..de69f6828c767a402fc8a63825a8d2bac8f8a172 100644 (file)
@@ -1355,7 +1355,7 @@ error_setup:
        return err;
 }
 
-static int __devinit
+static int
 w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int             err = -ENOMEM;
@@ -1387,7 +1387,7 @@ w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit
+static void
 w6692_remove_pci(struct pci_dev *pdev)
 {
        struct w6692_hw *card = pci_get_drvdata(pdev);
@@ -1414,7 +1414,7 @@ MODULE_DEVICE_TABLE(pci, w6692_ids);
 static struct pci_driver w6692_driver = {
        .name =  "w6692",
        .probe = w6692_probe,
-       .remove = __devexit_p(w6692_remove_pci),
+       .remove = w6692_remove_pci,
        .id_table = w6692_ids,
 };
 
index 525471e776a76dfe468be16a9d714011ea27546b..1063babe1d3ae1ba38ab43ed5cb1ee7407a87fed 100644 (file)
@@ -786,8 +786,7 @@ void Amd7930_init(struct IsdnCardState *cs)
        }
 }
 
-void __devinit
-setup_Amd7930(struct IsdnCardState *cs)
+void setup_Amd7930(struct IsdnCardState *cs)
 {
        INIT_WORK(&cs->tqueue, Amd7930_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
index 2b74a40ad2a02fb57949086d449ccac6f09f8a78..62f9c43e2377b0cfb9c3f9771d019b588033c898 100644 (file)
@@ -295,7 +295,7 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id asus_ids[] __devinitdata = {
+static struct isapnp_device_id asus_ids[] = {
        { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
          ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
          (unsigned long) "Asus1688 PnP" },
@@ -311,12 +311,11 @@ static struct isapnp_device_id asus_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &asus_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &asus_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit
-setup_asuscom(struct IsdnCard *card)
+int setup_asuscom(struct IsdnCard *card)
 {
        int bytecnt;
        struct IsdnCardState *cs = card->cs;
index 402d489cbbf144b18449f391f09357651c7845a1..7dd74087ad72a131c7245897c286251eb4ba0d17 100644 (file)
@@ -177,8 +177,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-int __devinit
-setup_avm_a1(struct IsdnCard *card)
+int setup_avm_a1(struct IsdnCard *card)
 {
        u_char val;
        struct IsdnCardState *cs = card->cs;
index 39347198d6430068cd85a77d4efcf00e915dd1b8..bc52d54ff5e1e3aab808748d9fb3fb157864f1aa 100644 (file)
@@ -213,7 +213,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return 0;
 }
 
-int __devinit setup_avm_a1_pcmcia(struct IsdnCard *card)
+int setup_avm_a1_pcmcia(struct IsdnCard *card)
 {
        u_char model, vers;
        struct IsdnCardState *cs = card->cs;
index 979492d69daee0e6cd6c18b8fb1a30f14f3d27c9..ee9b9a03cffa04d8bfe4a751cb24ce0f2824ec35 100644 (file)
@@ -718,7 +718,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit avm_setup_rest(struct IsdnCardState *cs)
+static int avm_setup_rest(struct IsdnCardState *cs)
 {
        u_int val, ver;
 
@@ -770,16 +770,16 @@ static int __devinit avm_setup_rest(struct IsdnCardState *cs)
 
 #ifndef __ISAPNP__
 
-static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
+static int avm_pnp_setup(struct IsdnCardState *cs)
 {
        return (1);     /* no-op: success */
 }
 
 #else
 
-static struct pnp_card *pnp_avm_c __devinitdata = NULL;
+static struct pnp_card *pnp_avm_c = NULL;
 
-static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
+static int avm_pnp_setup(struct IsdnCardState *cs)
 {
        struct pnp_dev *pnp_avm_d = NULL;
 
@@ -825,16 +825,16 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
 
 #ifndef CONFIG_PCI
 
-static int __devinit avm_pci_setup(struct IsdnCardState *cs)
+static int avm_pci_setup(struct IsdnCardState *cs)
 {
        return (1);     /* no-op: success */
 }
 
 #else
 
-static struct pci_dev *dev_avm __devinitdata = NULL;
+static struct pci_dev *dev_avm = NULL;
 
-static int __devinit avm_pci_setup(struct IsdnCardState *cs)
+static int avm_pci_setup(struct IsdnCardState *cs)
 {
        if ((dev_avm = hisax_find_pci_device(PCI_VENDOR_ID_AVM,
                                             PCI_DEVICE_ID_AVM_A1, dev_avm))) {
@@ -867,8 +867,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs)
 
 #endif /* CONFIG_PCI */
 
-int __devinit
-setup_avm_pcipnp(struct IsdnCard *card)
+int setup_avm_pcipnp(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index c644557ae614d2e56d4fb35cb2c9dc55d6e8c9c8..4e676bcf85062c1049077fa6d724a6bef5e2a804 100644 (file)
@@ -38,11 +38,11 @@ module_param(isdnprot, int, 0);
 
 /*====================================================================*/
 
-static int avma1cs_config(struct pcmcia_device *link) __devinit;
+static int avma1cs_config(struct pcmcia_device *link);
 static void avma1cs_release(struct pcmcia_device *link);
-static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit;
+static void avma1cs_detach(struct pcmcia_device *p_dev);
 
-static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
+static int avma1cs_probe(struct pcmcia_device *p_dev)
 {
        dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
@@ -54,7 +54,7 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
        return avma1cs_config(p_dev);
 } /* avma1cs_attach */
 
-static void __devexit avma1cs_detach(struct pcmcia_device *link)
+static void avma1cs_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
        avma1cs_release(link);
@@ -72,7 +72,7 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 }
 
 
-static int __devinit avma1cs_config(struct pcmcia_device *link)
+static int avma1cs_config(struct pcmcia_device *link)
 {
        int i = -1;
        char devname[128];
@@ -156,7 +156,7 @@ static struct pcmcia_driver avma1cs_driver = {
        .owner          = THIS_MODULE,
        .name           = "avma1_cs",
        .probe          = avma1cs_probe,
-       .remove         = __devexit_p(avma1cs_detach),
+       .remove         = avma1cs_detach,
        .id_table       = avma1cs_ids,
 };
 
index f6bf9c68892ec892a8116d627a9f6b3d17e89169..c360164bde1bbcb7813fb5afa67ab945221d46a5 100644 (file)
@@ -253,10 +253,8 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit a4t_pci_probe(struct pci_dev *dev_a4t,
-                                  struct IsdnCardState *cs,
-                                  u_int *found,
-                                  u_int *pci_memaddr)
+static int a4t_pci_probe(struct pci_dev *dev_a4t, struct IsdnCardState *cs,
+                        u_int *found, u_int *pci_memaddr)
 {
        u16 sub_sys;
        u16 sub_vendor;
@@ -275,9 +273,8 @@ static int __devinit a4t_pci_probe(struct pci_dev *dev_a4t,
        return (-1);                    /* continue looping */
 }
 
-static int __devinit a4t_cs_init(struct IsdnCard *card,
-                                struct IsdnCardState *cs,
-                                u_int pci_memaddr)
+static int a4t_cs_init(struct IsdnCard *card, struct IsdnCardState *cs,
+                      u_int pci_memaddr)
 {
        I20_REGISTER_FILE *pI20_Regs;
 
@@ -323,10 +320,9 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
        return (1);
 }
 
-static struct pci_dev *dev_a4t __devinitdata = NULL;
+static struct pci_dev *dev_a4t = NULL;
 
-int __devinit
-setup_bkm_a4t(struct IsdnCard *card)
+int setup_bkm_a4t(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index c9c98f071af6cd0b7d776f378d369e80d1c9e812..dd663ea57ec6679301e9f633fa8e1792692d7458 100644 (file)
@@ -255,8 +255,7 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit
-sct_alloc_io(u_int adr, u_int len)
+static int sct_alloc_io(u_int adr, u_int len)
 {
        if (!request_region(adr, len, "scitel")) {
                printk(KERN_WARNING
@@ -267,15 +266,14 @@ sct_alloc_io(u_int adr, u_int len)
        return (0);
 }
 
-static struct pci_dev *dev_a8 __devinitdata = NULL;
-static u16  sub_vendor_id __devinitdata = 0;
-static u16  sub_sys_id __devinitdata = 0;
-static u_char pci_bus __devinitdata = 0;
-static u_char pci_device_fn __devinitdata = 0;
-static u_char pci_irq __devinitdata = 0;
+static struct pci_dev *dev_a8 = NULL;
+static u16  sub_vendor_id = 0;
+static u16  sub_sys_id = 0;
+static u_char pci_bus = 0;
+static u_char pci_device_fn = 0;
+static u_char pci_irq = 0;
 
-int __devinit
-setup_sct_quadro(struct IsdnCard *card)
+int setup_sct_quadro(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index b5edc0eeec06face7b51ad12220db56139cec667..bf04d2a3cf4afe4614765b2b3d08d32ec77571a6 100644 (file)
@@ -338,11 +338,11 @@ static int io[HISAX_MAX_CARDS] = { 0, };
 #define IO0_IO1
 #endif
 #ifdef IO0_IO1
-static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
-static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int io0[HISAX_MAX_CARDS] = { 0, };
+static int io1[HISAX_MAX_CARDS] = { 0, };
 #endif
-static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
-static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int irq[HISAX_MAX_CARDS] = { 0, };
+static int mem[HISAX_MAX_CARDS] = { 0, };
 static char *id = HiSaxID;
 
 MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
@@ -852,7 +852,7 @@ static int init_card(struct IsdnCardState *cs)
        return 3;
 }
 
-static int __devinit hisax_cs_setup_card(struct IsdnCard *card)
+static int hisax_cs_setup_card(struct IsdnCard *card)
 {
        int ret;
 
@@ -1171,12 +1171,8 @@ outf_cs:
        return 0;
 }
 
-/* Used from an exported function but calls __devinit functions.
- * Tell modpost not to warn (__ref)
- */
-static int __ref checkcard(int cardnr, char *id, int *busy_flag,
-                          struct module *lockowner,
-                          hisax_setup_func_t card_setup)
+static int checkcard(int cardnr, char *id, int *busy_flag,
+                    struct module *lockowner, hisax_setup_func_t card_setup)
 {
        int ret;
        struct IsdnCard *card = cards + cardnr;
@@ -1547,9 +1543,7 @@ static void __exit HiSax_exit(void)
        printk(KERN_INFO "HiSax module removed\n");
 }
 
-#ifdef CONFIG_HOTPLUG
-
-int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
 {
        u_char ids[16];
        int ret = -1;
@@ -1568,9 +1562,7 @@ int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *
 error:
        return ret;
 }
-
 EXPORT_SYMBOL(hisax_init_pcmcia);
-#endif
 
 EXPORT_SYMBOL(HiSax_closecard);
 
@@ -1917,7 +1909,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if)
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 
-static struct pci_device_id hisax_pci_tbl[] __devinitdata __used = {
+static struct pci_device_id hisax_pci_tbl[] __used = {
 #ifdef CONFIG_HISAX_FRITZPCI
        {PCI_VDEVICE(AVM,      PCI_DEVICE_ID_AVM_A1)                    },
 #endif
index 62a2945fa7f2c2eaa011ab68522ec083c6030a43..8d0cf6e4dc00590a7d62f455d77bcc192de9dfa1 100644 (file)
@@ -904,7 +904,7 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit setup_diva_common(struct IsdnCardState *cs)
+static int setup_diva_common(struct IsdnCardState *cs)
 {
        int bytecnt;
        u_char val;
@@ -997,7 +997,7 @@ static int __devinit setup_diva_common(struct IsdnCardState *cs)
 
 #ifdef CONFIG_ISA
 
-static int __devinit setup_diva_isa(struct IsdnCard *card)
+static int setup_diva_isa(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        u_char val;
@@ -1033,7 +1033,7 @@ static int __devinit setup_diva_isa(struct IsdnCard *card)
 
 #else  /* if !CONFIG_ISA */
 
-static int __devinit setup_diva_isa(struct IsdnCard *card)
+static int setup_diva_isa(struct IsdnCard *card)
 {
        return (-1);    /* card not found; continue search */
 }
@@ -1041,7 +1041,7 @@ static int __devinit setup_diva_isa(struct IsdnCard *card)
 #endif /* CONFIG_ISA */
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id diva_ids[] __devinitdata = {
+static struct isapnp_device_id diva_ids[] = {
        { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
          ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
          (unsigned long) "Diva picola" },
@@ -1063,10 +1063,10 @@ static struct isapnp_device_id diva_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &diva_ids[0];
+static struct pnp_card *pnp_c = NULL;
 
-static int __devinit setup_diva_isapnp(struct IsdnCard *card)
+static int setup_diva_isapnp(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        struct pnp_dev *pnp_d;
@@ -1141,7 +1141,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card)
 
 #else  /* if !ISAPNP */
 
-static int __devinit setup_diva_isapnp(struct IsdnCard *card)
+static int setup_diva_isapnp(struct IsdnCard *card)
 {
        return (-1);    /* card not found; continue search */
 }
@@ -1149,12 +1149,12 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card)
 #endif /* ISAPNP */
 
 #ifdef CONFIG_PCI
-static struct pci_dev *dev_diva __devinitdata = NULL;
-static struct pci_dev *dev_diva_u __devinitdata = NULL;
-static struct pci_dev *dev_diva201 __devinitdata = NULL;
-static struct pci_dev *dev_diva202 __devinitdata = NULL;
+static struct pci_dev *dev_diva = NULL;
+static struct pci_dev *dev_diva_u = NULL;
+static struct pci_dev *dev_diva201 = NULL;
+static struct pci_dev *dev_diva202 = NULL;
 
-static int __devinit setup_diva_pci(struct IsdnCard *card)
+static int setup_diva_pci(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
 
@@ -1231,15 +1231,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card)
 
 #else  /* if !CONFIG_PCI */
 
-static int __devinit setup_diva_pci(struct IsdnCard *card)
+static int setup_diva_pci(struct IsdnCard *card)
 {
        return (-1);    /* card not found; continue search */
 }
 
 #endif /* CONFIG_PCI */
 
-int __devinit
-setup_diva(struct IsdnCard *card)
+int setup_diva(struct IsdnCard *card)
 {
        int rc, have_card = 0;
        struct IsdnCardState *cs = card->cs;
index 64ba26a4afe649818a23565fc4ae6631eaf9d9b1..1df6f9a56ca26926a9e684869e5471cfebc98e82 100644 (file)
@@ -831,8 +831,7 @@ probe_elsa(struct IsdnCardState *cs)
        return (CARD_portlist[i]);
 }
 
-static int __devinit
-setup_elsa_isa(struct IsdnCard *card)
+static int setup_elsa_isa(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        u_char val;
@@ -902,7 +901,7 @@ setup_elsa_isa(struct IsdnCard *card)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id elsa_ids[] __devinitdata = {
+static struct isapnp_device_id elsa_ids[] = {
        { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
          ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
          (unsigned long) "Elsa QS1000" },
@@ -912,12 +911,11 @@ static struct isapnp_device_id elsa_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &elsa_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif /* __ISAPNP__ */
 
-static int __devinit
-setup_elsa_isapnp(struct IsdnCard *card)
+static int setup_elsa_isapnp(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
 
@@ -994,8 +992,7 @@ setup_elsa_isapnp(struct IsdnCard *card)
        return (1);
 }
 
-static void __devinit
-setup_elsa_pcmcia(struct IsdnCard *card)
+static void setup_elsa_pcmcia(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        u_char val;
@@ -1027,11 +1024,10 @@ setup_elsa_pcmcia(struct IsdnCard *card)
 }
 
 #ifdef CONFIG_PCI
-static struct pci_dev *dev_qs1000 __devinitdata = NULL;
-static struct pci_dev *dev_qs3000 __devinitdata = NULL;
+static struct pci_dev *dev_qs1000 = NULL;
+static struct pci_dev *dev_qs3000 = NULL;
 
-static int __devinit
-setup_elsa_pci(struct IsdnCard *card)
+static int setup_elsa_pci(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
 
@@ -1089,15 +1085,13 @@ setup_elsa_pci(struct IsdnCard *card)
 
 #else
 
-static int __devinit
-setup_elsa_pci(struct IsdnCard *card)
+static int setup_elsa_pci(struct IsdnCard *card)
 {
        return (1);
 }
 #endif /* CONFIG_PCI */
 
-static int __devinit
-setup_elsa_common(struct IsdnCard *card)
+static int setup_elsa_common(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        u_char val;
@@ -1212,8 +1206,7 @@ setup_elsa_common(struct IsdnCard *card)
        return (1);
 }
 
-int __devinit
-setup_elsa(struct IsdnCard *card)
+int setup_elsa(struct IsdnCard *card)
 {
        int rc;
        struct IsdnCardState *cs = card->cs;
index a8c4d3fc9a6d6d8d7000ae8f6a5a6d4b02ca3d34..ebe56918f6fc5e0bbd52d2a4ca6231c41cd83fc1 100644 (file)
@@ -62,9 +62,9 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-static int elsa_cs_config(struct pcmcia_device *link) __devinit;
+static int elsa_cs_config(struct pcmcia_device *link);
 static void elsa_cs_release(struct pcmcia_device *link);
-static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit;
+static void elsa_cs_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
        struct pcmcia_device    *p_dev;
@@ -72,7 +72,7 @@ typedef struct local_info_t {
        int                     cardnr;
 } local_info_t;
 
-static int __devinit elsa_cs_probe(struct pcmcia_device *link)
+static int elsa_cs_probe(struct pcmcia_device *link)
 {
        local_info_t *local;
 
@@ -90,7 +90,7 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
        return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
-static void __devexit elsa_cs_detach(struct pcmcia_device *link)
+static void elsa_cs_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
 
@@ -126,7 +126,7 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
        return -ENODEV;
 }
 
-static int __devinit elsa_cs_config(struct pcmcia_device *link)
+static int elsa_cs_config(struct pcmcia_device *link)
 {
        int i;
        IsdnCard_t icard;
@@ -210,7 +210,7 @@ static struct pcmcia_driver elsa_cs_driver = {
        .owner          = THIS_MODULE,
        .name           = "elsa_cs",
        .probe          = elsa_cs_probe,
-       .remove         = __devexit_p(elsa_cs_detach),
+       .remove         = elsa_cs_detach,
        .id_table       = elsa_ids,
        .suspend        = elsa_suspend,
        .resume         = elsa_resume,
index b1e38b54ebac9dbc7d8dc60742f6b1df0ebde02b..e8d431a8302dad6048dd421eb7095e692c28c250 100644 (file)
@@ -300,8 +300,7 @@ enpci_interrupt(int intno, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit en_pci_probe(struct pci_dev *dev_netjet,
-                                 struct IsdnCardState *cs)
+static int en_pci_probe(struct pci_dev *dev_netjet, struct IsdnCardState *cs)
 {
        if (pci_enable_device(dev_netjet))
                return (0);
@@ -326,8 +325,7 @@ static int __devinit en_pci_probe(struct pci_dev *dev_netjet,
        return (1);
 }
 
-static void __devinit en_cs_init(struct IsdnCard *card,
-                                struct IsdnCardState *cs)
+static void en_cs_init(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
        cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
@@ -350,8 +348,7 @@ static void __devinit en_cs_init(struct IsdnCard *card,
        outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
 }
 
-static int __devinit en_cs_init_rest(struct IsdnCard *card,
-                                    struct IsdnCardState *cs)
+static int en_cs_init_rest(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        const int bytecnt = 256;
 
@@ -384,11 +381,10 @@ static int __devinit en_cs_init_rest(struct IsdnCard *card,
        return (1);
 }
 
-static struct pci_dev *dev_netjet __devinitdata = NULL;
+static struct pci_dev *dev_netjet = NULL;
 
 /* called by config.c */
-int __devinit
-setup_enternow_pci(struct IsdnCard *card)
+int setup_enternow_pci(struct IsdnCard *card)
 {
        int ret;
        struct IsdnCardState *cs = card->cs;
index 4fef775625549824e60e61eab9a0c478cccb40fc..35c6df6534ecde8507c417a61a1c93f41fa4a293 100644 (file)
@@ -483,8 +483,7 @@ error:
        return 1;
 }
 
-static int __devinit
-setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+static int setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
        // we got an irq parameter, assume it is an ISA card
@@ -532,10 +531,9 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
 }
 
 #ifdef CONFIG_PCI
-static struct pci_dev *dev_tel __devinitdata = NULL;
+static struct pci_dev *dev_tel = NULL;
 
-static int __devinit
-setup_gazelpci(struct IsdnCardState *cs)
+static int setup_gazelpci(struct IsdnCardState *cs)
 {
        u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
        u_char pci_irq = 0, found;
@@ -622,8 +620,7 @@ setup_gazelpci(struct IsdnCardState *cs)
 }
 #endif /* CONFIG_PCI */
 
-int __devinit
-setup_gazel(struct IsdnCard *card)
+int setup_gazel(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index dea04de8e7ca292005e4a1e1b13774977ffd8c36..c49c294fc81ef2176039421f6f0c6886d5e7167a 100644 (file)
@@ -1497,7 +1497,7 @@ enable_pci_ports(hfc4s8s_hw *hw)
 /* initialise the HFC-4s/8s hardware */
 /* return 0 on success.              */
 /*************************************/
-static int __devinit
+static int
 setup_instance(hfc4s8s_hw *hw)
 {
        int err = -EIO;
@@ -1585,7 +1585,7 @@ out:
 /*****************************************/
 /* PCI hotplug interface: probe new card */
 /*****************************************/
-static int __devinit
+static int
 hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -ENOMEM;
@@ -1640,7 +1640,7 @@ out:
 /**************************************/
 /* PCI hotplug interface: remove card */
 /**************************************/
-static void __devexit
+static void
 hfc4s8s_remove(struct pci_dev *pdev)
 {
        hfc4s8s_hw *hw = pci_get_drvdata(pdev);
@@ -1662,7 +1662,7 @@ hfc4s8s_remove(struct pci_dev *pdev)
 static struct pci_driver hfc4s8s_driver = {
        .name   = "hfc4s8s_l1",
        .probe  = hfc4s8s_probe,
-       .remove = __devexit_p(hfc4s8s_remove),
+       .remove = hfc4s8s_remove,
        .id_table       = hfc4s8s_ids,
 };
 
@@ -1688,14 +1688,6 @@ hfc4s8s_module_init(void)
        }
        printk(KERN_INFO "HFC-4S/8S: found %d cards\n", card_cnt);
 
-#if !defined(CONFIG_HOTPLUG)
-       if (err == 0) {
-               err = -ENODEV;
-               pci_unregister_driver(&hfc4s8s_driver);
-               goto out;
-       }
-#endif
-
        return 0;
 out:
        return (err);
index f60d4be589414149f1ca7e6f9157d37012ef2d24..3ccd724ff8c2812eb0af3fae58e6742d16970cd5 100644 (file)
@@ -1632,9 +1632,9 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 
 /* this variable is used as card index when more than one cards are present */
-static struct pci_dev *dev_hfcpci __devinitdata = NULL;
+static struct pci_dev *dev_hfcpci = NULL;
 
-int __devinit
+int
 setup_hfcpci(struct IsdnCard *card)
 {
        u_long flags;
index 4ec279ce052f0fc64f2d822b46a463fb562717fa..90f34ae2b80fb340401abbe0c9941a3a95cfc736 100644 (file)
@@ -1381,19 +1381,18 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id hfc_ids[] __devinitdata = {
+static struct isapnp_device_id hfc_ids[] = {
        { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
          ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
          (unsigned long) "Teles 16.3c2" },
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &hfc_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit
-setup_hfcsx(struct IsdnCard *card)
+int setup_hfcsx(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index a5f048bd2bb3fcc04910e8cc27a6a6f58d561f6e..394da646e97b7316e618f054519095f83c338caa 100644 (file)
@@ -136,7 +136,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id hfc_ids[] __devinitdata = {
+static struct isapnp_device_id hfc_ids[] = {
        { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
          ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
          (unsigned long) "Acer P10" },
@@ -161,12 +161,11 @@ static struct isapnp_device_id hfc_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &hfc_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit
-setup_hfcs(struct IsdnCard *card)
+int setup_hfcs(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index e4f47fe3f7fd00bcfb5f2be03a32dad793f640f5..5e8a5d967162e919f5db3856e3f897e71718c593 100644 (file)
@@ -70,7 +70,7 @@ static struct pci_device_id fcpci_ids[] = {
 MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
 #ifdef CONFIG_PNP
-static struct pnp_device_id fcpnp_ids[] __devinitdata = {
+static struct pnp_device_id fcpnp_ids[] = {
        {
                .id             = "AVM0900",
                .driver_data    = (unsigned long) "Fritz!Card PnP",
@@ -712,7 +712,7 @@ static inline void fcpci_init(struct fritz_adapter *adapter)
 
 // ----------------------------------------------------------------------
 
-static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
+static int fcpcipnp_setup(struct fritz_adapter *adapter)
 {
        u32 val = 0;
        int retval;
@@ -825,7 +825,7 @@ err:
        return retval;
 }
 
-static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
+static void fcpcipnp_release(struct fritz_adapter *adapter)
 {
        DBG(1, "");
 
@@ -836,8 +836,7 @@ static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
 
 // ----------------------------------------------------------------------
 
-static struct fritz_adapter * __devinit
-new_adapter(void)
+static struct fritz_adapter *new_adapter(void)
 {
        struct fritz_adapter *adapter;
        struct hisax_b_if *b_if[2];
@@ -876,8 +875,7 @@ static void delete_adapter(struct fritz_adapter *adapter)
        kfree(adapter);
 }
 
-static int __devinit fcpci_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int fcpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct fritz_adapter *adapter;
        int retval;
@@ -917,7 +915,7 @@ err:
 }
 
 #ifdef CONFIG_PNP
-static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
+static int fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 {
        struct fritz_adapter *adapter;
        int retval;
@@ -959,7 +957,7 @@ err:
        return retval;
 }
 
-static void __devexit fcpnp_remove(struct pnp_dev *pdev)
+static void fcpnp_remove(struct pnp_dev *pdev)
 {
        struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
 
@@ -973,12 +971,12 @@ static void __devexit fcpnp_remove(struct pnp_dev *pdev)
 static struct pnp_driver fcpnp_driver = {
        .name           = "fcpnp",
        .probe          = fcpnp_probe,
-       .remove         = __devexit_p(fcpnp_remove),
+       .remove         = fcpnp_remove,
        .id_table       = fcpnp_ids,
 };
 #endif
 
-static void __devexit fcpci_remove(struct pci_dev *pdev)
+static void fcpci_remove(struct pci_dev *pdev)
 {
        struct fritz_adapter *adapter = pci_get_drvdata(pdev);
 
@@ -990,7 +988,7 @@ static void __devexit fcpci_remove(struct pci_dev *pdev)
 static struct pci_driver fcpci_driver = {
        .name           = "fcpci",
        .probe          = fcpci_probe,
-       .remove         = __devexit_p(fcpci_remove),
+       .remove         = fcpci_remove,
        .id_table       = fcpci_ids,
 };
 
index 7be762b17c70c5163caaee37b19dcbc718644300..db5321f6379b0a454ffba83241abf540070138f9 100644 (file)
@@ -673,8 +673,7 @@ clear_pending_icc_ints(struct IsdnCardState *cs)
        cs->writeisac(cs, ICC_MASK, 0xFF);
 }
 
-void __devinit
-setup_icc(struct IsdnCardState *cs)
+void setup_icc(struct IsdnCardState *cs)
 {
        INIT_WORK(&cs->tqueue, icc_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
index bcd70a3873074974909630906afcbac98ca6ad4f..a365ccc1c99c886f94df163ab3b60280e20b9b49 100644 (file)
 #define DBUSY_TIMER_VALUE 80
 #define ARCOFI_USE 1
 
-static char *ISACVer[] __devinitdata =
+static char *ISACVer[] =
 {"2086/2186 V1.1", "2085 B1", "2085 B2",
  "2085 V2.3"};
 
-void __devinit ISACVersion(struct IsdnCardState *cs, char *s)
+void ISACVersion(struct IsdnCardState *cs, char *s)
 {
        int val;
 
@@ -669,8 +669,7 @@ void clear_pending_isac_ints(struct IsdnCardState *cs)
        cs->writeisac(cs, ISAC_MASK, 0xFF);
 }
 
-void __devinit
-setup_isac(struct IsdnCardState *cs)
+void setup_isac(struct IsdnCardState *cs)
 {
        INIT_WORK(&cs->tqueue, isac_bh);
        cs->dbusytimer.function = (void *) dbusy_timer_handler;
index c1530fe248c265a927f29009db48c3014134880a..1399ddd4f6cb3b62bdae723b63e0ffe86461a615 100644 (file)
@@ -194,11 +194,10 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 }
 
 #ifdef __ISAPNP__
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit
-setup_isurf(struct IsdnCard *card)
+int setup_isurf(struct IsdnCard *card)
 {
        int ver;
        struct IsdnCardState *cs = card->cs;
index 5f299f82b801a3554f55f659b1e455014d3ccc70..7ae39f5e865defc018a81aa555787bba5b78f07b 100644 (file)
@@ -209,7 +209,7 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id itk_ids[] __devinitdata = {
+static struct isapnp_device_id itk_ids[] = {
        { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
          ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
          (unsigned long) "ITK micro 2" },
@@ -219,13 +219,12 @@ static struct isapnp_device_id itk_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &itk_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &itk_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif
 
 
-int __devinit
-setup_ix1micro(struct IsdnCard *card)
+int setup_ix1micro(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index 08a6b7fb17f7769e406eb8927d5d0eba9df501e7..93398676f78fd2529b6fd2fd9670c7a96a2268b9 100644 (file)
@@ -187,8 +187,7 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-int __devinit
-setup_mic(struct IsdnCard *card)
+int setup_mic(struct IsdnCard *card)
 {
        int bytecnt;
        struct IsdnCardState *cs = card->cs;
index 6569e0315cca2c3a2a0a016ad7dc76cf245f6a99..e4c33cfe3ef489f7a26eefcebdba625e039cb9d5 100644 (file)
@@ -223,10 +223,10 @@ static int niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit setup_niccy(struct IsdnCard *card)
+int setup_niccy(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
@@ -298,7 +298,7 @@ int __devinit setup_niccy(struct IsdnCard *card)
                }
        } else {
 #ifdef CONFIG_PCI
-               static struct pci_dev *niccy_dev __devinitdata;
+               static struct pci_dev *niccy_dev;
 
                u_int pci_ioaddr;
                cs->subtyp = 0;
index f36ff69c07e1c870c7881c9f7e817d841ff5e0f1..32b4bbd18eb9237208eb13f4c95e567bd237b750 100644 (file)
@@ -148,8 +148,7 @@ NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit njs_pci_probe(struct pci_dev *dev_netjet,
-                                  struct IsdnCardState *cs)
+static int njs_pci_probe(struct pci_dev *dev_netjet, struct IsdnCardState *cs)
 {
        u32 cfg;
 
@@ -187,8 +186,7 @@ static int __devinit njs_pci_probe(struct pci_dev *dev_netjet,
        return (1);
 }
 
-static int __devinit njs_cs_init(struct IsdnCard *card,
-                                struct IsdnCardState *cs)
+static int njs_cs_init(struct IsdnCard *card, struct IsdnCardState *cs)
 {
 
        cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
@@ -225,8 +223,7 @@ static int __devinit njs_cs_init(struct IsdnCard *card,
        return 1;                       /* end loop */
 }
 
-static int __devinit njs_cs_init_rest(struct IsdnCard *card,
-                                     struct IsdnCardState *cs)
+static int njs_cs_init_rest(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        const int bytecnt = 256;
 
@@ -256,10 +253,9 @@ static int __devinit njs_cs_init_rest(struct IsdnCard *card,
        return (1);
 }
 
-static struct pci_dev *dev_netjet __devinitdata = NULL;
+static struct pci_dev *dev_netjet = NULL;
 
-int __devinit
-setup_netjet_s(struct IsdnCard *card)
+int setup_netjet_s(struct IsdnCard *card)
 {
        int ret;
        struct IsdnCardState *cs = card->cs;
index 333484aef425640e7d7cdb13ff7de983b3cb5bfb..4e8adbede361d5ddc147cbc811eda65f82a807f6 100644 (file)
@@ -128,8 +128,7 @@ NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit nju_pci_probe(struct pci_dev *dev_netjet,
-                                  struct IsdnCardState *cs)
+static int nju_pci_probe(struct pci_dev *dev_netjet, struct IsdnCardState *cs)
 {
        if (pci_enable_device(dev_netjet))
                return (0);
@@ -148,8 +147,7 @@ static int __devinit nju_pci_probe(struct pci_dev *dev_netjet,
        return (1);
 }
 
-static int __devinit nju_cs_init(struct IsdnCard *card,
-                                struct IsdnCardState *cs)
+static int nju_cs_init(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
        cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
@@ -187,8 +185,7 @@ static int __devinit nju_cs_init(struct IsdnCard *card,
        return 1;                       /* end loop */
 }
 
-static int __devinit nju_cs_init_rest(struct IsdnCard *card,
-                                     struct IsdnCardState *cs)
+static int nju_cs_init_rest(struct IsdnCard *card, struct IsdnCardState *cs)
 {
        const int bytecnt = 256;
 
@@ -219,10 +216,9 @@ static int __devinit nju_cs_init_rest(struct IsdnCard *card,
        return (1);
 }
 
-static struct pci_dev *dev_netjet __devinitdata = NULL;
+static struct pci_dev *dev_netjet = NULL;
 
-int __devinit
-setup_netjet_u(struct IsdnCard *card)
+int setup_netjet_u(struct IsdnCard *card)
 {
        int ret;
        struct IsdnCardState *cs = card->cs;
index 383c4e7ce50b5012c3bd501d4207ea54be7f97d6..4e7d0aa227ad887e23a1550f1d44f7cdb20f64a7 100644 (file)
@@ -210,8 +210,7 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-int __devinit
-setup_s0box(struct IsdnCard *card)
+int setup_s0box(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index 75dcae6d36e0b55d016117982d76b3f8ade315b9..6b2d0eccdd562dcee54e5e0917474a8bf56e4eee 100644 (file)
@@ -240,8 +240,7 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 
-int __devinit
-setup_saphir(struct IsdnCard *card)
+int setup_saphir(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index 1ee531b6be9978003b2bcbcf695bb425877b83af..f16a47bcef485cc41dcf688e2d87a48ef1b7aa87 100644 (file)
@@ -517,7 +517,7 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id sedl_ids[] __devinitdata = {
+static struct isapnp_device_id sedl_ids[] = {
        { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
          ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
          (unsigned long) "Speed win" },
@@ -527,11 +527,10 @@ static struct isapnp_device_id sedl_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &sedl_ids[0];
+static struct pnp_card *pnp_c = NULL;
 
-static int __devinit
-setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
+static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
 {
        struct IsdnCardState *cs = card->cs;
        struct pnp_dev *pnp_d;
@@ -591,18 +590,16 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
 }
 #else
 
-static int __devinit
-setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
+static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
 {
        return -1;
 }
 #endif /* __ISAPNP__ */
 
 #ifdef CONFIG_PCI
-static struct pci_dev *dev_sedl __devinitdata = NULL;
+static struct pci_dev *dev_sedl = NULL;
 
-static int __devinit
-setup_sedlbauer_pci(struct IsdnCard *card)
+static int setup_sedlbauer_pci(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        u16 sub_vendor_id, sub_id;
@@ -667,16 +664,14 @@ setup_sedlbauer_pci(struct IsdnCard *card)
 
 #else
 
-static int __devinit
-setup_sedlbauer_pci(struct IsdnCard *card)
+static int setup_sedlbauer_pci(struct IsdnCard *card)
 {
        return (1);
 }
 
 #endif /* CONFIG_PCI */
 
-int __devinit
-setup_sedlbauer(struct IsdnCard *card)
+int setup_sedlbauer(struct IsdnCard *card)
 {
        int bytecnt = 8, ver, val, rc;
        struct IsdnCardState *cs = card->cs;
index f0dfc0c976eb780cfd131478c964c00ad9e4c71f..90f81291641b714f45236b698b2caf54b5d1624a 100644 (file)
@@ -62,10 +62,10 @@ MODULE_LICENSE("Dual MPL/GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-static int sedlbauer_config(struct pcmcia_device *link) __devinit;
+static int sedlbauer_config(struct pcmcia_device *link);
 static void sedlbauer_release(struct pcmcia_device *link);
 
-static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
+static void sedlbauer_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
        struct pcmcia_device    *p_dev;
@@ -73,7 +73,7 @@ typedef struct local_info_t {
        int                     cardnr;
 } local_info_t;
 
-static int __devinit sedlbauer_probe(struct pcmcia_device *link)
+static int sedlbauer_probe(struct pcmcia_device *link)
 {
        local_info_t *local;
 
@@ -90,7 +90,7 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
        return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
-static void __devexit sedlbauer_detach(struct pcmcia_device *link)
+static void sedlbauer_detach(struct pcmcia_device *link)
 {
        dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
 
@@ -110,7 +110,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
        return pcmcia_request_io(p_dev);
 }
 
-static int __devinit sedlbauer_config(struct pcmcia_device *link)
+static int sedlbauer_config(struct pcmcia_device *link)
 {
        int ret;
        IsdnCard_t  icard;
@@ -201,7 +201,7 @@ static struct pcmcia_driver sedlbauer_driver = {
        .owner          = THIS_MODULE,
        .name           = "sedlbauer_cs",
        .probe          = sedlbauer_probe,
-       .remove         = __devexit_p(sedlbauer_detach),
+       .remove         = sedlbauer_detach,
        .id_table       = sedlbauer_ids,
        .suspend        = sedlbauer_suspend,
        .resume         = sedlbauer_resume,
index 1267298ef551b0a707cba1f11e92017ad9094743..18cee6360d0a330672fc58f3caf811e3d9b46b64 100644 (file)
@@ -183,8 +183,7 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static int __devinit
-get_io_range(struct IsdnCardState *cs)
+static int get_io_range(struct IsdnCardState *cs)
 {
        int i, j, adr;
 
@@ -208,8 +207,7 @@ get_io_range(struct IsdnCardState *cs)
        }
 }
 
-int __devinit
-setup_sportster(struct IsdnCard *card)
+int setup_sportster(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index fa329e27cc5b0c07e78f80e95ae83090de7e090c..bf647545c70c45b9bc5b0e381af27f67f17a3662 100644 (file)
@@ -259,8 +259,7 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-int __devinit
-setup_TeleInt(struct IsdnCard *card)
+int setup_TeleInt(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index 49b4a26f91e018be2490c5abf0afee7e65d4bb74..ce9eabdd2f6e26f0b358487180c2cad92a493bbc 100644 (file)
@@ -263,8 +263,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-int __devinit
-setup_teles0(struct IsdnCard *card)
+int setup_teles0(struct IsdnCard *card)
 {
        u_char val;
        struct IsdnCardState *cs = card->cs;
index 220b919fafc3b8cb0f1e15be3f79ac19381fcec1..38fb2c1a3f0f48cdbbf3511a467d09e16b042e33 100644 (file)
@@ -253,7 +253,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 #ifdef __ISAPNP__
 
-static struct isapnp_device_id teles_ids[] __devinitdata = {
+static struct isapnp_device_id teles_ids[] = {
        { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
          ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
          (unsigned long) "Teles 16.3 PnP" },
@@ -266,12 +266,11 @@ static struct isapnp_device_id teles_ids[] __devinitdata = {
        { 0, }
 };
 
-static struct isapnp_device_id *ipid __devinitdata = &teles_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
+static struct isapnp_device_id *ipid = &teles_ids[0];
+static struct pnp_card *pnp_c = NULL;
 #endif
 
-int __devinit
-setup_teles3(struct IsdnCard *card)
+int setup_teles3(struct IsdnCard *card)
 {
        u_char val;
        struct IsdnCardState *cs = card->cs;
index 4deac451807cb5891d12bdd9f2bd1efddffc113a..f2476ffb04fda65d87d146b8729c1ac9080db153 100644 (file)
@@ -43,9 +43,9 @@ MODULE_LICENSE("GPL");
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-static int teles_cs_config(struct pcmcia_device *link) __devinit;
+static int teles_cs_config(struct pcmcia_device *link);
 static void teles_cs_release(struct pcmcia_device *link);
-static void teles_detach(struct pcmcia_device *p_dev) __devexit;
+static void teles_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
        struct pcmcia_device    *p_dev;
@@ -53,7 +53,7 @@ typedef struct local_info_t {
        int                     cardnr;
 } local_info_t;
 
-static int __devinit teles_probe(struct pcmcia_device *link)
+static int teles_probe(struct pcmcia_device *link)
 {
        local_info_t *local;
 
@@ -72,7 +72,7 @@ static int __devinit teles_probe(struct pcmcia_device *link)
        return teles_cs_config(link);
 } /* teles_attach */
 
-static void __devexit teles_detach(struct pcmcia_device *link)
+static void teles_detach(struct pcmcia_device *link)
 {
        local_info_t *info = link->priv;
 
@@ -108,7 +108,7 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
        return -ENODEV;
 }
 
-static int __devinit teles_cs_config(struct pcmcia_device *link)
+static int teles_cs_config(struct pcmcia_device *link)
 {
        int i;
        IsdnCard_t icard;
@@ -192,7 +192,7 @@ static struct pcmcia_driver teles_cs_driver = {
        .owner          = THIS_MODULE,
        .name           = "teles_cs",
        .probe          = teles_probe,
-       .remove         = __devexit_p(teles_detach),
+       .remove         = teles_detach,
        .id_table       = teles_ids,
        .suspend        = teles_suspend,
        .resume         = teles_resume,
index 9c002c9dc7715c653957c9017f5c2113b66194ed..f6ab63aa699590278531ba9ae6ceabe75ba90813 100644 (file)
@@ -283,10 +283,9 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static struct pci_dev *dev_tel __devinitdata = NULL;
+static struct pci_dev *dev_tel = NULL;
 
-int __devinit
-setup_telespci(struct IsdnCard *card)
+int setup_telespci(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index 0f0d094af85b2e3427374446110648245cc53e0e..d8cac69358180ee455c92d99a0c58b8203372203 100644 (file)
@@ -991,10 +991,9 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 static int id_idx;
 
-static struct pci_dev *dev_w6692 __devinitdata = NULL;
+static struct pci_dev *dev_w6692 = NULL;
 
-int __devinit
-setup_w6692(struct IsdnCard *card)
+int setup_w6692(struct IsdnCard *card)
 {
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
index b61bbb4bb52b96e9590ade19442c2764d07641dd..0db2f7506250dccae8987911f8e522a596b6f2f9 100644 (file)
@@ -56,8 +56,8 @@ static hysdn_card *card_last = NULL;  /* pointer to first card */
 /* is assumed and the module will not be kept in memory.                    */
 /****************************************************************************/
 
-static int __devinit hysdn_pci_init_one(struct pci_dev *akt_pcidev,
-                                       const struct pci_device_id *ent)
+static int hysdn_pci_init_one(struct pci_dev *akt_pcidev,
+                             const struct pci_device_id *ent)
 {
        hysdn_card *card;
        int rc;
@@ -109,7 +109,7 @@ err_out:
        return rc;
 }
 
-static void __devexit hysdn_pci_remove_one(struct pci_dev *akt_pcidev)
+static void hysdn_pci_remove_one(struct pci_dev *akt_pcidev)
 {
        hysdn_card *card = pci_get_drvdata(akt_pcidev);
 
@@ -147,7 +147,7 @@ static struct pci_driver hysdn_pci_driver = {
        .name           = "hysdn",
        .id_table       = hysdn_pci_tbl,
        .probe          = hysdn_pci_init_one,
-       .remove         = __devexit_p(hysdn_pci_remove_one),
+       .remove         = hysdn_pci_remove_one,
 };
 
 static int hysdn_have_procfs;
index c401634c00eccb3802aaae1d12e955ac92d8d91e..3e245712bba7e17a9f47e2060fc0dc4fdcd4b7ae 100644 (file)
@@ -140,7 +140,6 @@ static struct device_attribute mISDN_dev_attrs[] = {
        {}
 };
 
-#ifdef CONFIG_HOTPLUG
 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct mISDNdevice *mdev = dev_to_mISDN(dev);
@@ -153,7 +152,6 @@ static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
 
        return 0;
 }
-#endif
 
 static void mISDN_class_release(struct class *cls)
 {
@@ -163,9 +161,7 @@ static void mISDN_class_release(struct class *cls)
 static struct class mISDN_class = {
        .name = "mISDN",
        .owner = THIS_MODULE,
-#ifdef CONFIG_HOTPLUG
        .dev_uevent = mISDN_uevent,
-#endif
        .dev_attrs = mISDN_dev_attrs,
        .dev_release = mISDN_dev_release,
        .class_release = mISDN_class_release,
index 5f21f629b7aebeac0163083a2a83a50f4e53c1a8..deda591f70b9fab4be605442fb1f6afe9bd9f7be 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/mISDNif.h>
 #include <linux/kthread.h>
+#include <linux/sched.h>
 #include "core.h"
 
 static u_int   *debug;
@@ -202,6 +203,9 @@ static int
 mISDNStackd(void *data)
 {
        struct mISDNstack *st = data;
+#ifdef MISDN_MSG_STATS
+       cputime_t utime, stime;
+#endif
        int err = 0;
 
        sigfillset(&current->blocked);
@@ -303,9 +307,10 @@ mISDNStackd(void *data)
               "msg %d sleep %d stopped\n",
               dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt,
               st->stopped_cnt);
+       task_cputime(st->thread, &utime, &stime);
        printk(KERN_DEBUG
               "mISDNStackd daemon for %s utime(%ld) stime(%ld)\n",
-              dev_name(&st->dev->dev), st->thread->utime, st->thread->stime);
+              dev_name(&st->dev->dev), utime, stime);
        printk(KERN_DEBUG
               "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n",
               dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw);
index 1885a26776b1b38256756d202639dc5a25a75f5a..a0d931bcb37c5cda58766ff365a0a42dd112f45d 100644 (file)
@@ -127,8 +127,9 @@ static int create_gpio_led(const struct gpio_led *template,
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = devm_gpio_request_one(parent, template->gpio,
-                       GPIOF_DIR_OUT | (led_dat->active_low ^ state),
-                       template->name);
+                                   (led_dat->active_low ^ state) ?
+                                   GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+                                   template->name);
        if (ret < 0)
                return ret;
 
index ef87310b7662415b4fca8f18c212d85090790ee1..ac5c879398604a48da1c193c6b9936a072736c7d 100644 (file)
@@ -679,7 +679,7 @@ void macio_release_resources(struct macio_dev *dev)
 
 #ifdef CONFIG_PCI
 
-static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct device_node* np;
        struct macio_chip* chip;
@@ -739,7 +739,7 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi
        return 0;
 }
 
-static void __devexit macio_pci_remove(struct pci_dev* pdev)
+static void macio_pci_remove(struct pci_dev* pdev)
 {
        panic("removing of macio-asic not supported !\n");
 }
@@ -748,7 +748,7 @@ static void __devexit macio_pci_remove(struct pci_dev* pdev)
  * MacIO is matched against any Apple ID, it's probe() function
  * will then decide wether it applies or not
  */
-static const struct pci_device_id __devinitconst pci_ids[] = { {
+static const struct pci_device_id pci_ids[] = { {
        .vendor         = PCI_VENDOR_ID_APPLE,
        .device         = PCI_ANY_ID,
        .subvendor      = PCI_ANY_ID,
index 3f8d032f180fd5c0ec76901742c00cb58212acb1..d98e566a8f5e843abff7ccbafa25be1a957e3cc6 100644 (file)
@@ -556,7 +556,8 @@ static int media_bay_task(void *x)
        return 0;
 }
 
-static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_device_id *match)
+static int media_bay_attach(struct macio_dev *mdev,
+                           const struct of_device_id *match)
 {
        struct media_bay_info* bay;
        u32 __iomem *regbase;
index 6dc26b61219b423da10ec463df990532440c9ecc..cad0e19b47a285eb4b96ae9d9869f640f26e064e 100644 (file)
@@ -253,7 +253,7 @@ static void rackmeter_do_timer(struct work_struct *work)
                                 msecs_to_jiffies(CPU_SAMPLING_RATE));
 }
 
-static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
+static void rackmeter_init_cpu_sniffer(struct rackmeter *rm)
 {
        unsigned int cpu;
 
@@ -287,7 +287,7 @@ static void rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
        cancel_delayed_work_sync(&rm->cpu[1].sniffer);
 }
 
-static int __devinit rackmeter_setup(struct rackmeter *rm)
+static int rackmeter_setup(struct rackmeter *rm)
 {
        pr_debug("rackmeter: setting up i2s..\n");
        rackmeter_setup_i2s(rm);
@@ -362,8 +362,8 @@ static irqreturn_t rackmeter_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static int __devinit rackmeter_probe(struct macio_dev* mdev,
-                                    const struct of_device_id *match)
+static int rackmeter_probe(struct macio_dev* mdev,
+                          const struct of_device_id *match)
 {
        struct device_node *i2s = NULL, *np = NULL;
        struct rackmeter *rm = NULL;
@@ -521,7 +521,7 @@ static int __devinit rackmeter_probe(struct macio_dev* mdev,
        return rc;
 }
 
-static int __devexit rackmeter_remove(struct macio_dev* mdev)
+static int rackmeter_remove(struct macio_dev* mdev)
 {
        struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
 
@@ -588,7 +588,7 @@ static struct macio_driver rackmeter_driver = {
                .of_match_table = rackmeter_match,
        },
        .probe = rackmeter_probe,
-       .remove = __devexit_p(rackmeter_remove),
+       .remove = rackmeter_remove,
        .shutdown = rackmeter_shutdown,
 };
 
index ac3f243b9c5a15b2528814808865ebf38ea1e472..7c28b71246c994d71bdf1c379b29e4e669ec466b 100644 (file)
@@ -177,9 +177,9 @@ static const struct wf_sensor_ops wf_ad7417_adc_ops = {
        .owner          = THIS_MODULE,
 };
 
-static void __devinit wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
-                                          int index, const char *name,
-                                          const struct wf_sensor_ops *ops)
+static void wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
+                                int index, const char *name,
+                                const struct wf_sensor_ops *ops)
 {
        pv->sensors[index].name = kasprintf(GFP_KERNEL, "%s-%d", name, pv->cpu);
        pv->sensors[index].priv = pv;
@@ -188,7 +188,7 @@ static void __devinit wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
                kref_get(&pv->ref);
 }
 
-static void __devinit wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
+static void wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
 {
        int rc;
        u8 buf[2];
@@ -230,8 +230,8 @@ static void __devinit wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
        pv->config = config;
 }
 
-static int __devinit wf_ad7417_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int wf_ad7417_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct wf_ad7417_priv *pv;
        const struct mpu_data *mpu;
@@ -290,7 +290,7 @@ static int __devinit wf_ad7417_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit wf_ad7417_remove(struct i2c_client *client)
+static int wf_ad7417_remove(struct i2c_client *client)
 {
        struct wf_ad7417_priv *pv = dev_get_drvdata(&client->dev);
        int i;
@@ -322,7 +322,7 @@ static struct i2c_driver wf_ad7417_driver = {
        .id_table       = wf_ad7417_id,
 };
 
-static int __devinit wf_ad7417_init(void)
+static int wf_ad7417_init(void)
 {
        /* This is only supported on these machines */
        if (!of_machine_is_compatible("PowerMac7,2") &&
@@ -333,7 +333,7 @@ static int __devinit wf_ad7417_init(void)
        return i2c_add_driver(&wf_ad7417_driver);
 }
 
-static void __devexit wf_ad7417_exit(void)
+static void wf_ad7417_exit(void)
 {
        i2c_del_driver(&wf_ad7417_driver);
 }
index fd6ed15a979dfae62db35fb2fd7ea3ff4f1c650b..0226b796a21c9aa3f1ca2b28b02ca3b66fd6316b 100644 (file)
@@ -282,7 +282,7 @@ static const struct wf_control_ops wf_fcu_fan_pwm_ops = {
        .owner          = THIS_MODULE,
 };
 
-static void __devinit wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
+static void wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
 {
        const struct mpu_data *mpu = wf_get_mpu(0);
        u16 pump_min = 0, pump_max = 0xffff;
@@ -317,7 +317,7 @@ static void __devinit wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
            fan->ctrl.name, pump_min, pump_max);
 }
 
-static void __devinit wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
+static void wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
 {
        struct wf_fcu_priv *pv = fan->fcu_priv;
        const struct mpu_data *mpu0 = wf_get_mpu(0);
@@ -359,9 +359,8 @@ static void __devinit wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
            fan->ctrl.name, fan->min, fan->max);
 }
 
-static void __devinit wf_fcu_add_fan(struct wf_fcu_priv *pv,
-                                    const char *name,
-                                    int type, int id)
+static void wf_fcu_add_fan(struct wf_fcu_priv *pv, const char *name,
+                          int type, int id)
 {
        struct wf_fcu_fan *fan;
 
@@ -399,7 +398,7 @@ static void __devinit wf_fcu_add_fan(struct wf_fcu_priv *pv,
        kref_get(&pv->ref);
 }
 
-static void __devinit wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
+static void wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
 {
        /* Translation of device-tree location properties to
         * windfarm fan names
@@ -481,7 +480,7 @@ static void __devinit wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
        }
 }
 
-static void __devinit wf_fcu_default_fans(struct wf_fcu_priv *pv)
+static void wf_fcu_default_fans(struct wf_fcu_priv *pv)
 {
        /* We only support the default fans for PowerMac7,2 */
        if (!of_machine_is_compatible("PowerMac7,2"))
@@ -496,7 +495,7 @@ static void __devinit wf_fcu_default_fans(struct wf_fcu_priv *pv)
        wf_fcu_add_fan(pv, "cpu-rear-fan-1",    FCU_FAN_RPM, 6);
 }
 
-static int __devinit wf_fcu_init_chip(struct wf_fcu_priv *pv)
+static int wf_fcu_init_chip(struct wf_fcu_priv *pv)
 {
        unsigned char buf = 0xff;
        int rc;
@@ -518,8 +517,8 @@ static int __devinit wf_fcu_init_chip(struct wf_fcu_priv *pv)
        return 0;
 }
 
-static int __devinit wf_fcu_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int wf_fcu_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct wf_fcu_priv *pv;
 
@@ -564,7 +563,7 @@ static int __devinit wf_fcu_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit wf_fcu_remove(struct i2c_client *client)
+static int wf_fcu_remove(struct i2c_client *client)
 {
        struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev);
        struct wf_fcu_fan *fan;
index e0ee80700cde4713430452bffbeb0625a51479db..35ef6e2582b85da123c9e0b9eb99889abc1b8b15 100644 (file)
@@ -656,7 +656,7 @@ static int wf_pm112_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit wf_pm112_remove(struct platform_device *dev)
+static int wf_pm112_remove(struct platform_device *dev)
 {
        wf_unregister_client(&pm112_events);
        /* should release all sensors and controls */
@@ -665,7 +665,7 @@ static int __devexit wf_pm112_remove(struct platform_device *dev)
 
 static struct platform_driver wf_pm112_driver = {
        .probe = wf_pm112_probe,
-       .remove = __devexit_p(wf_pm112_remove),
+       .remove = wf_pm112_remove,
        .driver = {
                .name = "windfarm",
                .owner  = THIS_MODULE,
index 04067e073aa956ee89e14b1898dbd5c0154c6c2c..af605e915d4196422681b6cd809d8aee3eadf600 100644 (file)
@@ -987,7 +987,7 @@ static int pm121_probe(struct platform_device *ddev)
        return 0;
 }
 
-static int __devexit pm121_remove(struct platform_device *ddev)
+static int pm121_remove(struct platform_device *ddev)
 {
        wf_unregister_client(&pm121_events);
        return 0;
@@ -995,7 +995,7 @@ static int __devexit pm121_remove(struct platform_device *ddev)
 
 static struct platform_driver pm121_driver = {
        .probe = pm121_probe,
-       .remove = __devexit_p(pm121_remove),
+       .remove = pm121_remove,
        .driver = {
                .name = "windfarm",
                .bus = &platform_bus_type,
index 84ac913d7e3a11242ec891faa82a61597635da92..6e5585357cd356dfde400a0ab6590b94cdc22b03 100644 (file)
@@ -776,7 +776,7 @@ static int wf_pm72_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit wf_pm72_remove(struct platform_device *dev)
+static int wf_pm72_remove(struct platform_device *dev)
 {
        wf_unregister_client(&pm72_events);
 
index 990c87606be9579db02549c765a05b9ebb82ee5c..f84933ff32988abac0ca8511b997f188dc9f226e 100644 (file)
@@ -720,7 +720,7 @@ static int wf_smu_probe(struct platform_device *ddev)
        return 0;
 }
 
-static int __devexit wf_smu_remove(struct platform_device *ddev)
+static int wf_smu_remove(struct platform_device *ddev)
 {
        wf_unregister_client(&wf_smu_events);
 
@@ -763,7 +763,7 @@ static int __devexit wf_smu_remove(struct platform_device *ddev)
 
 static struct platform_driver wf_smu_driver = {
         .probe = wf_smu_probe,
-        .remove = __devexit_p(wf_smu_remove),
+        .remove = wf_smu_remove,
        .driver = {
                .name = "windfarm",
                .owner  = THIS_MODULE,
index 7653603cb00eee8069eabf10d3a022e4b54a00ce..2eb484f213c84086655aae5adbedf9cebbb98cf0 100644 (file)
@@ -642,7 +642,7 @@ static int wf_smu_probe(struct platform_device *ddev)
        return 0;
 }
 
-static int __devexit wf_smu_remove(struct platform_device *ddev)
+static int wf_smu_remove(struct platform_device *ddev)
 {
        wf_unregister_client(&wf_smu_events);
 
@@ -692,7 +692,7 @@ static int __devexit wf_smu_remove(struct platform_device *ddev)
 
 static struct platform_driver wf_smu_driver = {
         .probe = wf_smu_probe,
-        .remove = __devexit_p(wf_smu_remove),
+        .remove = wf_smu_remove,
        .driver = {
                .name = "windfarm",
                .owner  = THIS_MODULE,
index 3eca6d4b52fce708235d4ddbc6c5b8c71905040f..844003fb4ef0d798001660e8ab8c58ad6d85354f 100644 (file)
@@ -669,7 +669,7 @@ static int wf_rm31_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit wf_rm31_remove(struct platform_device *dev)
+static int wf_rm31_remove(struct platform_device *dev)
 {
        wf_unregister_client(&rm31_events);
 
index e4e84156745972b6b910901ed7d4f6e5bceeb749..aefb78e3cbf9beda9a1bfe3170123a22d02ccfbb 100644 (file)
@@ -207,31 +207,6 @@ void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios)
 }
 EXPORT_SYMBOL_GPL(dm_cell_release);
 
-/*
- * There are a couple of places where we put a bio into a cell briefly
- * before taking it out again.  In these situations we know that no other
- * bio may be in the cell.  This function releases the cell, and also does
- * a sanity check.
- */
-static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
-{
-       BUG_ON(cell->holder != bio);
-       BUG_ON(!bio_list_empty(&cell->bios));
-
-       __cell_release(cell, NULL);
-}
-
-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio)
-{
-       unsigned long flags;
-       struct dm_bio_prison *prison = cell->prison;
-
-       spin_lock_irqsave(&prison->lock, flags);
-       __cell_release_singleton(cell, bio);
-       spin_unlock_irqrestore(&prison->lock, flags);
-}
-EXPORT_SYMBOL_GPL(dm_cell_release_singleton);
-
 /*
  * Sometimes we don't want the holder, just the additional bios.
  */
index 4e0ac376700ab7c7384f2f8aeceed3d4e6f107b5..53d1a7a84e2fec12da0bccfa23e0a86fb01fcbfb 100644 (file)
@@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key,
                  struct bio *inmate, struct dm_bio_prison_cell **ref);
 
 void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios);
-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed
 void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates);
 void dm_cell_error(struct dm_bio_prison_cell *cell);
 
index bbf459bca61d9442e11b9ca544084877b2155268..f7369f9d85957539e628cb037b076822318fdeb8 100644 (file)
@@ -1689,8 +1689,7 @@ bad:
        return ret;
 }
 
-static int crypt_map(struct dm_target *ti, struct bio *bio,
-                    union map_info *map_context)
+static int crypt_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_crypt_io *io;
        struct crypt_config *cc = ti->private;
@@ -1846,7 +1845,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
 
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 11, 0},
+       .version = {1, 12, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
index f53846f9ab502466be3208312e8cea518a8eff4d..cc1bd048acb2ba281ea22586d34b2fc2caa2263d 100644 (file)
@@ -274,8 +274,7 @@ static void delay_resume(struct dm_target *ti)
        atomic_set(&dc->may_delay, 1);
 }
 
-static int delay_map(struct dm_target *ti, struct bio *bio,
-                    union map_info *map_context)
+static int delay_map(struct dm_target *ti, struct bio *bio)
 {
        struct delay_c *dc = ti->private;
 
@@ -338,7 +337,7 @@ out:
 
 static struct target_type delay_target = {
        .name        = "delay",
-       .version     = {1, 1, 0},
+       .version     = {1, 2, 0},
        .module      = THIS_MODULE,
        .ctr         = delay_ctr,
        .dtr         = delay_dtr,
index cc15543a6ad7088d712151df371a5b0b92d02dbe..9721f2ffb1a22ba33e1b119728e15d106017f6ec 100644 (file)
@@ -39,6 +39,10 @@ enum feature_flag_bits {
        DROP_WRITES
 };
 
+struct per_bio_data {
+       bool bio_submitted;
+};
+
 static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
                          struct dm_target *ti)
 {
@@ -214,6 +218,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->num_flush_requests = 1;
        ti->num_discard_requests = 1;
+       ti->per_bio_data_size = sizeof(struct per_bio_data);
        ti->private = fc;
        return 0;
 
@@ -265,11 +270,12 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
        }
 }
 
-static int flakey_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int flakey_map(struct dm_target *ti, struct bio *bio)
 {
        struct flakey_c *fc = ti->private;
        unsigned elapsed;
+       struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
+       pb->bio_submitted = false;
 
        /* Are we alive ? */
        elapsed = (jiffies - fc->start_time) / HZ;
@@ -277,7 +283,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio,
                /*
                 * Flag this bio as submitted while down.
                 */
-               map_context->ll = 1;
+               pb->bio_submitted = true;
 
                /*
                 * Map reads as normal.
@@ -314,17 +320,16 @@ map_bio:
        return DM_MAPIO_REMAPPED;
 }
 
-static int flakey_end_io(struct dm_target *ti, struct bio *bio,
-                        int error, union map_info *map_context)
+static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct flakey_c *fc = ti->private;
-       unsigned bio_submitted_while_down = map_context->ll;
+       struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
 
        /*
         * Corrupt successful READs while in down state.
         * If flags were specified, only corrupt those that match.
         */
-       if (fc->corrupt_bio_byte && !error && bio_submitted_while_down &&
+       if (fc->corrupt_bio_byte && !error && pb->bio_submitted &&
            (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
            all_corrupt_bio_flags_match(bio, fc))
                corrupt_bio_data(bio, fc);
@@ -406,7 +411,7 @@ static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_
 
 static struct target_type flakey_target = {
        .name   = "flakey",
-       .version = {1, 2, 0},
+       .version = {1, 3, 0},
        .module = THIS_MODULE,
        .ctr    = flakey_ctr,
        .dtr    = flakey_dtr,
index 1c46f97d6664a850ea286f90b6a36e82d6b73074..ea49834377c8e17b6e8b221e4bd58389a8d7c32e 100644 (file)
@@ -287,7 +287,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
        unsigned num_bvecs;
        sector_t remaining = where->count;
        struct request_queue *q = bdev_get_queue(where->bdev);
-       sector_t discard_sectors;
+       unsigned short logical_block_size = queue_logical_block_size(q);
+       sector_t num_sectors;
 
        /*
         * where->count may be zero if rw holds a flush and we need to
@@ -297,7 +298,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                /*
                 * Allocate a suitably sized-bio.
                 */
-               if (rw & REQ_DISCARD)
+               if ((rw & REQ_DISCARD) || (rw & REQ_WRITE_SAME))
                        num_bvecs = 1;
                else
                        num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev),
@@ -310,9 +311,21 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                store_io_and_region_in_bio(bio, io, region);
 
                if (rw & REQ_DISCARD) {
-                       discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
-                       bio->bi_size = discard_sectors << SECTOR_SHIFT;
-                       remaining -= discard_sectors;
+                       num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
+                       bio->bi_size = num_sectors << SECTOR_SHIFT;
+                       remaining -= num_sectors;
+               } else if (rw & REQ_WRITE_SAME) {
+                       /*
+                        * WRITE SAME only uses a single page.
+                        */
+                       dp->get_page(dp, &page, &len, &offset);
+                       bio_add_page(bio, page, logical_block_size, offset);
+                       num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
+                       bio->bi_size = num_sectors << SECTOR_SHIFT;
+
+                       offset = 0;
+                       remaining -= num_sectors;
+                       dp->next_page(dp);
                } else while (remaining) {
                        /*
                         * Try and add as many pages as possible.
index afd95986d09903a11652aafe8e90912db9f356ca..0666b5d14b883b244a054932e2f52bb7ede66d25 100644 (file)
@@ -1543,7 +1543,21 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
        return r;
 }
 
-static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
+#define DM_PARAMS_VMALLOC      0x0001  /* Params alloced with vmalloc not kmalloc */
+#define DM_WIPE_BUFFER         0x0010  /* Wipe input buffer before returning from ioctl */
+
+static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
+{
+       if (param_flags & DM_WIPE_BUFFER)
+               memset(param, 0, param_size);
+
+       if (param_flags & DM_PARAMS_VMALLOC)
+               vfree(param);
+       else
+               kfree(param);
+}
+
+static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param, int *param_flags)
 {
        struct dm_ioctl tmp, *dmi;
        int secure_data;
@@ -1556,7 +1570,21 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
 
        secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
 
-       dmi = vmalloc(tmp.data_size);
+       *param_flags = secure_data ? DM_WIPE_BUFFER : 0;
+
+       /*
+        * Try to avoid low memory issues when a device is suspended.
+        * Use kmalloc() rather than vmalloc() when we can.
+        */
+       dmi = NULL;
+       if (tmp.data_size <= KMALLOC_MAX_SIZE)
+               dmi = kmalloc(tmp.data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+
+       if (!dmi) {
+               dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL);
+               *param_flags |= DM_PARAMS_VMALLOC;
+       }
+
        if (!dmi) {
                if (secure_data && clear_user(user, tmp.data_size))
                        return -EFAULT;
@@ -1566,6 +1594,14 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
        if (copy_from_user(dmi, user, tmp.data_size))
                goto bad;
 
+       /*
+        * Abort if something changed the ioctl data while it was being copied.
+        */
+       if (dmi->data_size != tmp.data_size) {
+               DMERR("rejecting ioctl: data size modified while processing parameters");
+               goto bad;
+       }
+
        /* Wipe the user buffer so we do not return it to userspace */
        if (secure_data && clear_user(user, tmp.data_size))
                goto bad;
@@ -1574,9 +1610,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
        return 0;
 
 bad:
-       if (secure_data)
-               memset(dmi, 0, tmp.data_size);
-       vfree(dmi);
+       free_params(dmi, tmp.data_size, *param_flags);
+
        return -EFAULT;
 }
 
@@ -1613,7 +1648,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
 static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
 {
        int r = 0;
-       int wipe_buffer;
+       int param_flags;
        unsigned int cmd;
        struct dm_ioctl *uninitialized_var(param);
        ioctl_fn fn = NULL;
@@ -1648,25 +1683,15 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
                return -ENOTTY;
        }
 
-       /*
-        * Trying to avoid low memory issues when a device is
-        * suspended.
-        */
-       current->flags |= PF_MEMALLOC;
-
        /*
         * Copy the parameters into kernel space.
         */
-       r = copy_params(user, &param);
-
-       current->flags &= ~PF_MEMALLOC;
+       r = copy_params(user, &param, &param_flags);
 
        if (r)
                return r;
 
        input_param_size = param->data_size;
-       wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
-
        r = validate_params(cmd, param);
        if (r)
                goto out;
@@ -1681,10 +1706,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
                r = -EFAULT;
 
 out:
-       if (wipe_buffer)
-               memset(param, 0, input_param_size);
-
-       vfree(param);
+       free_params(param, input_param_size, param_flags);
        return r;
 }
 
index bed444c93d8d49e03757fdf88c8facb7d98f07dc..68c02673263ba87b9749cda3e119838e75edf22a 100644 (file)
@@ -349,7 +349,7 @@ static void complete_io(unsigned long error, void *context)
        struct dm_kcopyd_client *kc = job->kc;
 
        if (error) {
-               if (job->rw == WRITE)
+               if (job->rw & WRITE)
                        job->write_err |= error;
                else
                        job->read_err = 1;
@@ -361,7 +361,7 @@ static void complete_io(unsigned long error, void *context)
                }
        }
 
-       if (job->rw == WRITE)
+       if (job->rw & WRITE)
                push(&kc->complete_jobs, job);
 
        else {
@@ -432,7 +432,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
 
                if (r < 0) {
                        /* error this rogue job */
-                       if (job->rw == WRITE)
+                       if (job->rw & WRITE)
                                job->write_err = (unsigned long) -1L;
                        else
                                job->read_err = 1;
@@ -585,6 +585,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
                   unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
 {
        struct kcopyd_job *job;
+       int i;
 
        /*
         * Allocate an array of jobs consisting of one master job
@@ -611,7 +612,16 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
                memset(&job->source, 0, sizeof job->source);
                job->source.count = job->dests[0].count;
                job->pages = &zero_page_list;
-               job->rw = WRITE;
+
+               /*
+                * Use WRITE SAME to optimize zeroing if all dests support it.
+                */
+               job->rw = WRITE | REQ_WRITE_SAME;
+               for (i = 0; i < job->num_dests; i++)
+                       if (!bdev_write_same(job->dests[i].bdev)) {
+                               job->rw = WRITE;
+                               break;
+                       }
        }
 
        job->fn = fn;
index 1bf19a93eef05f00c68f3ad096dd46273991ef93..328cad5617ab3f931c4201ad2dedfeca8190dd73 100644 (file)
@@ -55,6 +55,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->num_flush_requests = 1;
        ti->num_discard_requests = 1;
+       ti->num_write_same_requests = 1;
        ti->private = lc;
        return 0;
 
@@ -87,8 +88,7 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio)
                bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
 }
 
-static int linear_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int linear_map(struct dm_target *ti, struct bio *bio)
 {
        linear_map_bio(ti, bio);
 
@@ -155,7 +155,7 @@ static int linear_iterate_devices(struct dm_target *ti,
 
 static struct target_type linear_target = {
        .name   = "linear",
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module = THIS_MODULE,
        .ctr    = linear_ctr,
        .dtr    = linear_dtr,
index 45d94a7e7f6db798ce291546f7916b246203f85b..9e58dbd8d8cba839da9613e5f4e4060795cd0dc1 100644 (file)
@@ -295,9 +295,11 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
                 * Choose a reasonable default.  All figures in sectors.
                 */
                if (min_region_size > (1 << 13)) {
+                       /* If not a power of 2, make it the next power of 2 */
+                       if (min_region_size & (min_region_size - 1))
+                               region_size = 1 << fls(region_size);
                        DMINFO("Choosing default region size of %lu sectors",
                               region_size);
-                       region_size = min_region_size;
                } else {
                        DMINFO("Choosing default region size of 4MiB");
                        region_size = 1 << 13; /* sectors */
@@ -338,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
 }
 
 /*
- * validate_rebuild_devices
+ * validate_raid_redundancy
  * @rs
  *
- * Determine if the devices specified for rebuild can result in a valid
- * usable array that is capable of rebuilding the given devices.
+ * Determine if there are enough devices in the array that haven't
+ * failed (or are being rebuilt) to form a usable array.
  *
  * Returns: 0 on success, -EINVAL on failure.
  */
-static int validate_rebuild_devices(struct raid_set *rs)
+static int validate_raid_redundancy(struct raid_set *rs)
 {
        unsigned i, rebuild_cnt = 0;
        unsigned rebuilds_per_group, copies, d;
 
-       if (!(rs->print_flags & DMPF_REBUILD))
-               return 0;
-
        for (i = 0; i < rs->md.raid_disks; i++)
-               if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+               if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+                   !rs->dev[i].rdev.sb_page)
                        rebuild_cnt++;
 
        switch (rs->raid_type->level) {
@@ -391,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs)
                 *          A    A    B    B    C
                 *          C    D    D    E    E
                 */
-               rebuilds_per_group = 0;
                for (i = 0; i < rs->md.raid_disks * copies; i++) {
+                       if (!(i % copies))
+                               rebuilds_per_group = 0;
                        d = i % rs->md.raid_disks;
-                       if (!test_bit(In_sync, &rs->dev[d].rdev.flags) &&
+                       if ((!rs->dev[d].rdev.sb_page ||
+                            !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
                            (++rebuilds_per_group >= copies))
                                goto too_many;
-                       if (!((i + 1) % copies))
-                               rebuilds_per_group = 0;
                }
                break;
        default:
-               DMERR("The rebuild parameter is not supported for %s",
-                     rs->raid_type->name);
-               rs->ti->error = "Rebuild not supported for this RAID type";
-               return -EINVAL;
+               if (rebuild_cnt)
+                       return -EINVAL;
        }
 
        return 0;
 
 too_many:
-       rs->ti->error = "Too many rebuild devices specified";
        return -EINVAL;
 }
 
@@ -662,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
        }
        rs->md.dev_sectors = sectors_per_dev;
 
-       if (validate_rebuild_devices(rs))
-               return -EINVAL;
-
        /* Assume there are no metadata devices until the drives are parsed */
        rs->md.persistent = 0;
        rs->md.external = 1;
@@ -993,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
        int ret;
-       unsigned redundancy = 0;
        struct raid_dev *dev;
        struct md_rdev *rdev, *tmp, *freshest;
        struct mddev *mddev = &rs->md;
 
-       switch (rs->raid_type->level) {
-       case 1:
-               redundancy = rs->md.raid_disks - 1;
-               break;
-       case 4:
-       case 5:
-       case 6:
-               redundancy = rs->raid_type->parity_devs;
-               break;
-       case 10:
-               redundancy = raid10_md_layout_to_copies(mddev->layout) - 1;
-               break;
-       default:
-               ti->error = "Unknown RAID type";
-               return -EINVAL;
-       }
-
        freshest = NULL;
        rdev_for_each_safe(rdev, tmp, mddev) {
                /*
@@ -1043,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
                        break;
                default:
                        dev = container_of(rdev, struct raid_dev, rdev);
-                       if (redundancy--) {
-                               if (dev->meta_dev)
-                                       dm_put_device(ti, dev->meta_dev);
-
-                               dev->meta_dev = NULL;
-                               rdev->meta_bdev = NULL;
+                       if (dev->meta_dev)
+                               dm_put_device(ti, dev->meta_dev);
 
-                               if (rdev->sb_page)
-                                       put_page(rdev->sb_page);
+                       dev->meta_dev = NULL;
+                       rdev->meta_bdev = NULL;
 
-                               rdev->sb_page = NULL;
+                       if (rdev->sb_page)
+                               put_page(rdev->sb_page);
 
-                               rdev->sb_loaded = 0;
+                       rdev->sb_page = NULL;
 
-                               /*
-                                * We might be able to salvage the data device
-                                * even though the meta device has failed.  For
-                                * now, we behave as though '- -' had been
-                                * set for this device in the table.
-                                */
-                               if (dev->data_dev)
-                                       dm_put_device(ti, dev->data_dev);
+                       rdev->sb_loaded = 0;
 
-                               dev->data_dev = NULL;
-                               rdev->bdev = NULL;
+                       /*
+                        * We might be able to salvage the data device
+                        * even though the meta device has failed.  For
+                        * now, we behave as though '- -' had been
+                        * set for this device in the table.
+                        */
+                       if (dev->data_dev)
+                               dm_put_device(ti, dev->data_dev);
 
-                               list_del(&rdev->same_set);
+                       dev->data_dev = NULL;
+                       rdev->bdev = NULL;
 
-                               continue;
-                       }
-                       ti->error = "Failed to load superblock";
-                       return ret;
+                       list_del(&rdev->same_set);
                }
        }
 
        if (!freshest)
                return 0;
 
+       if (validate_raid_redundancy(rs)) {
+               rs->ti->error = "Insufficient redundancy to activate array";
+               return -EINVAL;
+       }
+
        /*
         * Validation of the freshest device provides the source of
         * validation for the remaining devices.
@@ -1216,7 +1191,7 @@ static void raid_dtr(struct dm_target *ti)
        context_free(rs);
 }
 
-static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_context)
+static int raid_map(struct dm_target *ti, struct bio *bio)
 {
        struct raid_set *rs = ti->private;
        struct mddev *mddev = &rs->md;
@@ -1430,7 +1405,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 3, 1},
+       .version = {1, 4, 1},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index fd61f98ee1f68af3085297afc0b1c46dc0899e2f..fa519185ebba8cb3eabd63293887c585800ec2b7 100644 (file)
@@ -61,7 +61,6 @@ struct mirror_set {
        struct dm_region_hash *rh;
        struct dm_kcopyd_client *kcopyd_client;
        struct dm_io_client *io_client;
-       mempool_t *read_record_pool;
 
        /* recovery */
        region_t nr_regions;
@@ -139,14 +138,13 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
                queue_bio(ms, bio, WRITE);
 }
 
-#define MIN_READ_RECORDS 20
-struct dm_raid1_read_record {
+struct dm_raid1_bio_record {
        struct mirror *m;
+       /* if details->bi_bdev == NULL, details were not saved */
        struct dm_bio_details details;
+       region_t write_region;
 };
 
-static struct kmem_cache *_dm_raid1_read_record_cache;
-
 /*
  * Every mirror should look like this one.
  */
@@ -876,19 +874,9 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
        atomic_set(&ms->suspend, 0);
        atomic_set(&ms->default_mirror, DEFAULT_MIRROR);
 
-       ms->read_record_pool = mempool_create_slab_pool(MIN_READ_RECORDS,
-                                               _dm_raid1_read_record_cache);
-
-       if (!ms->read_record_pool) {
-               ti->error = "Error creating mirror read_record_pool";
-               kfree(ms);
-               return NULL;
-       }
-
        ms->io_client = dm_io_client_create();
        if (IS_ERR(ms->io_client)) {
                ti->error = "Error creating dm_io client";
-               mempool_destroy(ms->read_record_pool);
                kfree(ms);
                return NULL;
        }
@@ -900,7 +888,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
        if (IS_ERR(ms->rh)) {
                ti->error = "Error creating dirty region hash";
                dm_io_client_destroy(ms->io_client);
-               mempool_destroy(ms->read_record_pool);
                kfree(ms);
                return NULL;
        }
@@ -916,7 +903,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
 
        dm_io_client_destroy(ms->io_client);
        dm_region_hash_destroy(ms->rh);
-       mempool_destroy(ms->read_record_pool);
        kfree(ms);
 }
 
@@ -1088,6 +1074,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->num_flush_requests = 1;
        ti->num_discard_requests = 1;
+       ti->per_bio_data_size = sizeof(struct dm_raid1_bio_record);
        ti->discard_zeroes_data_unsupported = true;
 
        ms->kmirrord_wq = alloc_workqueue("kmirrord",
@@ -1155,18 +1142,20 @@ static void mirror_dtr(struct dm_target *ti)
 /*
  * Mirror mapping function
  */
-static int mirror_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int mirror_map(struct dm_target *ti, struct bio *bio)
 {
        int r, rw = bio_rw(bio);
        struct mirror *m;
        struct mirror_set *ms = ti->private;
-       struct dm_raid1_read_record *read_record = NULL;
        struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
+       struct dm_raid1_bio_record *bio_record =
+         dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
+
+       bio_record->details.bi_bdev = NULL;
 
        if (rw == WRITE) {
                /* Save region for mirror_end_io() handler */
-               map_context->ll = dm_rh_bio_to_region(ms->rh, bio);
+               bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
                queue_bio(ms, bio, rw);
                return DM_MAPIO_SUBMITTED;
        }
@@ -1194,33 +1183,29 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
        if (unlikely(!m))
                return -EIO;
 
-       read_record = mempool_alloc(ms->read_record_pool, GFP_NOIO);
-       if (likely(read_record)) {
-               dm_bio_record(&read_record->details, bio);
-               map_context->ptr = read_record;
-               read_record->m = m;
-       }
+       dm_bio_record(&bio_record->details, bio);
+       bio_record->m = m;
 
        map_bio(m, bio);
 
        return DM_MAPIO_REMAPPED;
 }
 
-static int mirror_end_io(struct dm_target *ti, struct bio *bio,
-                        int error, union map_info *map_context)
+static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        int rw = bio_rw(bio);
        struct mirror_set *ms = (struct mirror_set *) ti->private;
        struct mirror *m = NULL;
        struct dm_bio_details *bd = NULL;
-       struct dm_raid1_read_record *read_record = map_context->ptr;
+       struct dm_raid1_bio_record *bio_record =
+         dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
 
        /*
         * We need to dec pending if this was a write.
         */
        if (rw == WRITE) {
                if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
-                       dm_rh_dec(ms->rh, map_context->ll);
+                       dm_rh_dec(ms->rh, bio_record->write_region);
                return error;
        }
 
@@ -1231,7 +1216,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
                goto out;
 
        if (unlikely(error)) {
-               if (!read_record) {
+               if (!bio_record->details.bi_bdev) {
                        /*
                         * There wasn't enough memory to record necessary
                         * information for a retry or there was no other
@@ -1241,7 +1226,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
                        return -EIO;
                }
 
-               m = read_record->m;
+               m = bio_record->m;
 
                DMERR("Mirror read failed from %s. Trying alternative device.",
                      m->dev->name);
@@ -1253,22 +1238,18 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
                 * mirror.
                 */
                if (default_ok(m) || mirror_available(ms, bio)) {
-                       bd = &read_record->details;
+                       bd = &bio_record->details;
 
                        dm_bio_restore(bd, bio);
-                       mempool_free(read_record, ms->read_record_pool);
-                       map_context->ptr = NULL;
+                       bio_record->details.bi_bdev = NULL;
                        queue_bio(ms, bio, rw);
-                       return 1;
+                       return DM_ENDIO_INCOMPLETE;
                }
                DMERR("All replicated volumes dead, failing I/O");
        }
 
 out:
-       if (read_record) {
-               mempool_free(read_record, ms->read_record_pool);
-               map_context->ptr = NULL;
-       }
+       bio_record->details.bi_bdev = NULL;
 
        return error;
 }
@@ -1422,7 +1403,7 @@ static int mirror_iterate_devices(struct dm_target *ti,
 
 static struct target_type mirror_target = {
        .name    = "mirror",
-       .version = {1, 12, 1},
+       .version = {1, 13, 1},
        .module  = THIS_MODULE,
        .ctr     = mirror_ctr,
        .dtr     = mirror_dtr,
@@ -1439,13 +1420,6 @@ static int __init dm_mirror_init(void)
 {
        int r;
 
-       _dm_raid1_read_record_cache = KMEM_CACHE(dm_raid1_read_record, 0);
-       if (!_dm_raid1_read_record_cache) {
-               DMERR("Can't allocate dm_raid1_read_record cache");
-               r = -ENOMEM;
-               goto bad_cache;
-       }
-
        r = dm_register_target(&mirror_target);
        if (r < 0) {
                DMERR("Failed to register mirror target");
@@ -1455,15 +1429,12 @@ static int __init dm_mirror_init(void)
        return 0;
 
 bad_target:
-       kmem_cache_destroy(_dm_raid1_read_record_cache);
-bad_cache:
        return r;
 }
 
 static void __exit dm_mirror_exit(void)
 {
        dm_unregister_target(&mirror_target);
-       kmem_cache_destroy(_dm_raid1_read_record_cache);
 }
 
 /* Module hooks */
index a143921feaf6480119f77d4f8600aefc98c7b583..59fc18ae52c21697477738188c395a4085686658 100644 (file)
@@ -79,7 +79,6 @@ struct dm_snapshot {
 
        /* Chunks with outstanding reads */
        spinlock_t tracked_chunk_lock;
-       mempool_t *tracked_chunk_pool;
        struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
 
        /* The on disk metadata handler */
@@ -191,35 +190,38 @@ struct dm_snap_tracked_chunk {
        chunk_t chunk;
 };
 
-static struct kmem_cache *tracked_chunk_cache;
+static void init_tracked_chunk(struct bio *bio)
+{
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
+       INIT_HLIST_NODE(&c->node);
+}
 
-static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
-                                                chunk_t chunk)
+static bool is_bio_tracked(struct bio *bio)
 {
-       struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
-                                                       GFP_NOIO);
-       unsigned long flags;
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
+       return !hlist_unhashed(&c->node);
+}
+
+static void track_chunk(struct dm_snapshot *s, struct bio *bio, chunk_t chunk)
+{
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
 
        c->chunk = chunk;
 
-       spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+       spin_lock_irq(&s->tracked_chunk_lock);
        hlist_add_head(&c->node,
                       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
-       spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
-
-       return c;
+       spin_unlock_irq(&s->tracked_chunk_lock);
 }
 
-static void stop_tracking_chunk(struct dm_snapshot *s,
-                               struct dm_snap_tracked_chunk *c)
+static void stop_tracking_chunk(struct dm_snapshot *s, struct bio *bio)
 {
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
        unsigned long flags;
 
        spin_lock_irqsave(&s->tracked_chunk_lock, flags);
        hlist_del(&c->node);
        spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
-
-       mempool_free(c, s->tracked_chunk_pool);
 }
 
 static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
@@ -1120,14 +1122,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad_pending_pool;
        }
 
-       s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
-                                                        tracked_chunk_cache);
-       if (!s->tracked_chunk_pool) {
-               ti->error = "Could not allocate tracked_chunk mempool for "
-                           "tracking reads";
-               goto bad_tracked_chunk_pool;
-       }
-
        for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
                INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
 
@@ -1135,6 +1129,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->private = s;
        ti->num_flush_requests = num_flush_requests;
+       ti->per_bio_data_size = sizeof(struct dm_snap_tracked_chunk);
 
        /* Add snapshot to the list of snapshots for this origin */
        /* Exceptions aren't triggered till snapshot_resume() is called */
@@ -1183,9 +1178,6 @@ bad_read_metadata:
        unregister_snapshot(s);
 
 bad_load_and_register:
-       mempool_destroy(s->tracked_chunk_pool);
-
-bad_tracked_chunk_pool:
        mempool_destroy(s->pending_pool);
 
 bad_pending_pool:
@@ -1290,8 +1282,6 @@ static void snapshot_dtr(struct dm_target *ti)
                BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
 #endif
 
-       mempool_destroy(s->tracked_chunk_pool);
-
        __free_exceptions(s);
 
        mempool_destroy(s->pending_pool);
@@ -1577,8 +1567,7 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
                                          s->store->chunk_mask);
 }
 
-static int snapshot_map(struct dm_target *ti, struct bio *bio,
-                       union map_info *map_context)
+static int snapshot_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_exception *e;
        struct dm_snapshot *s = ti->private;
@@ -1586,6 +1575,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
        chunk_t chunk;
        struct dm_snap_pending_exception *pe = NULL;
 
+       init_tracked_chunk(bio);
+
        if (bio->bi_rw & REQ_FLUSH) {
                bio->bi_bdev = s->cow->bdev;
                return DM_MAPIO_REMAPPED;
@@ -1670,7 +1661,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
                }
        } else {
                bio->bi_bdev = s->origin->bdev;
-               map_context->ptr = track_chunk(s, chunk);
+               track_chunk(s, bio, chunk);
        }
 
 out_unlock:
@@ -1691,20 +1682,20 @@ out:
  * If merging is currently taking place on the chunk in question, the
  * I/O is deferred by adding it to s->bios_queued_during_merge.
  */
-static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
-                             union map_info *map_context)
+static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_exception *e;
        struct dm_snapshot *s = ti->private;
        int r = DM_MAPIO_REMAPPED;
        chunk_t chunk;
 
+       init_tracked_chunk(bio);
+
        if (bio->bi_rw & REQ_FLUSH) {
-               if (!map_context->target_request_nr)
+               if (!dm_bio_get_target_request_nr(bio))
                        bio->bi_bdev = s->origin->bdev;
                else
                        bio->bi_bdev = s->cow->bdev;
-               map_context->ptr = NULL;
                return DM_MAPIO_REMAPPED;
        }
 
@@ -1733,7 +1724,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
                remap_exception(s, e, bio, chunk);
 
                if (bio_rw(bio) == WRITE)
-                       map_context->ptr = track_chunk(s, chunk);
+                       track_chunk(s, bio, chunk);
                goto out_unlock;
        }
 
@@ -1751,14 +1742,12 @@ out_unlock:
        return r;
 }
 
-static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
-                          int error, union map_info *map_context)
+static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct dm_snapshot *s = ti->private;
-       struct dm_snap_tracked_chunk *c = map_context->ptr;
 
-       if (c)
-               stop_tracking_chunk(s, c);
+       if (is_bio_tracked(bio))
+               stop_tracking_chunk(s, bio);
 
        return 0;
 }
@@ -2127,8 +2116,7 @@ static void origin_dtr(struct dm_target *ti)
        dm_put_device(ti, dev);
 }
 
-static int origin_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int origin_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_dev *dev = ti->private;
        bio->bi_bdev = dev->bdev;
@@ -2193,7 +2181,7 @@ static int origin_iterate_devices(struct dm_target *ti,
 
 static struct target_type origin_target = {
        .name    = "snapshot-origin",
-       .version = {1, 7, 1},
+       .version = {1, 8, 0},
        .module  = THIS_MODULE,
        .ctr     = origin_ctr,
        .dtr     = origin_dtr,
@@ -2206,7 +2194,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 10, 0},
+       .version = {1, 11, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2220,7 +2208,7 @@ static struct target_type snapshot_target = {
 
 static struct target_type merge_target = {
        .name    = dm_snapshot_merge_target_name,
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2281,17 +2269,8 @@ static int __init dm_snapshot_init(void)
                goto bad_pending_cache;
        }
 
-       tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
-       if (!tracked_chunk_cache) {
-               DMERR("Couldn't create cache to track chunks in use.");
-               r = -ENOMEM;
-               goto bad_tracked_chunk_cache;
-       }
-
        return 0;
 
-bad_tracked_chunk_cache:
-       kmem_cache_destroy(pending_cache);
 bad_pending_cache:
        kmem_cache_destroy(exception_cache);
 bad_exception_cache:
@@ -2317,7 +2296,6 @@ static void __exit dm_snapshot_exit(void)
        exit_origin_hash();
        kmem_cache_destroy(pending_cache);
        kmem_cache_destroy(exception_cache);
-       kmem_cache_destroy(tracked_chunk_cache);
 
        dm_exception_store_exit();
 }
index e2f876539743feb800022f4b6da23fe776721fac..c89cde86d400b409dee677184635ef4b77041fcc 100644 (file)
@@ -162,6 +162,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->num_flush_requests = stripes;
        ti->num_discard_requests = stripes;
+       ti->num_write_same_requests = stripes;
 
        sc->chunk_size = chunk_size;
        if (chunk_size & (chunk_size - 1))
@@ -251,8 +252,8 @@ static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector,
                *result += sc->chunk_size;              /* next chunk */
 }
 
-static int stripe_map_discard(struct stripe_c *sc, struct bio *bio,
-                             uint32_t target_stripe)
+static int stripe_map_range(struct stripe_c *sc, struct bio *bio,
+                           uint32_t target_stripe)
 {
        sector_t begin, end;
 
@@ -271,23 +272,23 @@ static int stripe_map_discard(struct stripe_c *sc, struct bio *bio,
        }
 }
 
-static int stripe_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int stripe_map(struct dm_target *ti, struct bio *bio)
 {
        struct stripe_c *sc = ti->private;
        uint32_t stripe;
        unsigned target_request_nr;
 
        if (bio->bi_rw & REQ_FLUSH) {
-               target_request_nr = map_context->target_request_nr;
+               target_request_nr = dm_bio_get_target_request_nr(bio);
                BUG_ON(target_request_nr >= sc->stripes);
                bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
                return DM_MAPIO_REMAPPED;
        }
-       if (unlikely(bio->bi_rw & REQ_DISCARD)) {
-               target_request_nr = map_context->target_request_nr;
+       if (unlikely(bio->bi_rw & REQ_DISCARD) ||
+           unlikely(bio->bi_rw & REQ_WRITE_SAME)) {
+               target_request_nr = dm_bio_get_target_request_nr(bio);
                BUG_ON(target_request_nr >= sc->stripes);
-               return stripe_map_discard(sc, bio, target_request_nr);
+               return stripe_map_range(sc, bio, target_request_nr);
        }
 
        stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector);
@@ -342,8 +343,7 @@ static int stripe_status(struct dm_target *ti, status_type_t type,
        return 0;
 }
 
-static int stripe_end_io(struct dm_target *ti, struct bio *bio,
-                        int error, union map_info *map_context)
+static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        unsigned i;
        char major_minor[16];
index 100368eb7991a50c57e473ea20bf4a8441e91ff0..daf25d0890b3d6cdf9852b739593648f00b86425 100644 (file)
@@ -967,13 +967,22 @@ bool dm_table_request_based(struct dm_table *t)
 int dm_table_alloc_md_mempools(struct dm_table *t)
 {
        unsigned type = dm_table_get_type(t);
+       unsigned per_bio_data_size = 0;
+       struct dm_target *tgt;
+       unsigned i;
 
        if (unlikely(type == DM_TYPE_NONE)) {
                DMWARN("no table type is set, can't allocate mempools");
                return -EINVAL;
        }
 
-       t->mempools = dm_alloc_md_mempools(type, t->integrity_supported);
+       if (type == DM_TYPE_BIO_BASED)
+               for (i = 0; i < t->num_targets; i++) {
+                       tgt = t->targets + i;
+                       per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size);
+               }
+
+       t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_bio_data_size);
        if (!t->mempools)
                return -ENOMEM;
 
@@ -1414,6 +1423,33 @@ static bool dm_table_all_devices_attribute(struct dm_table *t,
        return 1;
 }
 
+static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev,
+                                        sector_t start, sector_t len, void *data)
+{
+       struct request_queue *q = bdev_get_queue(dev->bdev);
+
+       return q && !q->limits.max_write_same_sectors;
+}
+
+static bool dm_table_supports_write_same(struct dm_table *t)
+{
+       struct dm_target *ti;
+       unsigned i = 0;
+
+       while (i < dm_table_get_num_targets(t)) {
+               ti = dm_table_get_target(t, i++);
+
+               if (!ti->num_write_same_requests)
+                       return false;
+
+               if (!ti->type->iterate_devices ||
+                   !ti->type->iterate_devices(ti, device_not_write_same_capable, NULL))
+                       return false;
+       }
+
+       return true;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
                               struct queue_limits *limits)
 {
@@ -1445,6 +1481,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
        else
                queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
 
+       if (!dm_table_supports_write_same(t))
+               q->limits.max_write_same_sectors = 0;
+
        dm_table_set_integrity(t);
 
        /*
index 8da366cf381cdbd2f7d1b830bd7ecbe1191a5df1..617d21a772568dad424aa1b49cb0a53de980b775 100644 (file)
@@ -126,15 +126,14 @@ static void io_err_dtr(struct dm_target *tt)
        /* empty */
 }
 
-static int io_err_map(struct dm_target *tt, struct bio *bio,
-                     union map_info *map_context)
+static int io_err_map(struct dm_target *tt, struct bio *bio)
 {
        return -EIO;
 }
 
 static struct target_type error_target = {
        .name = "error",
-       .version = {1, 0, 1},
+       .version = {1, 1, 0},
        .ctr  = io_err_ctr,
        .dtr  = io_err_dtr,
        .map  = io_err_map,
index 693e149e97271dbe3fa3b646cfac018533892835..4d6e85367b847c498be7a26c7feb900bd607d329 100644 (file)
@@ -408,7 +408,7 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd)
 
        pmd->tl_info.tm = pmd->tm;
        pmd->tl_info.levels = 1;
-       pmd->tl_info.value_type.context = &pmd->info;
+       pmd->tl_info.value_type.context = &pmd->bl_info;
        pmd->tl_info.value_type.size = sizeof(__le64);
        pmd->tl_info.value_type.inc = subtree_inc;
        pmd->tl_info.value_type.dec = subtree_dec;
index 058acf3a5ba7aaa43ba58e0eb7dd1acfd1f6399b..5409607d487533593d29c2207d857896121364a3 100644 (file)
@@ -186,7 +186,6 @@ struct pool {
 
        struct dm_thin_new_mapping *next_mapping;
        mempool_t *mapping_pool;
-       mempool_t *endio_hook_pool;
 
        process_bio_fn process_bio;
        process_bio_fn process_discard;
@@ -304,7 +303,7 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
        bio_list_init(master);
 
        while ((bio = bio_list_pop(&bios))) {
-               struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
                if (h->tc == tc)
                        bio_endio(bio, DM_ENDIO_REQUEUE);
@@ -368,6 +367,17 @@ static int bio_triggers_commit(struct thin_c *tc, struct bio *bio)
                dm_thin_changed_this_transaction(tc->td);
 }
 
+static void inc_all_io_entry(struct pool *pool, struct bio *bio)
+{
+       struct dm_thin_endio_hook *h;
+
+       if (bio->bi_rw & REQ_DISCARD)
+               return;
+
+       h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
+       h->all_io_entry = dm_deferred_entry_inc(pool->all_io_ds);
+}
+
 static void issue(struct thin_c *tc, struct bio *bio)
 {
        struct pool *pool = tc->pool;
@@ -474,7 +484,7 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
 static void overwrite_endio(struct bio *bio, int err)
 {
        unsigned long flags;
-       struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
        struct dm_thin_new_mapping *m = h->overwrite_mapping;
        struct pool *pool = m->tc->pool;
 
@@ -499,8 +509,7 @@ static void overwrite_endio(struct bio *bio, int err)
 /*
  * This sends the bios in the cell back to the deferred_bios list.
  */
-static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell,
-                      dm_block_t data_block)
+static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell)
 {
        struct pool *pool = tc->pool;
        unsigned long flags;
@@ -513,17 +522,13 @@ static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell,
 }
 
 /*
- * Same as cell_defer above, except it omits one particular detainee,
- * a write bio that covers the block and has already been processed.
+ * Same as cell_defer except it omits the original holder of the cell.
  */
-static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *cell)
 {
-       struct bio_list bios;
        struct pool *pool = tc->pool;
        unsigned long flags;
 
-       bio_list_init(&bios);
-
        spin_lock_irqsave(&pool->lock, flags);
        dm_cell_release_no_holder(cell, &pool->deferred_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
@@ -561,7 +566,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
        if (r) {
-               DMERR("dm_thin_insert_block() failed");
+               DMERR_LIMIT("dm_thin_insert_block() failed");
                dm_cell_error(m->cell);
                goto out;
        }
@@ -573,10 +578,10 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         * the bios in the cell.
         */
        if (bio) {
-               cell_defer_except(tc, m->cell);
+               cell_defer_no_holder(tc, m->cell);
                bio_endio(bio, 0);
        } else
-               cell_defer(tc, m->cell, m->data_block);
+               cell_defer(tc, m->cell);
 
 out:
        list_del(&m->list);
@@ -588,8 +593,8 @@ static void process_prepared_discard_fail(struct dm_thin_new_mapping *m)
        struct thin_c *tc = m->tc;
 
        bio_io_error(m->bio);
-       cell_defer_except(tc, m->cell);
-       cell_defer_except(tc, m->cell2);
+       cell_defer_no_holder(tc, m->cell);
+       cell_defer_no_holder(tc, m->cell2);
        mempool_free(m, tc->pool->mapping_pool);
 }
 
@@ -597,13 +602,15 @@ static void process_prepared_discard_passdown(struct dm_thin_new_mapping *m)
 {
        struct thin_c *tc = m->tc;
 
+       inc_all_io_entry(tc->pool, m->bio);
+       cell_defer_no_holder(tc, m->cell);
+       cell_defer_no_holder(tc, m->cell2);
+
        if (m->pass_discard)
                remap_and_issue(tc, m->bio, m->data_block);
        else
                bio_endio(m->bio, 0);
 
-       cell_defer_except(tc, m->cell);
-       cell_defer_except(tc, m->cell2);
        mempool_free(m, tc->pool->mapping_pool);
 }
 
@@ -614,7 +621,7 @@ static void process_prepared_discard(struct dm_thin_new_mapping *m)
 
        r = dm_thin_remove_block(tc->td, m->virt_block);
        if (r)
-               DMERR("dm_thin_remove_block() failed");
+               DMERR_LIMIT("dm_thin_remove_block() failed");
 
        process_prepared_discard_passdown(m);
 }
@@ -706,11 +713,12 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
         * bio immediately. Otherwise we use kcopyd to clone the data first.
         */
        if (io_overwrites_block(pool, bio)) {
-               struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
                h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+               inc_all_io_entry(pool, bio);
                remap_and_issue(tc, bio, data_dest);
        } else {
                struct dm_io_region from, to;
@@ -727,7 +735,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
                                   0, copy_complete, m);
                if (r < 0) {
                        mempool_free(m, pool->mapping_pool);
-                       DMERR("dm_kcopyd_copy() failed");
+                       DMERR_LIMIT("dm_kcopyd_copy() failed");
                        dm_cell_error(cell);
                }
        }
@@ -775,11 +783,12 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
                process_prepared_mapping(m);
 
        else if (io_overwrites_block(pool, bio)) {
-               struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
                h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+               inc_all_io_entry(pool, bio);
                remap_and_issue(tc, bio, data_block);
        } else {
                int r;
@@ -792,7 +801,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
                r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
                if (r < 0) {
                        mempool_free(m, pool->mapping_pool);
-                       DMERR("dm_kcopyd_zero() failed");
+                       DMERR_LIMIT("dm_kcopyd_zero() failed");
                        dm_cell_error(cell);
                }
        }
@@ -804,7 +813,7 @@ static int commit(struct pool *pool)
 
        r = dm_pool_commit_metadata(pool->pmd);
        if (r)
-               DMERR("commit failed, error = %d", r);
+               DMERR_LIMIT("commit failed: error = %d", r);
 
        return r;
 }
@@ -889,7 +898,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
  */
 static void retry_on_resume(struct bio *bio)
 {
-       struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
        struct thin_c *tc = h->tc;
        struct pool *pool = tc->pool;
        unsigned long flags;
@@ -936,7 +945,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                 */
                build_data_key(tc->td, lookup_result.block, &key2);
                if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) {
-                       dm_cell_release_singleton(cell, bio);
+                       cell_defer_no_holder(tc, cell);
                        break;
                }
 
@@ -962,13 +971,15 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                                wake_worker(pool);
                        }
                } else {
+                       inc_all_io_entry(pool, bio);
+                       cell_defer_no_holder(tc, cell);
+                       cell_defer_no_holder(tc, cell2);
+
                        /*
                         * The DM core makes sure that the discard doesn't span
                         * a block boundary.  So we submit the discard of a
                         * partial block appropriately.
                         */
-                       dm_cell_release_singleton(cell, bio);
-                       dm_cell_release_singleton(cell2, bio);
                        if ((!lookup_result.shared) && pool->pf.discard_passdown)
                                remap_and_issue(tc, bio, lookup_result.block);
                        else
@@ -980,13 +991,14 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                /*
                 * It isn't provisioned, just forget it.
                 */
-               dm_cell_release_singleton(cell, bio);
+               cell_defer_no_holder(tc, cell);
                bio_endio(bio, 0);
                break;
 
        default:
-               DMERR("discard: find block unexpectedly returned %d", r);
-               dm_cell_release_singleton(cell, bio);
+               DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d",
+                           __func__, r);
+               cell_defer_no_holder(tc, cell);
                bio_io_error(bio);
                break;
        }
@@ -1012,7 +1024,8 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
                break;
 
        default:
-               DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+               DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
+                           __func__, r);
                dm_cell_error(cell);
                break;
        }
@@ -1037,11 +1050,12 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
        if (bio_data_dir(bio) == WRITE && bio->bi_size)
                break_sharing(tc, bio, block, &key, lookup_result, cell);
        else {
-               struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
                h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds);
+               inc_all_io_entry(pool, bio);
+               cell_defer_no_holder(tc, cell);
 
-               dm_cell_release_singleton(cell, bio);
                remap_and_issue(tc, bio, lookup_result->block);
        }
 }
@@ -1056,7 +1070,9 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
         * Remap empty bios (flushes) immediately, without provisioning.
         */
        if (!bio->bi_size) {
-               dm_cell_release_singleton(cell, bio);
+               inc_all_io_entry(tc->pool, bio);
+               cell_defer_no_holder(tc, cell);
+
                remap_and_issue(tc, bio, 0);
                return;
        }
@@ -1066,7 +1082,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
         */
        if (bio_data_dir(bio) == READ) {
                zero_fill_bio(bio);
-               dm_cell_release_singleton(cell, bio);
+               cell_defer_no_holder(tc, cell);
                bio_endio(bio, 0);
                return;
        }
@@ -1085,7 +1101,8 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
                break;
 
        default:
-               DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+               DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
+                           __func__, r);
                set_pool_mode(tc->pool, PM_READ_ONLY);
                dm_cell_error(cell);
                break;
@@ -1111,34 +1128,31 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
        switch (r) {
        case 0:
-               /*
-                * We can release this cell now.  This thread is the only
-                * one that puts bios into a cell, and we know there were
-                * no preceding bios.
-                */
-               /*
-                * TODO: this will probably have to change when discard goes
-                * back in.
-                */
-               dm_cell_release_singleton(cell, bio);
-
-               if (lookup_result.shared)
+               if (lookup_result.shared) {
                        process_shared_bio(tc, bio, block, &lookup_result);
-               else
+                       cell_defer_no_holder(tc, cell);
+               } else {
+                       inc_all_io_entry(tc->pool, bio);
+                       cell_defer_no_holder(tc, cell);
+
                        remap_and_issue(tc, bio, lookup_result.block);
+               }
                break;
 
        case -ENODATA:
                if (bio_data_dir(bio) == READ && tc->origin_dev) {
-                       dm_cell_release_singleton(cell, bio);
+                       inc_all_io_entry(tc->pool, bio);
+                       cell_defer_no_holder(tc, cell);
+
                        remap_to_origin_and_issue(tc, bio);
                } else
                        provision_block(tc, bio, block, cell);
                break;
 
        default:
-               DMERR("dm_thin_find_block() failed, error = %d", r);
-               dm_cell_release_singleton(cell, bio);
+               DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d",
+                           __func__, r);
+               cell_defer_no_holder(tc, cell);
                bio_io_error(bio);
                break;
        }
@@ -1156,8 +1170,10 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
        case 0:
                if (lookup_result.shared && (rw == WRITE) && bio->bi_size)
                        bio_io_error(bio);
-               else
+               else {
+                       inc_all_io_entry(tc->pool, bio);
                        remap_and_issue(tc, bio, lookup_result.block);
+               }
                break;
 
        case -ENODATA:
@@ -1167,6 +1183,7 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
                }
 
                if (tc->origin_dev) {
+                       inc_all_io_entry(tc->pool, bio);
                        remap_to_origin_and_issue(tc, bio);
                        break;
                }
@@ -1176,7 +1193,8 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
                break;
 
        default:
-               DMERR("dm_thin_find_block() failed, error = %d", r);
+               DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d",
+                           __func__, r);
                bio_io_error(bio);
                break;
        }
@@ -1207,7 +1225,7 @@ static void process_deferred_bios(struct pool *pool)
        spin_unlock_irqrestore(&pool->lock, flags);
 
        while ((bio = bio_list_pop(&bios))) {
-               struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
                struct thin_c *tc = h->tc;
 
                /*
@@ -1340,32 +1358,30 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
        wake_worker(pool);
 }
 
-static struct dm_thin_endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio)
+static void thin_hook_bio(struct thin_c *tc, struct bio *bio)
 {
-       struct pool *pool = tc->pool;
-       struct dm_thin_endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
        h->tc = tc;
        h->shared_read_entry = NULL;
-       h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds);
+       h->all_io_entry = NULL;
        h->overwrite_mapping = NULL;
-
-       return h;
 }
 
 /*
  * Non-blocking function called from the thin target's map function.
  */
-static int thin_bio_map(struct dm_target *ti, struct bio *bio,
-                       union map_info *map_context)
+static int thin_bio_map(struct dm_target *ti, struct bio *bio)
 {
        int r;
        struct thin_c *tc = ti->private;
        dm_block_t block = get_bio_block(tc, bio);
        struct dm_thin_device *td = tc->td;
        struct dm_thin_lookup_result result;
+       struct dm_bio_prison_cell *cell1, *cell2;
+       struct dm_cell_key key;
 
-       map_context->ptr = thin_hook_bio(tc, bio);
+       thin_hook_bio(tc, bio);
 
        if (get_pool_mode(tc->pool) == PM_FAIL) {
                bio_io_error(bio);
@@ -1400,12 +1416,25 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
                         * shared flag will be set in their case.
                         */
                        thin_defer_bio(tc, bio);
-                       r = DM_MAPIO_SUBMITTED;
-               } else {
-                       remap(tc, bio, result.block);
-                       r = DM_MAPIO_REMAPPED;
+                       return DM_MAPIO_SUBMITTED;
                }
-               break;
+
+               build_virtual_key(tc->td, block, &key);
+               if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1))
+                       return DM_MAPIO_SUBMITTED;
+
+               build_data_key(tc->td, result.block, &key);
+               if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2)) {
+                       cell_defer_no_holder(tc, cell1);
+                       return DM_MAPIO_SUBMITTED;
+               }
+
+               inc_all_io_entry(tc->pool, bio);
+               cell_defer_no_holder(tc, cell2);
+               cell_defer_no_holder(tc, cell1);
+
+               remap(tc, bio, result.block);
+               return DM_MAPIO_REMAPPED;
 
        case -ENODATA:
                if (get_pool_mode(tc->pool) == PM_READ_ONLY) {
@@ -1414,8 +1443,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
                         * of doing so.  Just error it.
                         */
                        bio_io_error(bio);
-                       r = DM_MAPIO_SUBMITTED;
-                       break;
+                       return DM_MAPIO_SUBMITTED;
                }
                /* fall through */
 
@@ -1425,8 +1453,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
                 * provide the hint to load the metadata into cache.
                 */
                thin_defer_bio(tc, bio);
-               r = DM_MAPIO_SUBMITTED;
-               break;
+               return DM_MAPIO_SUBMITTED;
 
        default:
                /*
@@ -1435,11 +1462,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
                 * pool is switched to fail-io mode.
                 */
                bio_io_error(bio);
-               r = DM_MAPIO_SUBMITTED;
-               break;
+               return DM_MAPIO_SUBMITTED;
        }
-
-       return r;
 }
 
 static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
@@ -1566,14 +1590,12 @@ static void __pool_destroy(struct pool *pool)
        if (pool->next_mapping)
                mempool_free(pool->next_mapping, pool->mapping_pool);
        mempool_destroy(pool->mapping_pool);
-       mempool_destroy(pool->endio_hook_pool);
        dm_deferred_set_destroy(pool->shared_read_ds);
        dm_deferred_set_destroy(pool->all_io_ds);
        kfree(pool);
 }
 
 static struct kmem_cache *_new_mapping_cache;
-static struct kmem_cache *_endio_hook_cache;
 
 static struct pool *pool_create(struct mapped_device *pool_md,
                                struct block_device *metadata_dev,
@@ -1667,13 +1689,6 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                goto bad_mapping_pool;
        }
 
-       pool->endio_hook_pool = mempool_create_slab_pool(ENDIO_HOOK_POOL_SIZE,
-                                                        _endio_hook_cache);
-       if (!pool->endio_hook_pool) {
-               *error = "Error creating pool's endio_hook mempool";
-               err_p = ERR_PTR(-ENOMEM);
-               goto bad_endio_hook_pool;
-       }
        pool->ref_count = 1;
        pool->last_commit_jiffies = jiffies;
        pool->pool_md = pool_md;
@@ -1682,8 +1697,6 @@ static struct pool *pool_create(struct mapped_device *pool_md,
 
        return pool;
 
-bad_endio_hook_pool:
-       mempool_destroy(pool->mapping_pool);
 bad_mapping_pool:
        dm_deferred_set_destroy(pool->all_io_ds);
 bad_all_io_ds:
@@ -1966,8 +1979,7 @@ out_unlock:
        return r;
 }
 
-static int pool_map(struct dm_target *ti, struct bio *bio,
-                   union map_info *map_context)
+static int pool_map(struct dm_target *ti, struct bio *bio)
 {
        int r;
        struct pool_c *pt = ti->private;
@@ -2358,7 +2370,9 @@ static int pool_status(struct dm_target *ti, status_type_t type,
                else
                        DMEMIT("rw ");
 
-               if (pool->pf.discard_enabled && pool->pf.discard_passdown)
+               if (!pool->pf.discard_enabled)
+                       DMEMIT("ignore_discard");
+               else if (pool->pf.discard_passdown)
                        DMEMIT("discard_passdown");
                else
                        DMEMIT("no_discard_passdown");
@@ -2454,7 +2468,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 5, 0},
+       .version = {1, 6, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2576,6 +2590,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        ti->num_flush_requests = 1;
        ti->flush_supported = true;
+       ti->per_bio_data_size = sizeof(struct dm_thin_endio_hook);
 
        /* In case the pool supports discards, pass them on. */
        if (tc->pool->pf.discard_enabled) {
@@ -2609,20 +2624,17 @@ out_unlock:
        return r;
 }
 
-static int thin_map(struct dm_target *ti, struct bio *bio,
-                   union map_info *map_context)
+static int thin_map(struct dm_target *ti, struct bio *bio)
 {
        bio->bi_sector = dm_target_offset(ti, bio->bi_sector);
 
-       return thin_bio_map(ti, bio, map_context);
+       return thin_bio_map(ti, bio);
 }
 
-static int thin_endio(struct dm_target *ti,
-                     struct bio *bio, int err,
-                     union map_info *map_context)
+static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
 {
        unsigned long flags;
-       struct dm_thin_endio_hook *h = map_context->ptr;
+       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
        struct list_head work;
        struct dm_thin_new_mapping *m, *tmp;
        struct pool *pool = h->tc->pool;
@@ -2643,14 +2655,15 @@ static int thin_endio(struct dm_target *ti,
        if (h->all_io_entry) {
                INIT_LIST_HEAD(&work);
                dm_deferred_entry_dec(h->all_io_entry, &work);
-               spin_lock_irqsave(&pool->lock, flags);
-               list_for_each_entry_safe(m, tmp, &work, list)
-                       list_add(&m->list, &pool->prepared_discards);
-               spin_unlock_irqrestore(&pool->lock, flags);
+               if (!list_empty(&work)) {
+                       spin_lock_irqsave(&pool->lock, flags);
+                       list_for_each_entry_safe(m, tmp, &work, list)
+                               list_add(&m->list, &pool->prepared_discards);
+                       spin_unlock_irqrestore(&pool->lock, flags);
+                       wake_worker(pool);
+               }
        }
 
-       mempool_free(h, pool->endio_hook_pool);
-
        return 0;
 }
 
@@ -2733,19 +2746,9 @@ static int thin_iterate_devices(struct dm_target *ti,
        return 0;
 }
 
-/*
- * A thin device always inherits its queue limits from its pool.
- */
-static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
-{
-       struct thin_c *tc = ti->private;
-
-       *limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
-}
-
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 5, 0},
+       .version = {1, 7, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
@@ -2754,7 +2757,6 @@ static struct target_type thin_target = {
        .postsuspend = thin_postsuspend,
        .status = thin_status,
        .iterate_devices = thin_iterate_devices,
-       .io_hints = thin_io_hints,
 };
 
 /*----------------------------------------------------------------*/
@@ -2779,14 +2781,8 @@ static int __init dm_thin_init(void)
        if (!_new_mapping_cache)
                goto bad_new_mapping_cache;
 
-       _endio_hook_cache = KMEM_CACHE(dm_thin_endio_hook, 0);
-       if (!_endio_hook_cache)
-               goto bad_endio_hook_cache;
-
        return 0;
 
-bad_endio_hook_cache:
-       kmem_cache_destroy(_new_mapping_cache);
 bad_new_mapping_cache:
        dm_unregister_target(&pool_target);
 bad_pool_target:
@@ -2801,7 +2797,6 @@ static void dm_thin_exit(void)
        dm_unregister_target(&pool_target);
 
        kmem_cache_destroy(_new_mapping_cache);
-       kmem_cache_destroy(_endio_hook_cache);
 }
 
 module_init(dm_thin_init);
index 9e7328bb40301e83a402e79173f84f1022b14159..52cde982164a580dcd6216866beccc693fcc4865 100644 (file)
@@ -55,7 +55,6 @@ struct dm_verity {
        unsigned shash_descsize;/* the size of temporary space for crypto */
        int hash_failed;        /* set to 1 if hash of any block failed */
 
-       mempool_t *io_mempool;  /* mempool of struct dm_verity_io */
        mempool_t *vec_mempool; /* mempool of bio vector */
 
        struct workqueue_struct *verify_wq;
@@ -66,7 +65,6 @@ struct dm_verity {
 
 struct dm_verity_io {
        struct dm_verity *v;
-       struct bio *bio;
 
        /* original values of bio->bi_end_io and bio->bi_private */
        bio_end_io_t *orig_bi_end_io;
@@ -389,8 +387,8 @@ test_block_hash:
  */
 static void verity_finish_io(struct dm_verity_io *io, int error)
 {
-       struct bio *bio = io->bio;
        struct dm_verity *v = io->v;
+       struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_bio_data_size);
 
        bio->bi_end_io = io->orig_bi_end_io;
        bio->bi_private = io->orig_bi_private;
@@ -398,8 +396,6 @@ static void verity_finish_io(struct dm_verity_io *io, int error)
        if (io->io_vec != io->io_vec_inline)
                mempool_free(io->io_vec, v->vec_mempool);
 
-       mempool_free(io, v->io_mempool);
-
        bio_endio(bio, error);
 }
 
@@ -462,8 +458,7 @@ no_prefetch_cluster:
  * Bio map function. It allocates dm_verity_io structure and bio vector and
  * fills them. Then it issues prefetches and the I/O.
  */
-static int verity_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int verity_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_verity *v = ti->private;
        struct dm_verity_io *io;
@@ -486,9 +481,8 @@ static int verity_map(struct dm_target *ti, struct bio *bio,
        if (bio_data_dir(bio) == WRITE)
                return -EIO;
 
-       io = mempool_alloc(v->io_mempool, GFP_NOIO);
+       io = dm_per_bio_data(bio, ti->per_bio_data_size);
        io->v = v;
-       io->bio = bio;
        io->orig_bi_end_io = bio->bi_end_io;
        io->orig_bi_private = bio->bi_private;
        io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
@@ -610,9 +604,6 @@ static void verity_dtr(struct dm_target *ti)
        if (v->vec_mempool)
                mempool_destroy(v->vec_mempool);
 
-       if (v->io_mempool)
-               mempool_destroy(v->io_mempool);
-
        if (v->bufio)
                dm_bufio_client_destroy(v->bufio);
 
@@ -841,13 +832,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto bad;
        }
 
-       v->io_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
-         sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2);
-       if (!v->io_mempool) {
-               ti->error = "Cannot allocate io mempool";
-               r = -ENOMEM;
-               goto bad;
-       }
+       ti->per_bio_data_size = roundup(sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2, __alignof__(struct dm_verity_io));
 
        v->vec_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
                                        BIO_MAX_PAGES * sizeof(struct bio_vec));
@@ -875,7 +860,7 @@ bad:
 
 static struct target_type verity_target = {
        .name           = "verity",
-       .version        = {1, 0, 0},
+       .version        = {1, 1, 0},
        .module         = THIS_MODULE,
        .ctr            = verity_ctr,
        .dtr            = verity_dtr,
index cc2b3cb819465c4f6becb14897d998ebfb976572..69a5c3b3b340cad4e58997955c13c8b56c7135de 100644 (file)
@@ -33,8 +33,7 @@ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 /*
  * Return zeros only on reads
  */
-static int zero_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int zero_map(struct dm_target *ti, struct bio *bio)
 {
        switch(bio_rw(bio)) {
        case READ:
@@ -56,7 +55,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio,
 
 static struct target_type zero_target = {
        .name   = "zero",
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr    = zero_ctr,
        .map    = zero_map,
index 77e6eff41cae9bb7c693aac363c509f65c44251d..314a0e2faf79d6c097e7c1201bf25af8600baaf6 100644 (file)
@@ -62,18 +62,6 @@ struct dm_io {
        spinlock_t endio_lock;
 };
 
-/*
- * For bio-based dm.
- * One of these is allocated per target within a bio.  Hopefully
- * this will be simplified out one day.
- */
-struct dm_target_io {
-       struct dm_io *io;
-       struct dm_target *ti;
-       union map_info info;
-       struct bio clone;
-};
-
 /*
  * For request-based dm.
  * One of these is allocated per request.
@@ -657,7 +645,7 @@ static void clone_endio(struct bio *bio, int error)
                error = -EIO;
 
        if (endio) {
-               r = endio(tio->ti, bio, error, &tio->info);
+               r = endio(tio->ti, bio, error);
                if (r < 0 || r == DM_ENDIO_REQUEUE)
                        /*
                         * error and requeue request are handled
@@ -1016,7 +1004,7 @@ static void __map_bio(struct dm_target *ti, struct dm_target_io *tio)
         */
        atomic_inc(&tio->io->io_count);
        sector = clone->bi_sector;
-       r = ti->type->map(ti, clone, &tio->info);
+       r = ti->type->map(ti, clone);
        if (r == DM_MAPIO_REMAPPED) {
                /* the bio has been remapped so dispatch it */
 
@@ -1111,6 +1099,7 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci,
        tio->io = ci->io;
        tio->ti = ti;
        memset(&tio->info, 0, sizeof(tio->info));
+       tio->target_request_nr = 0;
 
        return tio;
 }
@@ -1121,7 +1110,7 @@ static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
        struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs);
        struct bio *clone = &tio->clone;
 
-       tio->info.target_request_nr = request_nr;
+       tio->target_request_nr = request_nr;
 
        /*
         * Discard requests require the bio's inline iovecs be initialized.
@@ -1174,10 +1163,32 @@ static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti)
        ci->sector_count = 0;
 }
 
-static int __clone_and_map_discard(struct clone_info *ci)
+typedef unsigned (*get_num_requests_fn)(struct dm_target *ti);
+
+static unsigned get_num_discard_requests(struct dm_target *ti)
+{
+       return ti->num_discard_requests;
+}
+
+static unsigned get_num_write_same_requests(struct dm_target *ti)
+{
+       return ti->num_write_same_requests;
+}
+
+typedef bool (*is_split_required_fn)(struct dm_target *ti);
+
+static bool is_split_required_for_discard(struct dm_target *ti)
+{
+       return ti->split_discard_requests;
+}
+
+static int __clone_and_map_changing_extent_only(struct clone_info *ci,
+                                               get_num_requests_fn get_num_requests,
+                                               is_split_required_fn is_split_required)
 {
        struct dm_target *ti;
        sector_t len;
+       unsigned num_requests;
 
        do {
                ti = dm_table_find_target(ci->map, ci->sector);
@@ -1185,20 +1196,21 @@ static int __clone_and_map_discard(struct clone_info *ci)
                        return -EIO;
 
                /*
-                * Even though the device advertised discard support,
-                * that does not mean every target supports it, and
+                * Even though the device advertised support for this type of
+                * request, that does not mean every target supports it, and
                 * reconfiguration might also have changed that since the
                 * check was performed.
                 */
-               if (!ti->num_discard_requests)
+               num_requests = get_num_requests ? get_num_requests(ti) : 0;
+               if (!num_requests)
                        return -EOPNOTSUPP;
 
-               if (!ti->split_discard_requests)
+               if (is_split_required && !is_split_required(ti))
                        len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti));
                else
                        len = min(ci->sector_count, max_io_len(ci->sector, ti));
 
-               __issue_target_requests(ci, ti, ti->num_discard_requests, len);
+               __issue_target_requests(ci, ti, num_requests, len);
 
                ci->sector += len;
        } while (ci->sector_count -= len);
@@ -1206,6 +1218,17 @@ static int __clone_and_map_discard(struct clone_info *ci)
        return 0;
 }
 
+static int __clone_and_map_discard(struct clone_info *ci)
+{
+       return __clone_and_map_changing_extent_only(ci, get_num_discard_requests,
+                                                   is_split_required_for_discard);
+}
+
+static int __clone_and_map_write_same(struct clone_info *ci)
+{
+       return __clone_and_map_changing_extent_only(ci, get_num_write_same_requests, NULL);
+}
+
 static int __clone_and_map(struct clone_info *ci)
 {
        struct bio *bio = ci->bio;
@@ -1215,6 +1238,8 @@ static int __clone_and_map(struct clone_info *ci)
 
        if (unlikely(bio->bi_rw & REQ_DISCARD))
                return __clone_and_map_discard(ci);
+       else if (unlikely(bio->bi_rw & REQ_WRITE_SAME))
+               return __clone_and_map_write_same(ci);
 
        ti = dm_table_find_target(ci->map, ci->sector);
        if (!dm_target_is_valid(ti))
@@ -1946,13 +1971,20 @@ static void free_dev(struct mapped_device *md)
 
 static void __bind_mempools(struct mapped_device *md, struct dm_table *t)
 {
-       struct dm_md_mempools *p;
+       struct dm_md_mempools *p = dm_table_get_md_mempools(t);
 
-       if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs)
-               /* the md already has necessary mempools */
+       if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) {
+               /*
+                * The md already has necessary mempools. Reload just the
+                * bioset because front_pad may have changed because
+                * a different table was loaded.
+                */
+               bioset_free(md->bs);
+               md->bs = p->bs;
+               p->bs = NULL;
                goto out;
+       }
 
-       p = dm_table_get_md_mempools(t);
        BUG_ON(!p || md->io_pool || md->tio_pool || md->bs);
 
        md->io_pool = p->io_pool;
@@ -2711,7 +2743,7 @@ int dm_noflush_suspending(struct dm_target *ti)
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);
 
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size)
 {
        struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL);
        unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS;
@@ -2719,6 +2751,8 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
        if (!pools)
                return NULL;
 
+       per_bio_data_size = roundup(per_bio_data_size, __alignof__(struct dm_target_io));
+
        pools->io_pool = (type == DM_TYPE_BIO_BASED) ?
                         mempool_create_slab_pool(MIN_IOS, _io_cache) :
                         mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache);
@@ -2734,7 +2768,7 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
 
        pools->bs = (type == DM_TYPE_BIO_BASED) ?
                bioset_create(pool_size,
-                             offsetof(struct dm_target_io, clone)) :
+                             per_bio_data_size + offsetof(struct dm_target_io, clone)) :
                bioset_create(pool_size,
                              offsetof(struct dm_rq_clone_bio_info, clone));
        if (!pools->bs)
index 6a99fefaa74306aa6e586c47c3eacf33706556b1..45b97da1bd061f02a32e0e7523fdf5125ffb1089 100644 (file)
@@ -159,7 +159,7 @@ void dm_kcopyd_exit(void);
 /*
  * Mempool operations
  */
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity);
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size);
 void dm_free_md_mempools(struct dm_md_mempools *pools);
 
 #endif
index a3ae09124a67f786c19f1e426c12ca77a06c3963..28c3ed072a7943752e90446a1a110776c2928fec 100644 (file)
@@ -428,15 +428,17 @@ static int dm_bm_validate_buffer(struct dm_block_manager *bm,
                if (!v)
                        return 0;
                r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio));
-               if (unlikely(r))
+               if (unlikely(r)) {
+                       DMERR_LIMIT("%s validator check failed for block %llu", v->name,
+                                   (unsigned long long) dm_bufio_get_block_number(buf));
                        return r;
+               }
                aux->validator = v;
        } else {
                if (unlikely(aux->validator != v)) {
-                       DMERR("validator mismatch (old=%s vs new=%s) for block %llu",
-                               aux->validator->name, v ? v->name : "NULL",
-                               (unsigned long long)
-                                       dm_bufio_get_block_number(buf));
+                       DMERR_LIMIT("validator mismatch (old=%s vs new=%s) for block %llu",
+                                   aux->validator->name, v ? v->name : "NULL",
+                                   (unsigned long long) dm_bufio_get_block_number(buf));
                        return -EINVAL;
                }
        }
index 5709bfeab1e8fb29af17ba7a66dc78a9432d86a2..accbb05f17b628456231d94e8a4a880862f980dd 100644 (file)
@@ -36,13 +36,13 @@ struct node_header {
        __le32 padding;
 } __packed;
 
-struct node {
+struct btree_node {
        struct node_header header;
        __le64 keys[0];
 } __packed;
 
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt);
 
 int new_block(struct dm_btree_info *info, struct dm_block **result);
@@ -64,7 +64,7 @@ struct ro_spine {
 void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
 int exit_ro_spine(struct ro_spine *s);
 int ro_step(struct ro_spine *s, dm_block_t new_child);
-struct node *ro_node(struct ro_spine *s);
+struct btree_node *ro_node(struct ro_spine *s);
 
 struct shadow_spine {
        struct dm_btree_info *info;
@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s);
 /*
  * Some inlines.
  */
-static inline __le64 *key_ptr(struct node *n, uint32_t index)
+static inline __le64 *key_ptr(struct btree_node *n, uint32_t index)
 {
        return n->keys + index;
 }
 
-static inline void *value_base(struct node *n)
+static inline void *value_base(struct btree_node *n)
 {
        return &n->keys[le32_to_cpu(n->header.max_entries)];
 }
 
-static inline void *value_ptr(struct node *n, uint32_t index)
+static inline void *value_ptr(struct btree_node *n, uint32_t index)
 {
        uint32_t value_size = le32_to_cpu(n->header.value_size);
        return value_base(n) + (value_size * index);
@@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index)
 /*
  * Assumes the values are suitably-aligned and converts to core format.
  */
-static inline uint64_t value64(struct node *n, uint32_t index)
+static inline uint64_t value64(struct btree_node *n, uint32_t index)
 {
        __le64 *values_le = value_base(n);
 
@@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index)
 /*
  * Searching for a key within a single node.
  */
-int lower_bound(struct node *n, uint64_t key);
+int lower_bound(struct btree_node *n, uint64_t key);
 
 extern struct dm_block_validator btree_node_validator;
 
index aa71e2359a0704050b0b61054d4faa21bac10b53..c4f28133ef829340d966393f7e6d9eba6857111d 100644 (file)
@@ -53,7 +53,7 @@
 /*
  * Some little utilities for moving node data around.
  */
-static void node_shift(struct node *n, int shift)
+static void node_shift(struct btree_node *n, int shift)
 {
        uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
        uint32_t value_size = le32_to_cpu(n->header.value_size);
@@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift)
        }
 }
 
-static void node_copy(struct node *left, struct node *right, int shift)
+static void node_copy(struct btree_node *left, struct btree_node *right, int shift)
 {
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t value_size = le32_to_cpu(left->header.value_size);
@@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift)
 /*
  * Delete a specific entry from a leaf node.
  */
-static void delete_at(struct node *n, unsigned index)
+static void delete_at(struct btree_node *n, unsigned index)
 {
        unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
        unsigned nr_to_copy = nr_entries - (index + 1);
@@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index)
        n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned merge_threshold(struct node *n)
+static unsigned merge_threshold(struct btree_node *n)
 {
        return le32_to_cpu(n->header.max_entries) / 3;
 }
@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n)
 struct child {
        unsigned index;
        struct dm_block *block;
-       struct node *n;
+       struct btree_node *n;
 };
 
 static struct dm_btree_value_type le64_type = {
@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = {
        .equal = NULL
 };
 
-static int init_child(struct dm_btree_info *info, struct node *parent,
+static int init_child(struct dm_btree_info *info, struct btree_node *parent,
                      unsigned index, struct child *result)
 {
        int r, inc;
@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c)
        return dm_tm_unlock(info->tm, c->block);
 }
 
-static void shift(struct node *left, struct node *right, int count)
+static void shift(struct btree_node *left, struct btree_node *right, int count)
 {
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
@@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count)
        right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
-static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
                         struct child *l, struct child *r)
 {
-       struct node *left = l->n;
-       struct node *right = r->n;
+       struct btree_node *left = l->n;
+       struct btree_node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
        unsigned threshold = 2 * merge_threshold(left) + 1;
@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
                      unsigned left_index)
 {
        int r;
-       struct node *parent;
+       struct btree_node *parent;
        struct child left, right;
 
        parent = dm_block_data(shadow_current(s));
@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
  * in right, then rebalance2.  This wastes some cpu, but I want something
  * simple atm.
  */
-static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent,
                               struct child *l, struct child *c, struct child *r,
-                              struct node *left, struct node *center, struct node *right,
+                              struct btree_node *left, struct btree_node *center, struct btree_node *right,
                               uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
        uint32_t max_entries = le32_to_cpu(left->header.max_entries);
@@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent,
 /*
  * Redistributes entries among 3 sibling nodes.
  */
-static void redistribute3(struct dm_btree_info *info, struct node *parent,
+static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                          struct child *l, struct child *c, struct child *r,
-                         struct node *left, struct node *center, struct node *right,
+                         struct btree_node *left, struct btree_node *center, struct btree_node *right,
                          uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
        int s;
@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent,
        *key_ptr(parent, r->index) = right->keys[0];
 }
 
-static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
                         struct child *l, struct child *c, struct child *r)
 {
-       struct node *left = l->n;
-       struct node *center = c->n;
-       struct node *right = r->n;
+       struct btree_node *left = l->n;
+       struct btree_node *center = c->n;
+       struct btree_node *right = r->n;
 
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
                      unsigned left_index)
 {
        int r;
-       struct node *parent = dm_block_data(shadow_current(s));
+       struct btree_node *parent = dm_block_data(shadow_current(s));
        struct child left, center, right;
 
        /*
@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm,
 {
        int r;
        struct dm_block *block;
-       struct node *n;
+       struct btree_node *n;
 
        r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
        if (r)
@@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s,
 {
        int i, r, has_left_sibling, has_right_sibling;
        uint32_t child_entries;
-       struct node *n;
+       struct btree_node *n;
 
        n = dm_block_data(shadow_current(s));
 
@@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s,
        return r;
 }
 
-static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
 {
        int i = lower_bound(n, key);
 
@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
                      uint64_t key, unsigned *index)
 {
        int i = *index, r;
-       struct node *n;
+       struct btree_node *n;
 
        for (;;) {
                r = shadow_step(s, root, vt);
@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
        unsigned level, last_level = info->levels - 1;
        int index = 0, r = 0;
        struct shadow_spine spine;
-       struct node *n;
+       struct btree_node *n;
 
        init_shadow_spine(&spine, info);
        for (level = 0; level < info->levels; level++) {
index d9a7912ee8ee67be0bd127fc797076f493e6cc8c..f199a0c4ed04ad2cbb263c73c9f61be6e69b46b5 100644 (file)
@@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v,
                                   struct dm_block *b,
                                   size_t block_size)
 {
-       struct node *n = dm_block_data(b);
+       struct btree_node *n = dm_block_data(b);
        struct node_header *h = &n->header;
 
        h->blocknr = cpu_to_le64(dm_block_location(b));
@@ -38,15 +38,15 @@ static int node_check(struct dm_block_validator *v,
                      struct dm_block *b,
                      size_t block_size)
 {
-       struct node *n = dm_block_data(b);
+       struct btree_node *n = dm_block_data(b);
        struct node_header *h = &n->header;
        size_t value_size;
        __le32 csum_disk;
        uint32_t flags;
 
        if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
-               DMERR("node_check failed blocknr %llu wanted %llu",
-                     le64_to_cpu(h->blocknr), dm_block_location(b));
+               DMERR_LIMIT("node_check failed: blocknr %llu != wanted %llu",
+                           le64_to_cpu(h->blocknr), dm_block_location(b));
                return -ENOTBLK;
        }
 
@@ -54,8 +54,8 @@ static int node_check(struct dm_block_validator *v,
                                               block_size - sizeof(__le32),
                                               BTREE_CSUM_XOR));
        if (csum_disk != h->csum) {
-               DMERR("node_check failed csum %u wanted %u",
-                     le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
+               DMERR_LIMIT("node_check failed: csum %u != wanted %u",
+                           le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
                return -EILSEQ;
        }
 
@@ -63,12 +63,12 @@ static int node_check(struct dm_block_validator *v,
 
        if (sizeof(struct node_header) +
            (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
-               DMERR("node_check failed: max_entries too large");
+               DMERR_LIMIT("node_check failed: max_entries too large");
                return -EILSEQ;
        }
 
        if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
-               DMERR("node_check failed, too many entries");
+               DMERR_LIMIT("node_check failed: too many entries");
                return -EILSEQ;
        }
 
@@ -77,7 +77,7 @@ static int node_check(struct dm_block_validator *v,
         */
        flags = le32_to_cpu(h->flags);
        if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
-               DMERR("node_check failed, node is neither INTERNAL or LEAF");
+               DMERR_LIMIT("node_check failed: node is neither INTERNAL or LEAF");
                return -EILSEQ;
        }
 
@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
        return r;
 }
 
-struct node *ro_node(struct ro_spine *s)
+struct btree_node *ro_node(struct ro_spine *s)
 {
        struct dm_block *block;
 
index d12b2cc51f1a37711586fe6d13f6261f0b56c1be..4caf66918cdb35249544fdf296dd07d2594ae63a 100644 (file)
@@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
 /*----------------------------------------------------------------*/
 
 /* makes the assumption that no two keys are the same. */
-static int bsearch(struct node *n, uint64_t key, int want_hi)
+static int bsearch(struct btree_node *n, uint64_t key, int want_hi)
 {
        int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
 
@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi)
        return want_hi ? hi : lo;
 }
 
-int lower_bound(struct node *n, uint64_t key)
+int lower_bound(struct btree_node *n, uint64_t key)
 {
        return bsearch(n, key, 0);
 }
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt)
 {
        unsigned i;
@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n,
                        vt->inc(vt->context, value_ptr(n, i));
 }
 
-static int insert_at(size_t value_size, struct node *node, unsigned index,
+static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
                      uint64_t key, void *value)
                      __dm_written_to_disk(value)
 {
@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
 {
        int r;
        struct dm_block *b;
-       struct node *n;
+       struct btree_node *n;
        size_t block_size;
        uint32_t max_entries;
 
@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty);
 #define MAX_SPINE_DEPTH 64
 struct frame {
        struct dm_block *b;
-       struct node *n;
+       struct btree_node *n;
        unsigned level;
        unsigned nr_children;
        unsigned current_child;
@@ -230,6 +230,11 @@ static void pop_frame(struct del_stack *s)
        dm_tm_unlock(s->tm, f->b);
 }
 
+static bool is_internal_level(struct dm_btree_info *info, struct frame *f)
+{
+       return f->level < (info->levels - 1);
+}
+
 int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
 {
        int r;
@@ -241,7 +246,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
        s->tm = info->tm;
        s->top = -1;
 
-       r = push_frame(s, root, 1);
+       r = push_frame(s, root, 0);
        if (r)
                goto out;
 
@@ -267,7 +272,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
                        if (r)
                                goto out;
 
-               } else if (f->level != (info->levels - 1)) {
+               } else if (is_internal_level(info, f)) {
                        b = value64(f->n, f->current_child);
                        f->current_child++;
                        r = push_frame(s, b, f->level + 1);
@@ -295,7 +300,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del);
 /*----------------------------------------------------------------*/
 
 static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
-                           int (*search_fn)(struct node *, uint64_t),
+                           int (*search_fn)(struct btree_node *, uint64_t),
                            uint64_t *result_key, void *v, size_t value_size)
 {
        int i, r;
@@ -406,7 +411,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
        size_t size;
        unsigned nr_left, nr_right;
        struct dm_block *left, *right, *parent;
-       struct node *ln, *rn, *pn;
+       struct btree_node *ln, *rn, *pn;
        __le64 location;
 
        left = shadow_current(s);
@@ -491,7 +496,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
        size_t size;
        unsigned nr_left, nr_right;
        struct dm_block *left, *right, *new_parent;
-       struct node *pn, *ln, *rn;
+       struct btree_node *pn, *ln, *rn;
        __le64 val;
 
        new_parent = shadow_current(s);
@@ -576,7 +581,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
                            uint64_t key, unsigned *index)
 {
        int r, i = *index, top = 1;
-       struct node *node;
+       struct btree_node *node;
 
        for (;;) {
                r = shadow_step(s, root, vt);
@@ -643,7 +648,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
        unsigned level, index = -1, last_level = info->levels - 1;
        dm_block_t block = root;
        struct shadow_spine spine;
-       struct node *n;
+       struct btree_node *n;
        struct dm_btree_value_type le64_type;
 
        le64_type.context = NULL;
index f3a9af8cdec3514448ae3f6ce9cb12ecca7f20ae..3e7a88d99eb0260ce4e9128f94349713b28170c5 100644 (file)
@@ -39,8 +39,8 @@ static int index_check(struct dm_block_validator *v,
        __le32 csum_disk;
 
        if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
-               DMERR("index_check failed blocknr %llu wanted %llu",
-                     le64_to_cpu(mi_le->blocknr), dm_block_location(b));
+               DMERR_LIMIT("index_check failed: blocknr %llu != wanted %llu",
+                           le64_to_cpu(mi_le->blocknr), dm_block_location(b));
                return -ENOTBLK;
        }
 
@@ -48,8 +48,8 @@ static int index_check(struct dm_block_validator *v,
                                               block_size - sizeof(__le32),
                                               INDEX_CSUM_XOR));
        if (csum_disk != mi_le->csum) {
-               DMERR("index_check failed csum %u wanted %u",
-                     le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
+               DMERR_LIMIT("index_check failed: csum %u != wanted %u",
+                           le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
                return -EILSEQ;
        }
 
@@ -89,8 +89,8 @@ static int bitmap_check(struct dm_block_validator *v,
        __le32 csum_disk;
 
        if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
-               DMERR("bitmap check failed blocknr %llu wanted %llu",
-                     le64_to_cpu(disk_header->blocknr), dm_block_location(b));
+               DMERR_LIMIT("bitmap check failed: blocknr %llu != wanted %llu",
+                           le64_to_cpu(disk_header->blocknr), dm_block_location(b));
                return -ENOTBLK;
        }
 
@@ -98,8 +98,8 @@ static int bitmap_check(struct dm_block_validator *v,
                                               block_size - sizeof(__le32),
                                               BITMAP_CSUM_XOR));
        if (csum_disk != disk_header->csum) {
-               DMERR("bitmap check failed csum %u wanted %u",
-                     le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
+               DMERR_LIMIT("bitmap check failed: csum %u != wanted %u",
+                           le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
                return -EILSEQ;
        }
 
index e89ae5e7a51959dc5a8e9ce68c70295ba840abb6..906cf3df71af33365e460cbca0a82b0077fc6abf 100644 (file)
@@ -337,7 +337,7 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
 {
        int r = sm_metadata_new_block_(sm, b);
        if (r)
-               DMERR("out of metadata space");
+               DMERR("unable to allocate new metadata block");
        return r;
 }
 
index 49d95040096a42589627d7e3446df5f470c2f919..0223ad255cb4c7e1f3218aa5a0f5debb076963fd 100644 (file)
@@ -1820,7 +1820,7 @@ static int dvb_frontend_ioctl(struct file *file,
        struct dvb_frontend *fe = dvbdev->priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int err = -ENOTTY;
+       int err = -EOPNOTSUPP;
 
        dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd));
        if (fepriv->exit != DVB_FE_NO_EXIT)
@@ -1938,7 +1938,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                }
 
        } else
-               err = -ENOTTY;
+               err = -EOPNOTSUPP;
 
 out:
        kfree(tvp);
@@ -2071,7 +2071,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int err = -ENOTTY;
+       int err = -EOPNOTSUPP;
 
        switch (cmd) {
        case FE_GET_INFO: {
index 45ecf8db1eaecadbc6debf310d0d5313dd2bc185..64d71fb87a96acc7dcda6eddc9069f8561842fbc 100644 (file)
@@ -540,8 +540,8 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state)
        return 0;
 }
 
-static __devinit int adv7180_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
+static int adv7180_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct adv7180_state *state;
        struct v4l2_subdev *sd;
@@ -587,7 +587,7 @@ err:
        return ret;
 }
 
-static __devexit int adv7180_remove(struct i2c_client *client)
+static int adv7180_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct adv7180_state *state = to_state(sd);
@@ -652,7 +652,7 @@ static struct i2c_driver adv7180_driver = {
                   .name = KBUILD_MODNAME,
                   },
        .probe = adv7180_probe,
-       .remove = __devexit_p(adv7180_remove),
+       .remove = adv7180_remove,
 #ifdef CONFIG_PM
        .suspend = adv7180_suspend,
        .resume = adv7180_resume,
index 10c3c1db4cdd1a473232027c602de8b3513ecb58..6fed5b74e74302e6580e43422202b4cf1942ca9a 100644 (file)
@@ -677,7 +677,7 @@ static struct i2c_driver adv7183_driver = {
                .name   = "adv7183",
        },
        .probe          = adv7183_probe,
-       .remove         = __devexit_p(adv7183_remove),
+       .remove         = adv7183_remove,
        .id_table       = adv7183_id,
 };
 
index 3bfdbf9d9bf1b4accb9632dd2f831d64fe89c12f..58d523f2648f61894ff8ed98526fff077da79e91 100644 (file)
@@ -713,7 +713,7 @@ static int as3645a_resume(struct device *dev)
  * The number of LEDs reported in platform data is used to compute default
  * limits. Parameters passed through platform data can override those limits.
  */
-static int __devinit as3645a_init_controls(struct as3645a *flash)
+static int as3645a_init_controls(struct as3645a *flash)
 {
        const struct as3645a_platform_data *pdata = flash->pdata;
        struct v4l2_ctrl *ctrl;
@@ -804,8 +804,8 @@ static int __devinit as3645a_init_controls(struct as3645a *flash)
        return flash->ctrls.error;
 }
 
-static int __devinit as3645a_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *devid)
+static int as3645a_probe(struct i2c_client *client,
+                        const struct i2c_device_id *devid)
 {
        struct as3645a *flash;
        int ret;
@@ -846,7 +846,7 @@ done:
        return ret;
 }
 
-static int __devexit as3645a_remove(struct i2c_client *client)
+static int as3645a_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
        struct as3645a *flash = to_as3645a(subdev);
@@ -877,7 +877,7 @@ static struct i2c_driver as3645a_i2c_driver = {
                .pm   = &as3645a_pm_ops,
        },
        .probe  = as3645a_probe,
-       .remove = __devexit_p(as3645a_remove),
+       .remove = as3645a_remove,
        .id_table = as3645a_id_table,
 };
 
index 8131d651de9ef11ea5c10d8e4111e9c8e4468896..d4e7567b367c04d25b9a21ba4c50d0db314596aa 100644 (file)
@@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        mutex_lock(&info->lock);
 
        format = __find_format(info, fh, fmt->which, info->res_type);
-       if (!format)
+       if (format)
                fmt->format = *format;
        else
                ret = -EINVAL;
@@ -926,8 +926,8 @@ static irqreturn_t m5mols_irq_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit m5mols_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int m5mols_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        const struct m5mols_platform_data *pdata = client->dev.platform_data;
        struct m5mols_info *info;
@@ -1018,7 +1018,7 @@ out_free:
        return ret;
 }
 
-static int __devexit m5mols_remove(struct i2c_client *client)
+static int m5mols_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct m5mols_info *info = to_m5mols(sd);
@@ -1045,7 +1045,7 @@ static struct i2c_driver m5mols_i2c_driver = {
                .name   = MODULE_NAME,
        },
        .probe          = m5mols_probe,
-       .remove         = __devexit_p(m5mols_remove),
+       .remove         = m5mols_remove,
        .id_table       = m5mols_id,
 };
 
index f434a19b9bcbb43fcbdb4d9e48f240fe9d2ae372..9ac1b8c3a837c4c0a0e33c321b7978785ea51843 100644 (file)
@@ -788,7 +788,7 @@ static const struct v4l2_subdev_ops vs6624_ops = {
        .video = &vs6624_video_ops,
 };
 
-static int __devinit vs6624_probe(struct i2c_client *client,
+static int vs6624_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct vs6624 *sensor;
@@ -881,7 +881,7 @@ static int __devinit vs6624_probe(struct i2c_client *client,
        return ret;
 }
 
-static int __devexit vs6624_remove(struct i2c_client *client)
+static int vs6624_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct vs6624 *sensor = to_vs6624(sd);
@@ -906,7 +906,7 @@ static struct i2c_driver vs6624_driver = {
                .name   = "vs6624",
        },
        .probe          = vs6624_probe,
-       .remove         = __devexit_p(vs6624_remove),
+       .remove         = vs6624_remove,
        .id_table       = vs6624_id,
 };
 
index d6f3f100699ae13e2f3dfec60fc1455db34adb07..15d34935e00b217da1e5e5a29518644de75a45e1 100644 (file)
@@ -50,7 +50,7 @@
 #define SMSSDIO_INT            0x04
 #define SMSSDIO_BLOCK_SIZE     128
 
-static const struct sdio_device_id smssdio_ids[] __devinitconst = {
+static const struct sdio_device_id smssdio_ids[] = {
        {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
         .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
        {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
@@ -224,7 +224,7 @@ static void smssdio_interrupt(struct sdio_func *func)
        smscore_onresponse(smsdev->coredev, cb);
 }
 
-static int __devinit smssdio_probe(struct sdio_func *func,
+static int smssdio_probe(struct sdio_func *func,
                         const struct sdio_device_id *id)
 {
        int ret;
index b34fa95185e4ac65ac96200c8a800d46889504d8..66eb0baab0e9948cb4beeb88a1bac60e71c19821 100644 (file)
@@ -391,7 +391,7 @@ EXPORT_SYMBOL(bt878_device_control);
                .driver_data = (unsigned long) name \
        }
 
-static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
+static struct pci_device_id bt878_pci_tbl[] = {
        BROOKTREE_878_DEVICE(0x0071, 0x0101, "Nebula Electronics DigiTV"),
        BROOKTREE_878_DEVICE(0x1461, 0x0761, "AverMedia AverTV DVB-T 761"),
        BROOKTREE_878_DEVICE(0x11bd, 0x001c, "Pinnacle PCTV Sat"),
@@ -410,7 +410,7 @@ static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
 
-static const char * __devinit card_name(const struct pci_device_id *id)
+static const char * card_name(const struct pci_device_id *id)
 {
        return id->driver_data ? (const char *)id->driver_data : "Unknown";
 }
@@ -419,8 +419,7 @@ static const char * __devinit card_name(const struct pci_device_id *id)
 /* PCI device handling */
 /***********************/
 
-static int __devinit bt878_probe(struct pci_dev *dev,
-                                const struct pci_device_id *pci_id)
+static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 {
        int result = 0;
        unsigned char lat;
@@ -529,7 +528,7 @@ static int __devinit bt878_probe(struct pci_dev *dev,
        return result;
 }
 
-static void __devexit bt878_remove(struct pci_dev *pci_dev)
+static void bt878_remove(struct pci_dev *pci_dev)
 {
        u8 command;
        struct bt878 *bt = pci_get_drvdata(pci_dev);
@@ -573,7 +572,7 @@ static struct pci_driver bt878_pci_driver = {
       .name    = "bt878",
       .id_table = bt878_pci_tbl,
       .probe   = bt878_probe,
-      .remove  = __devexit_p(bt878_remove),
+      .remove  = bt878_remove,
 };
 
 /*******************************/
index 38952faaffda3a44ed81d7d268bc7c98306d3b64..c4c59175e52c6c526042ed5fdf332641740f2b82 100644 (file)
@@ -87,7 +87,7 @@ static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
 static void identify_by_eeprom(struct bttv *btv,
                               unsigned char eeprom_data[256]);
-static int __devinit pvr_boot(struct bttv *btv);
+static int pvr_boot(struct bttv *btv);
 
 /* config variables */
 static unsigned int triton1;
@@ -151,7 +151,7 @@ static struct CARD {
        unsigned id;
        int cardnr;
        char *name;
-} cards[] __devinitdata = {
+} cards[] = {
        { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV" },
        { 0x39000070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV-D" },
        { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR,  "Hauppauge WinTV/PVR" },
@@ -2837,7 +2837,7 @@ static unsigned char eeprom_data[256];
 /*
  * identify card
  */
-void __devinit bttv_idcard(struct bttv *btv)
+void bttv_idcard(struct bttv *btv)
 {
        unsigned int gpiobits;
        int i,type;
@@ -3235,7 +3235,7 @@ static void bttv_reset_audio(struct bttv *btv)
 }
 
 /* initialization part one -- before registering i2c bus */
-void __devinit bttv_init_card1(struct bttv *btv)
+void bttv_init_card1(struct bttv *btv)
 {
        switch (btv->c.type) {
        case BTTV_BOARD_HAUPPAUGE:
@@ -3267,7 +3267,7 @@ void __devinit bttv_init_card1(struct bttv *btv)
 }
 
 /* initialization part two -- after registering i2c bus */
-void __devinit bttv_init_card2(struct bttv *btv)
+void bttv_init_card2(struct bttv *btv)
 {
        btv->tuner_type = UNSET;
 
@@ -3571,7 +3571,7 @@ no_audio:
 
 
 /* initialize the tuner */
-void __devinit bttv_init_tuner(struct bttv *btv)
+void bttv_init_tuner(struct bttv *btv)
 {
        int addr = ADDR_UNSET;
 
@@ -3635,7 +3635,7 @@ static void modtec_eeprom(struct bttv *btv)
        }
 }
 
-static void __devinit hauppauge_eeprom(struct bttv *btv)
+static void hauppauge_eeprom(struct bttv *btv)
 {
        struct tveeprom tv;
 
@@ -3709,8 +3709,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
 #define BTTV_ALT_DCLK          0x100000
 #define BTTV_ALT_NCONFIG       0x800000
 
-static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
-                                    u32 microlen)
+static int pvr_altera_load(struct bttv *btv, const u8 *micro, u32 microlen)
 {
        u32 n;
        u8 bits;
@@ -3747,7 +3746,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
        return 0;
 }
 
-static int __devinit pvr_boot(struct bttv *btv)
+static int pvr_boot(struct bttv *btv)
 {
        const struct firmware *fw_entry;
        int rc;
@@ -3767,7 +3766,7 @@ static int __devinit pvr_boot(struct bttv *btv)
 /* ----------------------------------------------------------------------- */
 /* some osprey specific stuff                                              */
 
-static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
+static void osprey_eeprom(struct bttv *btv, const u8 ee[256])
 {
        int i;
        u32 serial = 0;
@@ -3898,7 +3897,7 @@ static int tuner_1_table[] = {
        TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
        TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
 
-static void __devinit avermedia_eeprom(struct bttv *btv)
+static void avermedia_eeprom(struct bttv *btv)
 {
        int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
 
@@ -3960,7 +3959,7 @@ u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
  * Hauppauge:  pin  5
  * Voodoo:     pin 20
  */
-static void __devinit boot_msp34xx(struct bttv *btv, int pin)
+static void boot_msp34xx(struct bttv *btv, int pin)
 {
        int mask = (1 << pin);
 
@@ -3983,11 +3982,10 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
  *  used by Alessandro Rubini in his pxc200
  *  driver, but using BTTV functions */
 
-static void __devinit init_PXC200(struct bttv *btv)
+static void init_PXC200(struct bttv *btv)
 {
-       static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
-                                           0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-                                           0x00 };
+       static int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, 0x01, 0x02,
+                             0x03, 0x04, 0x05, 0x06, 0x00 };
        unsigned int i;
        int tmp;
        u32 val;
@@ -4851,7 +4849,7 @@ void __init bttv_check_chipset(void)
        }
 }
 
-int __devinit bttv_handle_chipset(struct bttv *btv)
+int bttv_handle_chipset(struct bttv *btv)
 {
        unsigned char command;
 
index de6f41f19187dd584be669baadc0398910e71b2b..45e5d0661b605fdeea861506c538e42e27f0ce22 100644 (file)
@@ -4199,7 +4199,7 @@ static void bttv_unregister_video(struct bttv *btv)
 }
 
 /* register video4linux devices */
-static int __devinit bttv_register_video(struct bttv *btv)
+static int bttv_register_video(struct bttv *btv)
 {
        if (no_overlay > 0)
                pr_notice("Overlay support disabled\n");
@@ -4265,8 +4265,7 @@ static void pci_set_command(struct pci_dev *dev)
 #endif
 }
 
-static int __devinit bttv_probe(struct pci_dev *dev,
-                               const struct pci_device_id *pci_id)
+static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 {
        int result;
        unsigned char lat;
@@ -4454,7 +4453,7 @@ fail0:
        return result;
 }
 
-static void __devexit bttv_remove(struct pci_dev *pci_dev)
+static void bttv_remove(struct pci_dev *pci_dev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
        struct bttv *btv = to_bttv(v4l2_dev);
@@ -4598,7 +4597,7 @@ static struct pci_driver bttv_pci_driver = {
        .name     = "bttv",
        .id_table = bttv_pci_tbl,
        .probe    = bttv_probe,
-       .remove   = __devexit_p(bttv_remove),
+       .remove   = bttv_remove,
 #ifdef CONFIG_PM
        .suspend  = bttv_suspend,
        .resume   = bttv_resume,
index 580c8e682392c4c5524c789c8b21a75fbbe23314..5039b8826e0a9c08dac1db8eb20f008d9c75ce47 100644 (file)
@@ -99,7 +99,7 @@ static int bttv_bit_getsda(void *data)
        return state;
 }
 
-static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
+static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
        .setsda  = bttv_bit_setsda,
        .setscl  = bttv_bit_setscl,
        .getsda  = bttv_bit_getsda,
@@ -312,7 +312,7 @@ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
 }
 
 /* read EEPROM content */
-void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
+void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
 {
        memset(eedata, 0, 256);
        if (0 != btv->i2c_rc)
@@ -347,7 +347,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
 }
 
 /* init + register i2c adapter */
-int __devinit init_bttv_i2c(struct bttv *btv)
+int init_bttv_i2c(struct bttv *btv)
 {
        strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
 
index ef4c7cd419827f800f2073775923e042e73536a7..04207a7990557a763e9cd18eea252713dd8ff8ec 100644 (file)
@@ -368,7 +368,7 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 }
 
 /* Instantiate the I2C IR receiver device, if present */
-void __devinit init_bttv_i2c_ir(struct bttv *btv)
+void init_bttv_i2c_ir(struct bttv *btv)
 {
        const unsigned short addr_list[] = {
                0x1a, 0x18, 0x64, 0x30, 0x71,
@@ -411,7 +411,7 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv)
        return;
 }
 
-int __devexit fini_bttv_i2c(struct bttv *btv)
+int fini_bttv_i2c(struct bttv *btv)
 {
        if (0 != btv->i2c_rc)
                return 0;
index 81fab9adc1cad18de7d3f24420893fdc894f1994..d407244fd1bce3339b3fdbc13ea3e4801114f19a 100644 (file)
@@ -118,7 +118,8 @@ static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
        return 0;
 }
 
-static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
+static struct bt878 *dvb_bt8xx_878_match(unsigned int bttv_nr,
+                                        struct pci_dev* bttv_pci_dev)
 {
        unsigned int card_nr;
 
@@ -720,7 +721,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                }
 }
 
-static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
        int result;
 
@@ -811,7 +812,7 @@ err_unregister_adaptor:
        return result;
 }
 
-static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
+static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
 {
        struct dvb_bt8xx_card *card;
        struct pci_dev* bttv_pci_dev;
index 039133d692e34e0f839c1496ce13cb6b869b67d8..613e5ae7d5caed9da4c38cd60da171097460bb4c 100644 (file)
@@ -53,7 +53,7 @@ int (*cx18_ext_init)(struct cx18 *);
 EXPORT_SYMBOL(cx18_ext_init);
 
 /* add your revision and whatnot here */
-static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
+static struct pci_device_id cx18_pci_tbl[] = {
        {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {0,}
@@ -691,7 +691,7 @@ done:
        cx->card_i2c = cx->card->i2c;
 }
 
-static int __devinit cx18_create_in_workq(struct cx18 *cx)
+static int cx18_create_in_workq(struct cx18 *cx)
 {
        snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
                 cx->v4l2_dev.name);
@@ -703,7 +703,7 @@ static int __devinit cx18_create_in_workq(struct cx18 *cx)
        return 0;
 }
 
-static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
+static void cx18_init_in_work_orders(struct cx18 *cx)
 {
        int i;
        for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
@@ -718,7 +718,7 @@ static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
    No assumptions on the card type may be made here (see cx18_init_struct2
    for that).
  */
-static int __devinit cx18_init_struct1(struct cx18 *cx)
+static int cx18_init_struct1(struct cx18 *cx)
 {
        int ret;
 
@@ -775,7 +775,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
 
 /* Second initialization part. Here the card type has been
    autodetected. */
-static void __devinit cx18_init_struct2(struct cx18 *cx)
+static void cx18_init_struct2(struct cx18 *cx)
 {
        int i;
 
@@ -892,8 +892,8 @@ static void cx18_init_subdevs(struct cx18 *cx)
                cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer);
 }
 
-static int __devinit cx18_probe(struct pci_dev *pci_dev,
-                               const struct pci_device_id *pci_id)
+static int cx18_probe(struct pci_dev *pci_dev,
+                     const struct pci_device_id *pci_id)
 {
        int retval = 0;
        int i;
index 065ecd54bda3d6127b4ff0ab8e846c41924b3d96..f0416a668b4cf8f0ea75d25b124404aaffce1c3c 100644 (file)
@@ -2086,8 +2086,8 @@ void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
        /* TODO: 23-19 */
 }
 
-static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
+static int cx23885_initdev(struct pci_dev *pci_dev,
+                          const struct pci_device_id *pci_id)
 {
        struct cx23885_dev *dev;
        int err;
@@ -2167,7 +2167,7 @@ fail_free:
        return err;
 }
 
-static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
+static void cx23885_finidev(struct pci_dev *pci_dev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
        struct cx23885_dev *dev = to_cx23885(v4l2_dev);
@@ -2210,7 +2210,7 @@ static struct pci_driver cx23885_pci_driver = {
        .name     = "cx23885",
        .id_table = cx23885_pci_tbl,
        .probe    = cx23885_initdev,
-       .remove   = __devexit_p(cx23885_finidev),
+       .remove   = cx23885_finidev,
        /* TODO */
        .suspend  = NULL,
        .resume   = NULL,
index f11f6f07e9154cd4d00790031d3da5e63c1ec8d1..1884e2cc35e9426805e589f2e53cd024a3ceff6c 100644 (file)
@@ -1361,8 +1361,8 @@ struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
 }
 EXPORT_SYMBOL(cx25821_dev_get);
 
-static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
+static int cx25821_initdev(struct pci_dev *pci_dev,
+                          const struct pci_device_id *pci_id)
 {
        struct cx25821_dev *dev;
        int err = 0;
@@ -1433,7 +1433,7 @@ fail_free:
        return err;
 }
 
-static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+static void cx25821_finidev(struct pci_dev *pci_dev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
        struct cx25821_dev *dev = get_cx25821(v4l2_dev);
@@ -1478,7 +1478,7 @@ static struct pci_driver cx25821_pci_driver = {
        .name = "cx25821",
        .id_table = cx25821_pci_tbl,
        .probe = cx25821_initdev,
-       .remove = __devexit_p(cx25821_finidev),
+       .remove = cx25821_finidev,
        /* TODO */
        .suspend = NULL,
        .resume = NULL,
index d2de1a913e1978343937682689f2096320169f41..27d62623274bbd967fa56559f3ed617a0557c6ba 100644 (file)
@@ -540,7 +540,7 @@ static struct snd_pcm_ops snd_cx88_pcm_ops = {
 /*
  * create a PCM device
  */
-static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
+static int snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
 {
        int err;
        struct snd_pcm *pcm;
@@ -753,7 +753,7 @@ static struct snd_kcontrol_new snd_cx88_alc_switch = {
  * Only boards with eeprom and byte 1 at eeprom=1 have it
  */
 
-static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
+static const struct pci_device_id cx88_audio_pci_tbl[] = {
        {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
        {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
        {0, }
@@ -792,10 +792,9 @@ static void snd_cx88_dev_free(struct snd_card * card)
  */
 
 static int devno;
-static int __devinit snd_cx88_create(struct snd_card *card,
-                                    struct pci_dev *pci,
-                                    snd_cx88_card_t **rchip,
-                                    struct cx88_core **core_ptr)
+static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
+                          snd_cx88_card_t **rchip,
+                          struct cx88_core **core_ptr)
 {
        snd_cx88_card_t   *chip;
        struct cx88_core  *core;
@@ -862,8 +861,8 @@ static int __devinit snd_cx88_create(struct snd_card *card,
        return 0;
 }
 
-static int __devinit cx88_audio_initdev(struct pci_dev *pci,
-                                   const struct pci_device_id *pci_id)
+static int cx88_audio_initdev(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
 {
        struct snd_card  *card;
        snd_cx88_card_t  *chip;
@@ -931,7 +930,7 @@ error:
 /*
  * ALSA destructor
  */
-static void __devexit cx88_audio_finidev(struct pci_dev *pci)
+static void cx88_audio_finidev(struct pci_dev *pci)
 {
        struct cx88_audio_dev *card = pci_get_drvdata(pci);
 
@@ -950,7 +949,7 @@ static struct pci_driver cx88_audio_pci_driver = {
        .name     = "cx88_audio",
        .id_table = cx88_audio_pci_tbl,
        .probe    = cx88_audio_initdev,
-       .remove   = __devexit_p(cx88_audio_finidev),
+       .remove   = cx88_audio_finidev,
 };
 
 /****************************************************************************
index d46b008a46b86f4d2e2684cba33b650d2b12ff44..c9d3182f79d57a0a9fd26b321ca27fbf66c0a9ce 100644 (file)
@@ -791,8 +791,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
 }
 
 /* ----------------------------------------------------------- */
-static int __devinit cx8802_probe(struct pci_dev *pci_dev,
-                              const struct pci_device_id *pci_id)
+static int cx8802_probe(struct pci_dev *pci_dev,
+                       const struct pci_device_id *pci_id)
 {
        struct cx8802_dev *dev;
        struct cx88_core  *core;
@@ -840,7 +840,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
        return err;
 }
 
-static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+static void cx8802_remove(struct pci_dev *pci_dev)
 {
        struct cx8802_dev *dev;
 
@@ -898,7 +898,7 @@ static struct pci_driver cx8802_pci_driver = {
        .name     = "cx88-mpeg driver manager",
        .id_table = cx8802_pci_tbl,
        .probe    = cx8802_probe,
-       .remove   = __devexit_p(cx8802_remove),
+       .remove   = cx8802_remove,
 };
 
 static int __init cx8802_init(void)
index 05171457bf282e42c47dfe00c4410c33cde74518..bc78354262acae2dc90c877455c532a0120cd47a 100644 (file)
@@ -1696,8 +1696,8 @@ static void cx8800_unregister_video(struct cx8800_dev *dev)
        }
 }
 
-static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
-                                   const struct pci_device_id *pci_id)
+static int cx8800_initdev(struct pci_dev *pci_dev,
+                         const struct pci_device_id *pci_id)
 {
        struct cx8800_dev *dev;
        struct cx88_core *core;
@@ -1923,7 +1923,7 @@ fail_free:
        return err;
 }
 
-static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
+static void cx8800_finidev(struct pci_dev *pci_dev)
 {
        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
        struct cx88_core *core = dev->core;
@@ -2052,7 +2052,7 @@ static struct pci_driver cx8800_pci_driver = {
        .name     = "cx8800",
        .id_table = cx8800_pci_tbl,
        .probe    = cx8800_initdev,
-       .remove   = __devexit_p(cx8800_finidev),
+       .remove   = cx8800_finidev,
 #ifdef CONFIG_PM
        .suspend  = cx8800_suspend,
        .resume   = cx8800_resume,
index feff57ee5a083b55ec1c822b69807d4d1df84851..36e34522b9a80878b61e78ed10a5276f3e7b570f 100644 (file)
@@ -1542,7 +1542,7 @@ static void ddb_unmap(struct ddb *dev)
 }
 
 
-static void __devexit ddb_remove(struct pci_dev *pdev)
+static void ddb_remove(struct pci_dev *pdev)
 {
        struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
 
@@ -1565,8 +1565,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
 }
 
 
-static int __devinit ddb_probe(struct pci_dev *pdev,
-                              const struct pci_device_id *id)
+static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct ddb *dev;
        int stat = 0;
@@ -1679,7 +1678,7 @@ static struct ddb_info ddb_v6 = {
        .subvendor   = _subvend, .subdevice = _subdev, \
        .driver_data = (unsigned long)&_driverdata }
 
-static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
+static const struct pci_device_id ddb_id_tbl[] = {
        DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
        DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
        DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
@@ -1696,7 +1695,7 @@ static struct pci_driver ddb_pci_driver = {
        .name        = "DDBridge",
        .id_table    = ddb_id_tbl,
        .probe       = ddb_probe,
-       .remove      = __devexit_p(ddb_remove),
+       .remove      = ddb_remove,
 };
 
 static __init int module_init_ddbridge(void)
index f288ffcc4b6bb9004941d75830c2b90e393d2565..904c3ea350f5468a0161a70d2d3672f038662a8e 100644 (file)
@@ -616,7 +616,7 @@ static void dm1105_set_dma_addr(struct dm1105_dev *dev)
        dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr));
 }
 
-static int __devinit dm1105_dma_map(struct dm1105_dev *dev)
+static int dm1105_dma_map(struct dm1105_dev *dev)
 {
        dev->ts_buf = pci_alloc_consistent(dev->pdev,
                                        6 * DM1105_DMA_BYTES,
@@ -736,7 +736,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
+static int dm1105_ir_init(struct dm1105_dev *dm1105)
 {
        struct rc_dev *dev;
        int err = -ENOMEM;
@@ -776,12 +776,12 @@ static int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
        return 0;
 }
 
-static void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
+static void dm1105_ir_exit(struct dm1105_dev *dm1105)
 {
        rc_unregister_device(dm1105->ir.dev);
 }
 
-static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
+static int dm1105_hw_init(struct dm1105_dev *dev)
 {
        dm1105_disable_irqs(dev);
 
@@ -849,7 +849,7 @@ static struct ds3000_config dvbworld_ds3000_config = {
        .demod_address = 0x68,
 };
 
-static int __devinit frontend_init(struct dm1105_dev *dev)
+static int frontend_init(struct dm1105_dev *dev)
 {
        int ret;
 
@@ -949,7 +949,7 @@ static int __devinit frontend_init(struct dm1105_dev *dev)
        return 0;
 }
 
-static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
+static void dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
 {
        static u8 command[1] = { 0x28 };
 
@@ -971,7 +971,7 @@ static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
        dev_info(&dev->pdev->dev, "MAC %pM\n", mac);
 }
 
-static int __devinit dm1105_probe(struct pci_dev *pdev,
+static int dm1105_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        struct dm1105_dev *dev;
@@ -1174,7 +1174,7 @@ err_kfree:
        return ret;
 }
 
-static void __devexit dm1105_remove(struct pci_dev *pdev)
+static void dm1105_remove(struct pci_dev *pdev)
 {
        struct dm1105_dev *dev = pci_get_drvdata(pdev);
        struct dvb_adapter *dvb_adapter = &dev->dvb_adapter;
@@ -1207,7 +1207,7 @@ static void __devexit dm1105_remove(struct pci_dev *pdev)
        kfree(dev);
 }
 
-static struct pci_device_id dm1105_id_table[] __devinitdata = {
+static struct pci_device_id dm1105_id_table[] = {
        {
                .vendor = PCI_VENDOR_ID_TRIGEM,
                .device = PCI_DEVICE_ID_DM1105,
@@ -1229,7 +1229,7 @@ static struct pci_driver dm1105_driver = {
        .name = DRIVER_NAME,
        .id_table = dm1105_id_table,
        .probe = dm1105_probe,
-       .remove = __devexit_p(dm1105_remove),
+       .remove = dm1105_remove,
 };
 
 static int __init dm1105_init(void)
index 74e9a503236432b8c606ebfed56e87bca1fca10d..df88dc4ab555616dc830c1c7f237eefef3aa2191 100644 (file)
@@ -73,7 +73,7 @@ int (*ivtv_ext_init)(struct ivtv *);
 EXPORT_SYMBOL(ivtv_ext_init);
 
 /* add your revision and whatnot here */
-static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
+static struct pci_device_id ivtv_pci_tbl[] = {
        {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16,
@@ -736,7 +736,7 @@ done:
    No assumptions on the card type may be made here (see ivtv_init_struct2
    for that).
  */
-static int __devinit ivtv_init_struct1(struct ivtv *itv)
+static int ivtv_init_struct1(struct ivtv *itv)
 {
        struct sched_param param = { .sched_priority = 99 };
 
@@ -802,7 +802,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
 
 /* Second initialization part. Here the card type has been
    autodetected. */
-static void __devinit ivtv_init_struct2(struct ivtv *itv)
+static void ivtv_init_struct2(struct ivtv *itv)
 {
        int i;
 
@@ -1001,8 +1001,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
        }
 }
 
-static int __devinit ivtv_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *pci_id)
+static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
        int retval = 0;
        int vbi_buf_size;
index cc0251e010776525301319ada5cada8f648d9641..6fe9fe5293dc79fd1c5154c0dd52dd8a543793e0 100644 (file)
@@ -151,7 +151,8 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+static int hopper_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *pci_id)
 {
        struct mantis_pci *mantis;
        struct mantis_hwconfig *config;
@@ -230,7 +231,7 @@ fail0:
        return err;
 }
 
-static void __devexit hopper_pci_remove(struct pci_dev *pdev)
+static void hopper_pci_remove(struct pci_dev *pdev)
 {
        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 
@@ -259,12 +260,12 @@ static struct pci_driver hopper_pci_driver = {
        .remove         = hopper_pci_remove,
 };
 
-static int __devinit hopper_init(void)
+static int hopper_init(void)
 {
        return pci_register_driver(&hopper_pci_driver);
 }
 
-static void __devexit hopper_exit(void)
+static void hopper_exit(void)
 {
        return pci_unregister_driver(&hopper_pci_driver);
 }
index 0207d1f064e080ea2739a8c1a47d6d5a95c6dbcd..932a0d73a7f8f7d40b5d447f9d88f49fb60d6b4c 100644 (file)
@@ -159,7 +159,8 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+static int mantis_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *pci_id)
 {
        struct mantis_pci *mantis;
        struct mantis_hwconfig *config;
@@ -249,7 +250,7 @@ fail0:
        return err;
 }
 
-static void __devexit mantis_pci_remove(struct pci_dev *pdev)
+static void mantis_pci_remove(struct pci_dev *pdev)
 {
        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 
@@ -289,12 +290,12 @@ static struct pci_driver mantis_pci_driver = {
        .remove         = mantis_pci_remove,
 };
 
-static int __devinit mantis_init(void)
+static int mantis_init(void)
 {
        return pci_register_driver(&mantis_pci_driver);
 }
 
-static void __devexit mantis_exit(void)
+static void mantis_exit(void)
 {
        return pci_unregister_driver(&mantis_pci_driver);
 }
index 5d15c6b74d9be621bb5cb8fecfae9ad50512804f..5a71e1791cf5a00ab1d198520c380cf7a44c1890 100644 (file)
@@ -144,7 +144,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        return 0;
 }
 
-int __devinit mantis_dvb_init(struct mantis_pci *mantis)
+int mantis_dvb_init(struct mantis_pci *mantis)
 {
        struct mantis_hwconfig *config = mantis->hwconfig;
        int result = -1;
@@ -271,7 +271,7 @@ err0:
 }
 EXPORT_SYMBOL_GPL(mantis_dvb_init);
 
-int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
+int mantis_dvb_exit(struct mantis_pci *mantis)
 {
        int err;
 
index e7794517fe26c36098ff1d56fffcbde814e52a37..937fb9d50213ce94484a0be496ac0820b568eda3 100644 (file)
@@ -217,7 +217,7 @@ static struct i2c_algorithm mantis_algo = {
        .functionality          = mantis_i2c_func,
 };
 
-int __devinit mantis_i2c_init(struct mantis_pci *mantis)
+int mantis_i2c_init(struct mantis_pci *mantis)
 {
        u32 intstat, intmask;
        struct i2c_adapter *i2c_adapter = &mantis->adapter;
index 371558af2d9613fd45307c2e8a95d0ccaf62f4e9..a846036ea0227dfaabcc64d7e20401b495dcc424 100644 (file)
@@ -46,7 +46,7 @@
 
 #define DRIVER_NAME            "Mantis Core"
 
-int __devinit mantis_pci_init(struct mantis_pci *mantis)
+int mantis_pci_init(struct mantis_pci *mantis)
 {
        u8 latency;
        struct mantis_hwconfig *config  = mantis->hwconfig;
index ae7d32027bf726e0e73499880a61a07187fa6744..049e18667cd0339bbfc4437ca4d66d9fe6776594 100644 (file)
@@ -1728,8 +1728,7 @@ static int meye_resume(struct pci_dev *pdev)
 }
 #endif
 
-static int __devinit meye_probe(struct pci_dev *pcidev,
-                               const struct pci_device_id *ent)
+static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
 {
        struct v4l2_device *v4l2_dev = &meye.v4l2_dev;
        int ret = -EBUSY;
@@ -1889,7 +1888,7 @@ outnotdev:
        return ret;
 }
 
-static void __devexit meye_remove(struct pci_dev *pcidev)
+static void meye_remove(struct pci_dev *pcidev)
 {
        video_unregister_device(meye.vdev);
 
@@ -1935,7 +1934,7 @@ static struct pci_driver meye_driver = {
        .name           = "meye",
        .id_table       = meye_pci_tbl,
        .probe          = meye_probe,
-       .remove         = __devexit_p(meye_remove),
+       .remove         = meye_remove,
 #ifdef CONFIG_PM
        .suspend        = meye_suspend,
        .resume         = meye_resume,
index b38bce529566cdaa02b87b2855674ba5a03dd90e..fad2141136696a87d5f3e9dbbe2ebc28f51518ec 100644 (file)
@@ -743,7 +743,7 @@ static struct ngene_info ngene_info_terratec = {
 
 /****************************************************************************/
 
-static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
+static const struct pci_device_id ngene_id_tbl[] = {
        NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
        NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
        NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
@@ -800,7 +800,7 @@ static struct pci_driver ngene_pci_driver = {
        .name        = "ngene",
        .id_table    = ngene_id_tbl,
        .probe       = ngene_probe,
-       .remove      = __devexit_p(ngene_remove),
+       .remove      = ngene_remove,
        .err_handler = &ngene_errors,
        .shutdown    = ngene_shutdown,
 };
index 8eeec4f50ccb4103d2db272b3c1bc6d7b2608f18..37ebc42392adb45f0de0be794548a17761be0543 100644 (file)
@@ -1636,7 +1636,7 @@ void ngene_shutdown(struct pci_dev *pdev)
 /* device probe/remove calls ************************************************/
 /****************************************************************************/
 
-void __devexit ngene_remove(struct pci_dev *pdev)
+void ngene_remove(struct pci_dev *pdev)
 {
        struct ngene *dev = pci_get_drvdata(pdev);
        int i;
@@ -1652,8 +1652,7 @@ void __devexit ngene_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-int __devinit ngene_probe(struct pci_dev *pci_dev,
-                         const struct pci_device_id *id)
+int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
        struct ngene *dev;
        int stat = 0;
index 5443dc0caea50e2067a68c5df66d6563d79f7f58..22c39ff6bfa0e90c278d08c0cbc84d156c8e5732 100644 (file)
@@ -887,9 +887,8 @@ struct ngene_buffer {
 
 
 /* Provided by ngene-core.c */
-int __devinit ngene_probe(struct pci_dev *pci_dev,
-                         const struct pci_device_id *id);
-void __devexit ngene_remove(struct pci_dev *pdev);
+int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
+void ngene_remove(struct pci_dev *pdev);
 void ngene_shutdown(struct pci_dev *pdev);
 int ngene_command(struct ngene *dev, struct ngene_command *com);
 int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level);
index f148b19a206a0bd617c29a1cf65a0aa83c2649ac..2290faee5852f13124d83503538fbd8bc6cd59af 100644 (file)
@@ -240,7 +240,7 @@ static void pluto_set_dma_addr(struct pluto *pluto)
        pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
 }
 
-static int __devinit pluto_dma_map(struct pluto *pluto)
+static int pluto_dma_map(struct pluto *pluto)
 {
        pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
                        TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
@@ -368,7 +368,7 @@ static irqreturn_t pluto_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void __devinit pluto_enable_irqs(struct pluto *pluto)
+static void pluto_enable_irqs(struct pluto *pluto)
 {
        u32 val = pluto_readreg(pluto, REG_TSCR);
 
@@ -394,7 +394,7 @@ static void pluto_disable_irqs(struct pluto *pluto)
        pluto_write_tscr(pluto, val);
 }
 
-static int __devinit pluto_hw_init(struct pluto *pluto)
+static int pluto_hw_init(struct pluto *pluto)
 {
        pluto_reset_frontend(pluto, 1);
 
@@ -505,7 +505,7 @@ static int pluto2_request_firmware(struct dvb_frontend *fe,
        return request_firmware(fw, name, &pluto->pdev->dev);
 }
 
-static struct tda1004x_config pluto2_fe_config __devinitdata = {
+static struct tda1004x_config pluto2_fe_config = {
        .demod_address = I2C_ADDR_TDA10046 >> 1,
        .invert = 1,
        .invert_oclk = 0,
@@ -515,7 +515,7 @@ static struct tda1004x_config pluto2_fe_config __devinitdata = {
        .request_firmware = pluto2_request_firmware,
 };
 
-static int __devinit frontend_init(struct pluto *pluto)
+static int frontend_init(struct pluto *pluto)
 {
        int ret;
 
@@ -536,14 +536,14 @@ static int __devinit frontend_init(struct pluto *pluto)
        return 0;
 }
 
-static void __devinit pluto_read_rev(struct pluto *pluto)
+static void pluto_read_rev(struct pluto *pluto)
 {
        u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR;
        dev_info(&pluto->pdev->dev, "board revision %d.%d\n",
                        (val >> 12) & 0x0f, (val >> 4) & 0xff);
 }
 
-static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
+static void pluto_read_mac(struct pluto *pluto, u8 *mac)
 {
        u32 val = pluto_readreg(pluto, REG_MMAC);
        mac[0] = (val >> 8) & 0xff;
@@ -560,7 +560,7 @@ static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
        dev_info(&pluto->pdev->dev, "MAC %pM\n", mac);
 }
 
-static int __devinit pluto_read_serial(struct pluto *pluto)
+static int pluto_read_serial(struct pluto *pluto)
 {
        struct pci_dev *pdev = pluto->pdev;
        unsigned int i, j;
@@ -588,8 +588,7 @@ out:
        return 0;
 }
 
-static int __devinit pluto2_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int pluto2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct pluto *pluto;
        struct dvb_adapter *dvb_adapter;
@@ -742,7 +741,7 @@ err_kfree:
        goto out;
 }
 
-static void __devexit pluto2_remove(struct pci_dev *pdev)
+static void pluto2_remove(struct pci_dev *pdev)
 {
        struct pluto *pluto = pci_get_drvdata(pdev);
        struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter;
@@ -777,7 +776,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev)
 #define PCI_DEVICE_ID_PLUTO2   0x0001
 #endif
 
-static struct pci_device_id pluto2_id_table[] __devinitdata = {
+static struct pci_device_id pluto2_id_table[] = {
        {
                .vendor = PCI_VENDOR_ID_SCM,
                .device = PCI_DEVICE_ID_PLUTO2,
@@ -794,7 +793,7 @@ static struct pci_driver pluto2_driver = {
        .name = DRIVER_NAME,
        .id_table = pluto2_id_table,
        .probe = pluto2_probe,
-       .remove = __devexit_p(pluto2_remove),
+       .remove = pluto2_remove,
 };
 
 static int __init pluto2_init(void)
index 15b35c4725f18874b3306be104cadf6cc6dc8a7b..e9211086df490c1b7ec9db82f7ab74d82f4fd427 100644 (file)
@@ -1058,7 +1058,7 @@ static void pt1_i2c_init(struct pt1 *pt1)
                pt1_i2c_emit(pt1, i, 0, 0, 1, 1, 0);
 }
 
-static void __devexit pt1_remove(struct pci_dev *pdev)
+static void pt1_remove(struct pci_dev *pdev)
 {
        struct pt1 *pt1;
        void __iomem *regs;
@@ -1083,8 +1083,7 @@ static void __devexit pt1_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static int __devinit
-pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret;
        void __iomem *regs;
@@ -1222,7 +1221,7 @@ MODULE_DEVICE_TABLE(pci, pt1_id_table);
 static struct pci_driver pt1_driver = {
        .name           = DRIVER_NAME,
        .probe          = pt1_probe,
-       .remove         = __devexit_p(pt1_remove),
+       .remove         = pt1_remove,
        .id_table       = pt1_id_table,
 };
 
index 8976d0e65813d26d7c2761d7172fd7549899d1d4..e359d200d698d9b03ff7a07dba9236c6070fc6d9 100644 (file)
@@ -754,7 +754,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
        return 0;
 }
 
-static void __devinit must_configure_manually(int has_eeprom)
+static void must_configure_manually(int has_eeprom)
 {
        unsigned int i,p;
 
@@ -860,8 +860,8 @@ static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
        dev->mops = NULL;
 }
 
-static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
+static int saa7134_initdev(struct pci_dev *pci_dev,
+                          const struct pci_device_id *pci_id)
 {
        struct saa7134_dev *dev;
        struct saa7134_mpeg_ops *mops;
@@ -1102,7 +1102,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        return err;
 }
 
-static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
+static void saa7134_finidev(struct pci_dev *pci_dev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
        struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
@@ -1322,7 +1322,7 @@ static struct pci_driver saa7134_pci_driver = {
        .name     = "saa7134",
        .id_table = saa7134_pci_tbl,
        .probe    = saa7134_initdev,
-       .remove   = __devexit_p(saa7134_finidev),
+       .remove   = saa7134_finidev,
 #ifdef CONFIG_PM
        .suspend  = saa7134_suspend,
        .resume   = saa7134_resume
index c24b6512bd8f8976f514c8a609f2238eaa2b9f45..075908fae4d90a409849825c97b0d1d701762f7e 100644 (file)
@@ -739,7 +739,7 @@ extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
 
 extern struct saa7134_board saa7134_boards[];
 extern const unsigned int saa7134_bcount;
-extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
+extern struct pci_device_id saa7134_pci_tbl[];
 
 extern int saa7134_board_init1(struct saa7134_dev *dev);
 extern int saa7134_board_init2(struct saa7134_dev *dev);
index 063047f567669f1bdc6c33bcfdca33528d56f5a3..63502e7a2a762fbf75f90108ac9cf3b8781ad70b 100644 (file)
@@ -1185,8 +1185,8 @@ static int saa7164_thread_function(void *data)
        return 0;
 }
 
-static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
+static int saa7164_initdev(struct pci_dev *pci_dev,
+                          const struct pci_device_id *pci_id)
 {
        struct saa7164_dev *dev;
        int err, i;
@@ -1376,7 +1376,7 @@ static void saa7164_shutdown(struct saa7164_dev *dev)
        dprintk(1, "%s()\n", __func__);
 }
 
-static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
+static void saa7164_finidev(struct pci_dev *pci_dev)
 {
        struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
 
@@ -1459,7 +1459,7 @@ static struct pci_driver saa7164_pci_driver = {
        .name     = "saa7164",
        .id_table = saa7164_pci_tbl,
        .probe    = saa7164_initdev,
-       .remove   = __devexit_p(saa7164_finidev),
+       .remove   = saa7164_finidev,
        /* TODO */
        .suspend  = NULL,
        .resume   = NULL,
index 4c10205264d4d7c0e2ba25ae48e999bb1aa593a7..27ae4884265644190b1777d61059c84410f8d3ea 100644 (file)
@@ -1205,8 +1205,8 @@ static void vip_gpio_release(struct device *dev, int pin, const char *name)
  *
  * -ENODEV, device could not be detected or registered
  */
-static int __devinit sta2x11_vip_init_one(struct pci_dev *pdev,
-                                         const struct pci_device_id *ent)
+static int sta2x11_vip_init_one(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
 {
        int ret;
        struct sta2x11_vip *vip;
@@ -1376,7 +1376,7 @@ disable:
  * free memory
  * free GPIO pins
  */
-static void __devexit sta2x11_vip_remove_one(struct pci_dev *pdev)
+static void sta2x11_vip_remove_one(struct pci_dev *pdev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
        struct sta2x11_vip *vip =
@@ -1517,7 +1517,7 @@ static DEFINE_PCI_DEVICE_TABLE(sta2x11_vip_pci_tbl) = {
 static struct pci_driver sta2x11_vip_driver = {
        .name = DRV_NAME,
        .probe = sta2x11_vip_init_one,
-       .remove = __devexit_p(sta2x11_vip_remove_one),
+       .remove = sta2x11_vip_remove_one,
        .id_table = sta2x11_vip_pci_tbl,
 #ifdef CONFIG_PM
        .suspend = sta2x11_vip_suspend,
index 4bd8bd56befc2230d739c89c7deea63b0644bd25..4656d4a10af062286f313ef0aa4ac73f10b45014 100644 (file)
@@ -2367,8 +2367,8 @@ static int frontend_init(struct av7110 *av7110)
  * The same behaviour of missing VSYNC can be duplicated on budget
  * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
  */
-static int __devinit av7110_attach(struct saa7146_dev* dev,
-                                  struct saa7146_pci_extension_data *pci_ext)
+static int av7110_attach(struct saa7146_dev* dev,
+                        struct saa7146_pci_extension_data *pci_ext)
 {
        const int length = TS_WIDTH * TS_HEIGHT;
        struct pci_dev *pdev = dev->pci;
@@ -2761,7 +2761,7 @@ err_kfree_0:
        goto out;
 }
 
-static int __devexit av7110_detach(struct saa7146_dev* saa)
+static int av7110_detach(struct saa7146_dev* saa)
 {
        struct av7110 *av7110 = saa->ext_priv;
        dprintk(4, "%p\n", av7110);
@@ -2910,7 +2910,7 @@ static struct saa7146_extension av7110_extension_driver = {
        .module         = THIS_MODULE,
        .pci_tbl        = &pci_tbl[0],
        .attach         = av7110_attach,
-       .detach         = __devexit_p(av7110_detach),
+       .detach         = av7110_detach,
 
        .irq_mask       = MASK_19 | MASK_03 | MASK_10,
        .irq_func       = av7110_irq,
index 908f272fe26cc0b1c6ad8c4517c8342b1a94a44a..eb822862a6467fdc096fd9f992d8c6b863045cb2 100644 (file)
@@ -324,7 +324,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
 }
 
 
-int __devinit av7110_ir_init(struct av7110 *av7110)
+int av7110_ir_init(struct av7110 *av7110)
 {
        struct input_dev *input_dev;
        static struct proc_dir_entry *e;
@@ -385,7 +385,7 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
 }
 
 
-void __devexit av7110_ir_exit(struct av7110 *av7110)
+void av7110_ir_exit(struct av7110 *av7110)
 {
        int i;
 
index fffc54b452c8aa8f510928eaa40c7e99171f8d3f..a90a3b9b09bff6074f1f06c808b655425b1180c2 100644 (file)
@@ -369,7 +369,7 @@ static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END };
 static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END };
 static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END };
 
-static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
+static struct card_info zoran_cards[NUM_CARDS] = {
        {
                .type = DC10_old,
                .name = "DC10(old)",
@@ -948,8 +948,7 @@ zoran_open_init_params (struct zoran *zr)
        zr->testing = 0;
 }
 
-static void __devinit
-test_interrupts (struct zoran *zr)
+static void test_interrupts (struct zoran *zr)
 {
        DEFINE_WAIT(wait);
        int timeout, icr;
@@ -974,8 +973,7 @@ test_interrupts (struct zoran *zr)
        btwrite(icr, ZR36057_ICR);
 }
 
-static int __devinit
-zr36057_init (struct zoran *zr)
+static int zr36057_init (struct zoran *zr)
 {
        int j, err;
 
@@ -1083,7 +1081,7 @@ exit_free:
        return err;
 }
 
-static void __devexit zoran_remove(struct pci_dev *pdev)
+static void zoran_remove(struct pci_dev *pdev)
 {
        struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
        struct zoran *zr = to_zoran(v4l2_dev);
@@ -1129,9 +1127,8 @@ zoran_vdev_release (struct video_device *vdev)
        kfree(vdev);
 }
 
-static struct videocodec_master * __devinit
-zoran_setup_videocodec (struct zoran *zr,
-                       int           type)
+static struct videocodec_master *zoran_setup_videocodec(struct zoran *zr,
+                                                       int type)
 {
        struct videocodec_master *m = NULL;
 
@@ -1192,8 +1189,7 @@ static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *
  *   Scan for a Buz card (actually for the PCI controller ZR36057),
  *   request the irq and map the io memory
  */
-static int __devinit zoran_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned char latency, need_latency;
        struct zoran *zr;
@@ -1459,7 +1455,7 @@ static struct pci_driver zoran_driver = {
        .name = "zr36067",
        .id_table = zr36067_pci_tbl,
        .probe = zoran_probe,
-       .remove = __devexit_p(zoran_remove),
+       .remove = zoran_remove,
 };
 
 static int __init zoran_init(void)
index 53f12c7466b0b971218c2c1c6d769fa0d3f32461..e60ae41e2319e0aaf91538454984a12e8975ab8e 100644 (file)
@@ -3080,7 +3080,7 @@ static const struct v4l2_file_operations zoran_fops = {
        .poll = zoran_poll,
 };
 
-struct video_device zoran_template __devinitdata = {
+struct video_device zoran_template = {
        .name = ZORAN_NAME,
        .fops = &zoran_fops,
        .ioctl_ops = &zoran_ioctl_ops,
index ec476ef5b709bbe8c56e354e6fecb5d3c70902d5..1aad2a65d2f35d2e2c280ad77db725a2a0d3305b 100644 (file)
@@ -862,7 +862,7 @@ static struct v4l2_file_operations bcap_fops = {
        .poll = bcap_poll
 };
 
-static int __devinit bcap_probe(struct platform_device *pdev)
+static int bcap_probe(struct platform_device *pdev)
 {
        struct bcap_device *bcap_dev;
        struct video_device *vfd;
@@ -1026,7 +1026,7 @@ err_free_dev:
        return ret;
 }
 
-static int __devexit bcap_remove(struct platform_device *pdev)
+static int bcap_remove(struct platform_device *pdev)
 {
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
        struct bcap_device *bcap_dev = container_of(v4l2_dev,
@@ -1048,7 +1048,7 @@ static struct platform_driver bcap_driver = {
                .owner = THIS_MODULE,
        },
        .probe = bcap_probe,
-       .remove = __devexit_p(bcap_remove),
+       .remove = bcap_remove,
 };
 module_platform_driver(bcap_driver);
 
index 7b8b547f2d51867115f9bf5a510495e6c35baebb..4a980e029ca70163b30288663a7f273943002e18 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/of.h>
+#include <linux/platform_data/imx-iram.h>
 
-#include <mach/iram.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -1891,7 +1891,7 @@ static const struct of_device_id coda_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, coda_dt_ids);
 #endif
 
-static int __devinit coda_probe(struct platform_device *pdev)
+static int coda_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id =
                        of_match_device(of_match_ptr(coda_dt_ids), &pdev->dev);
@@ -2033,7 +2033,7 @@ static int coda_remove(struct platform_device *pdev)
 
 static struct platform_driver coda_driver = {
        .probe  = coda_probe,
-       .remove = __devexit_p(coda_remove),
+       .remove = coda_remove,
        .driver = {
                .name   = CODA_NAME,
                .owner  = THIS_MODULE,
index 030950dcfb1628d56d0a640e264750da0ea62f45..f263cabade7af0d7b8f315fdce1102160b5d3610 100644 (file)
@@ -965,7 +965,7 @@ static struct ccdc_hw_device ccdc_hw_dev = {
        },
 };
 
-static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
+static int dm355_ccdc_probe(struct platform_device *pdev)
 {
        void (*setup_pinmux)(void);
        struct resource *res;
@@ -1069,7 +1069,7 @@ static struct platform_driver dm355_ccdc_driver = {
                .name   = "dm355_ccdc",
                .owner = THIS_MODULE,
        },
-       .remove = __devexit_p(dm355_ccdc_remove),
+       .remove = dm355_ccdc_remove,
        .probe = dm355_ccdc_probe,
 };
 
index 0215ab6ebc909d3ae4b4042aa4c8880223b0beb4..318e805129984348cb6d3295c7caa71f0e9a2548 100644 (file)
@@ -957,7 +957,7 @@ static struct ccdc_hw_device ccdc_hw_dev = {
        },
 };
 
-static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
+static int dm644x_ccdc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int status = 0;
@@ -1078,7 +1078,7 @@ static struct platform_driver dm644x_ccdc_driver = {
                .owner = THIS_MODULE,
                .pm = &dm644x_ccdc_pm_ops,
        },
-       .remove = __devexit_p(dm644x_ccdc_remove),
+       .remove = dm644x_ccdc_remove,
        .probe = dm644x_ccdc_probe,
 };
 
index 2c26c3e1837eb05b974a8e071f62640354264407..5050f9265f48333c53a3bdaa35353ebe7daf60bd 100644 (file)
@@ -1032,7 +1032,7 @@ static struct ccdc_hw_device isif_hw_dev = {
        },
 };
 
-static int __devinit isif_probe(struct platform_device *pdev)
+static int isif_probe(struct platform_device *pdev)
 {
        void (*setup_pinmux)(void);
        struct resource *res;
@@ -1156,7 +1156,7 @@ static struct platform_driver isif_driver = {
                .name   = "isif",
                .owner = THIS_MODULE,
        },
-       .remove = __devexit_p(isif_remove),
+       .remove = isif_remove,
        .probe = isif_probe,
 };
 
index 7f5cf9b347b2c40e22f5056a0fe062a31cfabf86..841b91a3d2551763db04cdc4c6a6e0459645a457 100644 (file)
@@ -807,7 +807,7 @@ static struct vpbe_device_ops vpbe_dev_ops = {
        .set_mode = vpbe_set_mode,
 };
 
-static __devinit int vpbe_probe(struct platform_device *pdev)
+static int vpbe_probe(struct platform_device *pdev)
 {
        struct vpbe_device *vpbe_dev;
        struct vpbe_config *cfg;
index 2bfde7958fefb700d948d9635a32ae9c4888ab88..e707a6f2325ba63cced2d05839f092171c382f15 100644 (file)
@@ -1662,8 +1662,8 @@ static int vpbe_device_get(struct device *dev, void *data)
        return 0;
 }
 
-static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
-                                    struct platform_device *pdev)
+static int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
+                          struct platform_device *pdev)
 {
        struct vpbe_layer *vpbe_display_layer = NULL;
        struct video_device *vbd = NULL;
@@ -1718,9 +1718,10 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
        return 0;
 }
 
-static __devinit int register_device(struct vpbe_layer *vpbe_display_layer,
-                                       struct vpbe_display *disp_dev,
-                                       struct platform_device *pdev) {
+static int register_device(struct vpbe_layer *vpbe_display_layer,
+                          struct vpbe_display *disp_dev,
+                          struct platform_device *pdev)
+{
        int err;
 
        v4l2_info(&disp_dev->vpbe_dev->v4l2_dev,
@@ -1752,7 +1753,7 @@ static __devinit int register_device(struct vpbe_layer *vpbe_display_layer,
  * This function creates device entries by register itself to the V4L2 driver
  * and initializes fields of each layer objects
  */
-static __devinit int vpbe_display_probe(struct platform_device *pdev)
+static int vpbe_display_probe(struct platform_device *pdev)
 {
        struct vpbe_layer *vpbe_display_layer;
        struct vpbe_display *disp_dev;
@@ -1886,7 +1887,7 @@ static struct platform_driver vpbe_display_driver = {
                .bus = &platform_bus_type,
        },
        .probe = vpbe_display_probe,
-       .remove = __devexit_p(vpbe_display_remove),
+       .remove = vpbe_display_remove,
 };
 
 module_platform_driver(vpbe_display_driver);
index 8be492cd8ed46bf58a9cd79ce4d26ed8474404aa..be9d3e1b48687bf25830fec6f53711aed6eafbf5 100644 (file)
@@ -1831,7 +1831,7 @@ static struct vpfe_device *vpfe_initialize(void)
  * itself to the V4L2 driver and initializes fields of each
  * device objects
  */
-static __devinit int vpfe_probe(struct platform_device *pdev)
+static int vpfe_probe(struct platform_device *pdev)
 {
        struct vpfe_subdev_info *sdinfo;
        struct vpfe_config *vpfe_cfg;
@@ -2038,7 +2038,7 @@ probe_free_dev_mem:
 /*
  * vpfe_remove : It un-register device from V4L2 driver
  */
-static int __devexit vpfe_remove(struct platform_device *pdev)
+static int vpfe_remove(struct platform_device *pdev)
 {
        struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
 
@@ -2075,7 +2075,7 @@ static struct platform_driver vpfe_driver = {
                .pm = &vpfe_dev_pm_ops,
        },
        .probe = vpfe_probe,
-       .remove = __devexit_p(vpfe_remove),
+       .remove = vpfe_remove,
 };
 
 module_platform_driver(vpfe_driver);
index 0d6cc8e4deb28889ea2286b0e84cb8a194475dd2..28638a86f12964c9ab81e3d5bd99d9ba495429a7 100644 (file)
@@ -419,7 +419,7 @@ int vpif_channel_getfid(u8 channel_id)
 }
 EXPORT_SYMBOL(vpif_channel_getfid);
 
-static int __devinit vpif_probe(struct platform_device *pdev)
+static int vpif_probe(struct platform_device *pdev)
 {
        int status = 0;
 
@@ -457,7 +457,7 @@ fail:
        return status;
 }
 
-static int __devexit vpif_remove(struct platform_device *pdev)
+static int vpif_remove(struct platform_device *pdev)
 {
        if (vpif_clk) {
                clk_disable_unprepare(vpif_clk);
@@ -498,7 +498,7 @@ static struct platform_driver vpif_driver = {
                .owner = THIS_MODULE,
                .pm     = vpif_pm_ops,
        },
-       .remove = __devexit_p(vpif_remove),
+       .remove = vpif_remove,
        .probe = vpif_probe,
 };
 
index 146e4b01ac177593b58ad5c7fadc1724d2118973..cdbff88e0f1e337beacb06d108f403ba422396ba 100644 (file)
@@ -357,7 +357,7 @@ void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
 }
 EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
 
-static int __devinit vpss_probe(struct platform_device *pdev)
+static int vpss_probe(struct platform_device *pdev)
 {
        struct resource         *r1, *r2;
        char *platform_name;
@@ -445,7 +445,7 @@ fail1:
        return status;
 }
 
-static int __devexit vpss_remove(struct platform_device *pdev)
+static int vpss_remove(struct platform_device *pdev)
 {
        struct resource         *res;
 
@@ -465,7 +465,7 @@ static struct platform_driver vpss_driver = {
                .name   = "vpss",
                .owner = THIS_MODULE,
        },
-       .remove = __devexit_p(vpss_remove),
+       .remove = vpss_remove,
        .probe = vpss_probe,
 };
 
index cc7b218d047cffb5e48e0e031eaae6ae7a0bbffb..2b1b9f30e1f940032e20505142cd7291f3587511 100644 (file)
@@ -1151,7 +1151,7 @@ err_clk:
        return ret;
 }
 
-static int __devexit gsc_remove(struct platform_device *pdev)
+static int gsc_remove(struct platform_device *pdev)
 {
        struct gsc_dev *gsc = platform_get_drvdata(pdev);
 
@@ -1237,7 +1237,7 @@ static const struct dev_pm_ops gsc_pm_ops = {
 
 static struct platform_driver gsc_driver = {
        .probe          = gsc_probe,
-       .remove = __devexit_p(gsc_remove),
+       .remove         = gsc_remove,
        .id_table       = gsc_driver_ids,
        .driver = {
                .name   = GSC_MODULE_NAME,
index a8ddb0cacab82cc7d81e5c3f17b6d4d5f29d9a2a..9115a2c8d075b4be9f69be36cfcb1bcfd05bf820 100644 (file)
@@ -1478,7 +1478,7 @@ static struct video_device viu_template = {
        .current_norm   = V4L2_STD_NTSC_M,
 };
 
-static int __devinit viu_of_probe(struct platform_device *op)
+static int viu_of_probe(struct platform_device *op)
 {
        struct viu_dev *viu_dev;
        struct video_device *vdev;
@@ -1615,7 +1615,7 @@ err:
        return ret;
 }
 
-static int __devexit viu_of_remove(struct platform_device *op)
+static int viu_of_remove(struct platform_device *op)
 {
        struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev);
        struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
@@ -1668,7 +1668,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
 
 static struct platform_driver viu_of_platform_driver = {
        .probe = viu_of_probe,
-       .remove = __devexit_p(viu_of_remove),
+       .remove = viu_of_remove,
 #ifdef CONFIG_PM
        .suspend = viu_suspend,
        .resume = viu_resume,
index 70f45c381318929f4b80b70025fb368305a0b788..8b7ccea982e771e109327cbcf40683b41bd48c18 100644 (file)
@@ -1736,7 +1736,7 @@ static struct v4l2_int_device omap24xxcam = {
  *
  */
 
-static int __devinit omap24xxcam_probe(struct platform_device *pdev)
+static int omap24xxcam_probe(struct platform_device *pdev)
 {
        struct omap24xxcam_device *cam;
        struct resource *mem;
index a9f6de5b69d85949fdda469d9ed2e9aaafa8cdd5..e4aaee91201dade6d811ebdb2b3c21d44f69f299 100644 (file)
@@ -71,8 +71,6 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 
-#include <plat/cpu.h>
-
 #include "isp.h"
 #include "ispreg.h"
 #include "ispccdc.h"
@@ -1992,7 +1990,7 @@ error_csiphy:
  *
  * Always returns 0.
  */
-static int __devexit isp_remove(struct platform_device *pdev)
+static int isp_remove(struct platform_device *pdev)
 {
        struct isp_device *isp = platform_get_drvdata(pdev);
        int i;
@@ -2073,7 +2071,7 @@ static int isp_map_mem_resource(struct platform_device *pdev,
  *   -EINVAL if couldn't install ISR,
  *   or clk_get return error value.
  */
-static int __devinit isp_probe(struct platform_device *pdev)
+static int isp_probe(struct platform_device *pdev)
 {
        struct isp_platform_data *pdata = pdev->dev.platform_data;
        struct isp_device *isp;
@@ -2252,7 +2250,7 @@ MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
 
 static struct platform_driver omap3isp_driver = {
        .probe = isp_probe,
-       .remove = __devexit_p(isp_remove),
+       .remove = isp_remove,
        .id_table = omap3isp_id_table,
        .driver = {
                .owner = THIS_MODULE,
index e0d73a642186d34ae63d841cabe3f42c57604acd..8dac17511e618c84d27a9db8bbfbd7587f5c1d2a 100644 (file)
@@ -35,9 +35,6 @@
 #include <linux/vmalloc.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
 
 #include "ispvideo.h"
 #include "isp.h"
index 0dd65376c067a2052373c82a13a3b13d7600ffb6..e2716c35f8f189ebbfbbb44de6386ffb82fc4133 100644 (file)
@@ -531,7 +531,7 @@ err_sd:
        return ret;
 }
 
-static int __devexit s3c_camif_remove(struct platform_device *pdev)
+static int s3c_camif_remove(struct platform_device *pdev)
 {
        struct camif_dev *camif = platform_get_drvdata(pdev);
        struct s3c_camif_plat_data *pdata = &camif->pdata;
@@ -645,7 +645,7 @@ static const struct dev_pm_ops s3c_camif_pm_ops = {
 
 static struct platform_driver s3c_camif_driver = {
        .probe          = s3c_camif_probe,
-       .remove         = __devexit_p(s3c_camif_remove),
+       .remove         = s3c_camif_remove,
        .id_table       = s3c_camif_driver_ids,
        .driver = {
                .name   = S3C_CAMIF_DRIVER_NAME,
index 8d0d2b94a135f45b0d8fa2c1378fd287aff7ef27..545b46ae12a1ae90c63c93c4e18f76ddc81ca7af 100644 (file)
@@ -1035,7 +1035,7 @@ static int fimc_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static int __devexit fimc_remove(struct platform_device *pdev)
+static int fimc_remove(struct platform_device *pdev)
 {
        struct fimc_dev *fimc = platform_get_drvdata(pdev);
 
@@ -1234,7 +1234,7 @@ static const struct dev_pm_ops fimc_pm_ops = {
 
 static struct platform_driver fimc_driver = {
        .probe          = fimc_probe,
-       .remove         = __devexit_p(fimc_remove),
+       .remove         = fimc_remove,
        .id_table       = fimc_driver_ids,
        .driver = {
                .name   = FIMC_MODULE_NAME,
index 1b309a72f09fbe847c1b4ac2178c1717a68f5a04..ed67220d0a64734bd56498c63555db5c732d4f5a 100644 (file)
@@ -1406,7 +1406,7 @@ static int fimc_lite_clk_get(struct fimc_lite *fimc)
        return ret;
 }
 
-static int __devinit fimc_lite_probe(struct platform_device *pdev)
+static int fimc_lite_probe(struct platform_device *pdev)
 {
        struct flite_drvdata *drv_data = fimc_lite_get_drvdata(pdev);
        struct fimc_lite *fimc;
@@ -1547,7 +1547,7 @@ static int fimc_lite_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static int __devexit fimc_lite_remove(struct platform_device *pdev)
+static int fimc_lite_remove(struct platform_device *pdev)
 {
        struct fimc_lite *fimc = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -1595,7 +1595,7 @@ static const struct dev_pm_ops fimc_lite_pm_ops = {
 
 static struct platform_driver fimc_lite_driver = {
        .probe          = fimc_lite_probe,
-       .remove         = __devexit_p(fimc_lite_remove),
+       .remove         = fimc_lite_remove,
        .id_table       = fimc_lite_driver_ids,
        .driver = {
                .name           = FIMC_LITE_DRV_NAME,
index 1bd5678cfeb9d13f4bfd4b1dc0f7ffccac5ce33b..b4a68ecf0ca78731ea98b0178c45dac926378e3d 100644 (file)
@@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
 {
        struct media_entity *source, *sink;
        unsigned int flags = MEDIA_LNK_FL_ENABLED;
-       int i, ret;
+       int i, ret = 0;
 
        for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
                struct fimc_lite *fimc = fmd->fimc_lite[i];
@@ -1000,7 +1000,7 @@ err_md:
        return ret;
 }
 
-static int __devexit fimc_md_remove(struct platform_device *pdev)
+static int fimc_md_remove(struct platform_device *pdev)
 {
        struct fimc_md *fmd = platform_get_drvdata(pdev);
 
@@ -1015,7 +1015,7 @@ static int __devexit fimc_md_remove(struct platform_device *pdev)
 
 static struct platform_driver fimc_md_driver = {
        .probe          = fimc_md_probe,
-       .remove         = __devexit_p(fimc_md_remove),
+       .remove         = fimc_md_remove,
        .driver = {
                .name   = "s5p-fimc-md",
                .owner  = THIS_MODULE,
index 4c961b1b68e6004ab1dd98d578b0e6cc407e97f9..ec3fa7d75306675d4fde53ecb2c2f52c0fc6cbe8 100644 (file)
@@ -654,7 +654,7 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit s5pcsis_probe(struct platform_device *pdev)
+static int s5pcsis_probe(struct platform_device *pdev)
 {
        struct s5p_platform_mipi_csis *pdata;
        struct resource *mem_res;
@@ -851,7 +851,7 @@ static int s5pcsis_runtime_resume(struct device *dev)
 }
 #endif
 
-static int __devexit s5pcsis_remove(struct platform_device *pdev)
+static int s5pcsis_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -876,7 +876,7 @@ static const struct dev_pm_ops s5pcsis_pm_ops = {
 
 static struct platform_driver s5pcsis_driver = {
        .probe          = s5pcsis_probe,
-       .remove         = __devexit_p(s5pcsis_remove),
+       .remove         = s5pcsis_remove,
        .driver         = {
                .name   = CSIS_DRIVER_NAME,
                .owner  = THIS_MODULE,
index 3afe879d54d7dec195cc99ff49aa316ff42ff53a..681bc6ba149db1bdf380b483c32b9babfb335a58 100644 (file)
@@ -412,62 +412,48 @@ leave_handle_frame:
 }
 
 /* Error handling for interrupt */
-static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
-                                unsigned int reason, unsigned int err)
+static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
 {
-       struct s5p_mfc_dev *dev;
        unsigned long flags;
 
-       /* If no context is available then all necessary
-        * processing has been done. */
-       if (ctx == NULL)
-               return;
-
-       dev = ctx->dev;
        mfc_err("Interrupt Error: %08x\n", err);
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       wake_up_dev(dev, reason, err);
 
-       /* Error recovery is dependent on the state of context */
-       switch (ctx->state) {
-       case MFCINST_INIT:
-               /* This error had to happen while acquireing instance */
-       case MFCINST_GOT_INST:
-               /* This error had to happen while parsing the header */
-       case MFCINST_HEAD_PARSED:
-               /* This error had to happen while setting dst buffers */
-       case MFCINST_RETURN_INST:
-               /* This error had to happen while releasing instance */
-               clear_work_bit(ctx);
-               wake_up_ctx(ctx, reason, err);
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       BUG();
-               s5p_mfc_clock_off();
-               ctx->state = MFCINST_ERROR;
-               break;
-       case MFCINST_FINISHING:
-       case MFCINST_FINISHED:
-       case MFCINST_RUNNING:
-               /* It is higly probable that an error occured
-                * while decoding a frame */
-               clear_work_bit(ctx);
-               ctx->state = MFCINST_ERROR;
-               /* Mark all dst buffers as having an error */
-               spin_lock_irqsave(&dev->irqlock, flags);
-               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
-                               &ctx->vq_dst);
-               /* Mark all src buffers as having an error */
-               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
-                               &ctx->vq_src);
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       BUG();
-               s5p_mfc_clock_off();
-               break;
-       default:
-               mfc_err("Encountered an error interrupt which had not been handled\n");
-               break;
+       if (ctx != NULL) {
+               /* Error recovery is dependent on the state of context */
+               switch (ctx->state) {
+               case MFCINST_RES_CHANGE_INIT:
+               case MFCINST_RES_CHANGE_FLUSH:
+               case MFCINST_RES_CHANGE_END:
+               case MFCINST_FINISHING:
+               case MFCINST_FINISHED:
+               case MFCINST_RUNNING:
+                       /* It is higly probable that an error occured
+                        * while decoding a frame */
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       /* Mark all dst buffers as having an error */
+                       spin_lock_irqsave(&dev->irqlock, flags);
+                       s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+                                               &ctx->dst_queue, &ctx->vq_dst);
+                       /* Mark all src buffers as having an error */
+                       s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+                                               &ctx->src_queue, &ctx->vq_src);
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               default:
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               }
        }
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               BUG();
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       s5p_mfc_clock_off();
+       wake_up_dev(dev, reason, err);
        return;
 }
 
@@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
                                dev->warn_start)
                        s5p_mfc_handle_frame(ctx, reason, err);
                else
-                       s5p_mfc_handle_error(ctx, reason, err);
+                       s5p_mfc_handle_error(dev, ctx, reason, err);
                clear_bit(0, &dev->enter_suspend);
                break;
 
@@ -1203,7 +1189,7 @@ err_res:
 }
 
 /* Remove the driver */
-static int __devexit s5p_mfc_remove(struct platform_device *pdev)
+static int s5p_mfc_remove(struct platform_device *pdev)
 {
        struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
 
@@ -1368,7 +1354,7 @@ MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
 
 static struct platform_driver s5p_mfc_driver = {
        .probe          = s5p_mfc_probe,
-       .remove         = __devexit_p(s5p_mfc_remove),
+       .remove         = s5p_mfc_remove,
        .id_table       = mfc_driver_ids,
        .driver = {
                .name   = S5P_MFC_NAME,
index 8a9cf43018f635f48724953756108ec3ce800cb5..7c1116c73bf3e09c76d81c2ca397bcc042fc3c13 100644 (file)
@@ -830,7 +830,7 @@ fail:
        return -ENODEV;
 }
 
-static int __devinit hdmi_probe(struct platform_device *pdev)
+static int hdmi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct resource *res;
@@ -979,7 +979,7 @@ fail:
        return ret;
 }
 
-static int __devexit hdmi_remove(struct platform_device *pdev)
+static int hdmi_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct v4l2_subdev *sd = dev_get_drvdata(dev);
@@ -997,7 +997,7 @@ static int __devexit hdmi_remove(struct platform_device *pdev)
 
 static struct platform_driver hdmi_driver __refdata = {
        .probe = hdmi_probe,
-       .remove = __devexit_p(hdmi_remove),
+       .remove = hdmi_remove,
        .id_table = hdmi_driver_types,
        .driver = {
                .name = "s5p-hdmi",
index f67b386318014c34dff3fdc13c9aa8815eaf1d13..06b5d2dbb2d9000294209a74c04d85606f5083c9 100644 (file)
@@ -279,8 +279,8 @@ static const struct v4l2_subdev_ops hdmiphy_ops = {
        .video = &hdmiphy_video_ops,
 };
 
-static int __devinit hdmiphy_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
+static int hdmiphy_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct hdmiphy_ctx *ctx;
 
@@ -295,7 +295,7 @@ static int __devinit hdmiphy_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit hdmiphy_remove(struct i2c_client *client)
+static int hdmiphy_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
@@ -322,7 +322,7 @@ static struct i2c_driver hdmiphy_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = hdmiphy_probe,
-       .remove         = __devexit_p(hdmiphy_remove),
+       .remove         = hdmiphy_remove,
        .id_table = hdmiphy_id,
 };
 
index ddb422e23550214df4877bd1767495723acab0a9..b671e20e9318abcb6e062c6648bc967485a20e01 100644 (file)
@@ -290,7 +290,7 @@ static inline struct v4l2_subdev *to_outsd(struct mxr_device *mdev)
 struct mxr_platform_data;
 
 /** acquiring common video resources */
-int __devinit mxr_acquire_video(struct mxr_device *mdev,
+int mxr_acquire_video(struct mxr_device *mdev,
        struct mxr_output_conf *output_cont, int output_count);
 
 /** releasing common video resources */
index ca0f2971744851e6ee9770fcc3227ad8c699be72..02faea03aa7d1679cbdefe5fe9b9b002c60abdfc 100644 (file)
@@ -151,8 +151,8 @@ void mxr_power_put(struct mxr_device *mdev)
 
 /* --------- RESOURCE MANAGEMENT -------------*/
 
-static int __devinit mxr_acquire_plat_resources(struct mxr_device *mdev,
-       struct platform_device *pdev)
+static int mxr_acquire_plat_resources(struct mxr_device *mdev,
+                                     struct platform_device *pdev)
 {
        struct resource *res;
        int ret;
@@ -271,8 +271,8 @@ fail:
        return -ENODEV;
 }
 
-static int __devinit mxr_acquire_resources(struct mxr_device *mdev,
-       struct platform_device *pdev)
+static int mxr_acquire_resources(struct mxr_device *mdev,
+                                struct platform_device *pdev)
 {
        int ret;
        ret = mxr_acquire_plat_resources(mdev, pdev);
@@ -310,8 +310,8 @@ static void mxr_release_layers(struct mxr_device *mdev)
                        mxr_layer_release(mdev->layer[i]);
 }
 
-static int __devinit mxr_acquire_layers(struct mxr_device *mdev,
-       struct mxr_platform_data *pdata)
+static int mxr_acquire_layers(struct mxr_device *mdev,
+                             struct mxr_platform_data *pdata)
 {
        mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
        mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
@@ -372,7 +372,7 @@ static const struct dev_pm_ops mxr_pm_ops = {
 
 /* --------- DRIVER INITIALIZATION ---------- */
 
-static int __devinit mxr_probe(struct platform_device *pdev)
+static int mxr_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct mxr_platform_data *pdata = dev->platform_data;
@@ -431,7 +431,7 @@ fail:
        return ret;
 }
 
-static int __devexit mxr_remove(struct platform_device *pdev)
+static int mxr_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct mxr_device *mdev = to_mdev(dev);
@@ -450,7 +450,7 @@ static int __devexit mxr_remove(struct platform_device *pdev)
 
 static struct platform_driver mxr_driver __refdata = {
        .probe = mxr_probe,
-       .remove = __devexit_p(mxr_remove),
+       .remove = mxr_remove,
        .driver = {
                .name = MXR_DRIVER_NAME,
                .owner = THIS_MODULE,
index 7379e77bf4e1daf1b89ae7a3b66ba24322c18942..1f3b7436511cee3331956c7e2f6f5a75b3e56d14 100644 (file)
@@ -62,8 +62,8 @@ done:
        return sd;
 }
 
-int __devinit mxr_acquire_video(struct mxr_device *mdev,
-       struct mxr_output_conf *output_conf, int output_count)
+int mxr_acquire_video(struct mxr_device *mdev,
+                     struct mxr_output_conf *output_conf, int output_count)
 {
        struct device *dev = mdev->dev;
        struct v4l2_device *v4l2_dev = &mdev->v4l2_dev;
index ad68bbed014e2c3a31119c0f4ea46c0317903b5f..91a6939a270a56a237b450c57fb26bd1977af4fc 100644 (file)
@@ -292,7 +292,7 @@ static const struct dev_pm_ops sdo_pm_ops = {
        .runtime_resume  = sdo_runtime_resume,
 };
 
-static int __devinit sdo_probe(struct platform_device *pdev)
+static int sdo_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct sdo_device *sdev;
@@ -419,7 +419,7 @@ fail:
        return ret;
 }
 
-static int __devexit sdo_remove(struct platform_device *pdev)
+static int sdo_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
        struct sdo_device *sdev = sd_to_sdev(sd);
@@ -437,7 +437,7 @@ static int __devexit sdo_remove(struct platform_device *pdev)
 
 static struct platform_driver sdo_driver __refdata = {
        .probe = sdo_probe,
-       .remove = __devexit_p(sdo_remove),
+       .remove = sdo_remove,
        .driver = {
                .name = "s5p-sdo",
                .owner = THIS_MODULE,
index 716d4846f8bdba7cadf04e992fc36ece0ffac226..49191aac96348fb1ffa4c5fe771dc2a797b09e32 100644 (file)
@@ -315,8 +315,8 @@ static const struct v4l2_subdev_ops sii9234_ops = {
        .video = &sii9234_video_ops,
 };
 
-static int __devinit sii9234_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
+static int sii9234_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct device *dev = &client->dev;
        struct sii9234_platform_data *pdata = dev->platform_data;
@@ -378,7 +378,7 @@ fail:
        return ret;
 }
 
-static int __devexit sii9234_remove(struct i2c_client *client)
+static int sii9234_remove(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -406,7 +406,7 @@ static struct i2c_driver sii9234_driver = {
                .pm = &sii9234_pm_ops,
        },
        .probe          = sii9234_probe,
-       .remove         = __devexit_p(sii9234_remove),
+       .remove         = sii9234_remove,
        .id_table = sii9234_id,
 };
 
index a1c87f0ceaabe0285ddd2d6b03dd3ead5303d22d..f3c4571ac01e65064b28ef8917b27380351c5350 100644 (file)
@@ -1326,7 +1326,7 @@ static const struct video_device sh_vou_video_template = {
        .vfl_dir        = VFL_DIR_TX,
 };
 
-static int __devinit sh_vou_probe(struct platform_device *pdev)
+static int sh_vou_probe(struct platform_device *pdev)
 {
        struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data;
        struct v4l2_rect *rect;
@@ -1461,7 +1461,7 @@ ereqmemreg:
        return ret;
 }
 
-static int __devexit sh_vou_remove(struct platform_device *pdev)
+static int sh_vou_remove(struct platform_device *pdev)
 {
        int irq = platform_get_irq(pdev, 0);
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
@@ -1487,7 +1487,7 @@ static int __devexit sh_vou_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver __refdata sh_vou = {
-       .remove  = __devexit_p(sh_vou_remove),
+       .remove  = sh_vou_remove,
        .driver  = {
                .name   = "sh-vou",
                .owner  = THIS_MODULE,
index 6274a91c25c74b711f30510a584056697edaa6ed..d96c8c7e01d9f41f04c461556c841243e59a057b 100644 (file)
@@ -897,7 +897,7 @@ static struct soc_camera_host_ops isi_soc_camera_host_ops = {
 };
 
 /* -----------------------------------------------------------------------*/
-static int __devexit atmel_isi_remove(struct platform_device *pdev)
+static int atmel_isi_remove(struct platform_device *pdev)
 {
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct atmel_isi *isi = container_of(soc_host,
@@ -921,7 +921,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit atmel_isi_probe(struct platform_device *pdev)
+static int atmel_isi_probe(struct platform_device *pdev)
 {
        unsigned int irq;
        struct atmel_isi *isi;
@@ -1074,7 +1074,7 @@ err_clk_prepare_pclk:
 
 static struct platform_driver atmel_isi_driver = {
        .probe          = atmel_isi_probe,
-       .remove         = __devexit_p(atmel_isi_remove),
+       .remove         = atmel_isi_remove,
        .driver         = {
                .name = "atmel_isi",
                .owner = THIS_MODULE,
index 791cd1d54a769c5321cca32d8fa7cc6665467324..8bda2c908aba3b17aa53dc44f96474aca76a284f 100644 (file)
@@ -1692,7 +1692,7 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit mx27_camera_emma_init(struct platform_device *pdev)
+static int mx27_camera_emma_init(struct platform_device *pdev)
 {
        struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev);
        struct resource *res_emma;
@@ -1750,7 +1750,7 @@ out:
        return err;
 }
 
-static int __devinit mx2_camera_probe(struct platform_device *pdev)
+static int mx2_camera_probe(struct platform_device *pdev)
 {
        struct mx2_camera_dev *pcdev;
        struct resource *res_csi;
@@ -1887,7 +1887,7 @@ exit:
        return err;
 }
 
-static int __devexit mx2_camera_remove(struct platform_device *pdev)
+static int mx2_camera_remove(struct platform_device *pdev)
 {
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct mx2_camera_dev *pcdev = container_of(soc_host,
@@ -1912,7 +1912,7 @@ static struct platform_driver mx2_camera_driver = {
                .name   = MX2_CAM_DRV_NAME,
        },
        .id_table       = mx2_camera_devtype,
-       .remove         = __devexit_p(mx2_camera_remove),
+       .remove         = mx2_camera_remove,
 };
 
 
index 06d16de763773b54f11941a73e2806fcbad30dab..45aef1053a49834c3515ee8093e99ceb0ea1b85a 100644 (file)
@@ -1143,7 +1143,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
        .set_bus_param  = mx3_camera_set_bus_param,
 };
 
-static int __devinit mx3_camera_probe(struct platform_device *pdev)
+static int mx3_camera_probe(struct platform_device *pdev)
 {
        struct mx3_camera_dev *mx3_cam;
        struct resource *res;
@@ -1246,7 +1246,7 @@ egetres:
        return err;
 }
 
-static int __devexit mx3_camera_remove(struct platform_device *pdev)
+static int mx3_camera_remove(struct platform_device *pdev)
 {
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct mx3_camera_dev *mx3_cam = container_of(soc_host,
@@ -1279,7 +1279,7 @@ static struct platform_driver mx3_camera_driver = {
                .name   = MX3_CAM_DRV_NAME,
        },
        .probe          = mx3_camera_probe,
-       .remove         = __devexit_p(mx3_camera_remove),
+       .remove         = mx3_camera_remove,
 };
 
 module_platform_driver(mx3_camera_driver);
index 3434ffe79c6ecc445a8b451dc2c55767b552c217..523330d00deeb08de48b525df93c8f71c29d6005 100644 (file)
@@ -1651,7 +1651,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
        .set_bus_param  = pxa_camera_set_bus_param,
 };
 
-static int __devinit pxa_camera_probe(struct platform_device *pdev)
+static int pxa_camera_probe(struct platform_device *pdev)
 {
        struct pxa_camera_dev *pcdev;
        struct resource *res;
@@ -1801,7 +1801,7 @@ exit:
        return err;
 }
 
-static int __devexit pxa_camera_remove(struct platform_device *pdev)
+static int pxa_camera_remove(struct platform_device *pdev)
 {
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct pxa_camera_dev *pcdev = container_of(soc_host,
@@ -1840,7 +1840,7 @@ static struct platform_driver pxa_camera_driver = {
                .pm     = &pxa_camera_pm,
        },
        .probe          = pxa_camera_probe,
-       .remove         = __devexit_p(pxa_camera_remove),
+       .remove         = pxa_camera_remove,
 };
 
 module_platform_driver(pxa_camera_driver);
index 2d8861c0e8f2c23baae9908a0fdf2955e458ead3..ebbc126e71a6e409fda2cf5d798441531b004659 100644 (file)
@@ -2071,7 +2071,7 @@ static int bus_notify(struct notifier_block *nb,
        return NOTIFY_DONE;
 }
 
-static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
+static int sh_mobile_ceu_probe(struct platform_device *pdev)
 {
        struct sh_mobile_ceu_dev *pcdev;
        struct resource *res;
@@ -2258,7 +2258,7 @@ exit:
        return err;
 }
 
-static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev)
+static int sh_mobile_ceu_remove(struct platform_device *pdev)
 {
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
@@ -2307,7 +2307,7 @@ static struct platform_driver sh_mobile_ceu_driver = {
                .pm     = &sh_mobile_ceu_dev_pm_ops,
        },
        .probe          = sh_mobile_ceu_probe,
-       .remove         = __devexit_p(sh_mobile_ceu_remove),
+       .remove         = sh_mobile_ceu_remove,
 };
 
 static int __init sh_mobile_ceu_init(void)
index 05286500b4d432de590fa206070c2611bcb57a5a..a17aba9a0104c41cbc4e5e5d277010ecac577600 100644 (file)
@@ -294,7 +294,7 @@ static struct v4l2_subdev_ops sh_csi2_subdev_ops = {
        .video  = &sh_csi2_subdev_video_ops,
 };
 
-static __devinit int sh_csi2_probe(struct platform_device *pdev)
+static int sh_csi2_probe(struct platform_device *pdev)
 {
        struct resource *res;
        unsigned int irq;
@@ -366,7 +366,7 @@ ereqreg:
        return ret;
 }
 
-static __devexit int sh_csi2_remove(struct platform_device *pdev)
+static int sh_csi2_remove(struct platform_device *pdev)
 {
        struct sh_csi2 *priv = platform_get_drvdata(pdev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -382,7 +382,7 @@ static __devexit int sh_csi2_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver __refdata sh_csi2_pdrv = {
-       .remove = __devexit_p(sh_csi2_remove),
+       .remove = sh_csi2_remove,
        .probe  = sh_csi2_probe,
        .driver = {
                .name   = "sh-mobile-csi2",
index 4e3735679f172fa3daf9620e3364a26987649da3..2ec90eae6ba0e01c34e5d837749e3aa9e3ad4dca 100644 (file)
@@ -1530,7 +1530,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
        return 0;
 }
 
-static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
+static int soc_camera_pdrv_probe(struct platform_device *pdev)
 {
        struct soc_camera_link *icl = pdev->dev.platform_data;
        struct soc_camera_device *icd;
@@ -1558,7 +1558,7 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
  * hot-pluggable. Now we know, that all our users - hosts and devices have
  * been unloaded already
  */
-static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
+static int soc_camera_pdrv_remove(struct platform_device *pdev)
 {
        struct soc_camera_device *icd = platform_get_drvdata(pdev);
 
@@ -1572,7 +1572,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
 
 static struct platform_driver __refdata soc_camera_pdrv = {
        .probe = soc_camera_pdrv_probe,
-       .remove  = __devexit_p(soc_camera_pdrv_remove),
+       .remove  = soc_camera_pdrv_remove,
        .driver  = {
                .name   = "soc-camera-pdrv",
                .owner  = THIS_MODULE,
index 02194c056b005f601d5d6743221f38c7f67971ab..d854d08a6c7f5f2c1e152215acc3daceb74bfc0b 100644 (file)
@@ -745,7 +745,7 @@ static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
 
 /* Platform device functions */
 
-static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
+static struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
        .vidioc_querycap                = timblogiw_querycap,
        .vidioc_enum_fmt_vid_cap        = timblogiw_enum_fmt,
        .vidioc_g_fmt_vid_cap           = timblogiw_g_fmt,
@@ -767,7 +767,7 @@ static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
        .vidioc_enum_framesizes         = timblogiw_enum_framesizes,
 };
 
-static __devinitconst struct v4l2_file_operations timblogiw_fops = {
+static struct v4l2_file_operations timblogiw_fops = {
        .owner          = THIS_MODULE,
        .open           = timblogiw_open,
        .release        = timblogiw_close,
@@ -777,7 +777,7 @@ static __devinitconst struct v4l2_file_operations timblogiw_fops = {
        .poll           = timblogiw_poll,
 };
 
-static __devinitconst struct video_device timblogiw_template = {
+static struct video_device timblogiw_template = {
        .name           = TIMBLOGIWIN_NAME,
        .fops           = &timblogiw_fops,
        .ioctl_ops      = &timblogiw_ioctl_ops,
@@ -786,7 +786,7 @@ static __devinitconst struct video_device timblogiw_template = {
        .tvnorms        = V4L2_STD_PAL | V4L2_STD_NTSC
 };
 
-static int __devinit timblogiw_probe(struct platform_device *pdev)
+static int timblogiw_probe(struct platform_device *pdev)
 {
        int err;
        struct timblogiw *lw = NULL;
@@ -848,7 +848,7 @@ err:
        return err;
 }
 
-static int __devexit timblogiw_remove(struct platform_device *pdev)
+static int timblogiw_remove(struct platform_device *pdev)
 {
        struct timblogiw *lw = platform_get_drvdata(pdev);
 
@@ -869,7 +869,7 @@ static struct platform_driver timblogiw_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = timblogiw_probe,
-       .remove         = __devexit_p(timblogiw_remove),
+       .remove         = timblogiw_remove,
 };
 
 module_platform_driver(timblogiw_platform_driver);
index eb404c2ce27043489a80ebfe1cbff114f55438ae..63e8c34612392fa808e2921ebcb7754902dde36e 100644 (file)
@@ -1324,7 +1324,7 @@ static struct video_device viacam_v4l_template = {
 #define VIACAM_SERIAL_CREG 0x46
 #define VIACAM_SERIAL_BIT 0x40
 
-static __devinit bool viacam_serial_is_enabled(void)
+static bool viacam_serial_is_enabled(void)
 {
        struct pci_bus *pbus = pci_find_bus(0, 0);
        u8 cbyte;
@@ -1353,7 +1353,7 @@ static struct ov7670_config sensor_cfg = {
        .clock_speed = 90,
 };
 
-static __devinit int viacam_probe(struct platform_device *pdev)
+static int viacam_probe(struct platform_device *pdev)
 {
        int ret;
        struct i2c_adapter *sensor_adapter;
@@ -1490,7 +1490,7 @@ out_unregister:
        return ret;
 }
 
-static __devexit int viacam_remove(struct platform_device *pdev)
+static int viacam_remove(struct platform_device *pdev)
 {
        struct via_camera *cam = via_cam_info;
        struct viafb_dev *viadev = pdev->dev.platform_data;
index e10e525f33e51f0a14b5c3f5b7ef0006ae3524cb..296941a9ae25decc88dd4d0da8b2240319eb2b34 100644 (file)
@@ -374,6 +374,7 @@ static int usb_keene_probe(struct usb_interface *intf,
        radio->vdev.ioctl_ops = &usb_keene_ioctl_ops;
        radio->vdev.lock = &radio->lock;
        radio->vdev.release = video_device_release_empty;
+       radio->vdev.vfl_dir = VFL_DIR_TX;
 
        radio->usbdev = interface_to_usbdev(intf);
        radio->intf = intf;
index b415211d0c4bee08a38093f3ddb11c9e9918a79e..bd4d3a7cdadd130511cc186679124fd6231a929c 100644 (file)
@@ -114,7 +114,8 @@ static struct snd_tea575x_ops maxiradio_tea_ops = {
        .set_direction = maxiradio_tea575x_set_direction,
 };
 
-static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int maxiradio_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct maxiradio *dev;
        struct v4l2_device *v4l2_dev;
@@ -172,7 +173,7 @@ errfr:
        return retval;
 }
 
-static void __devexit maxiradio_remove(struct pci_dev *pdev)
+static void maxiradio_remove(struct pci_dev *pdev)
 {
        struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
        struct maxiradio *dev = to_maxiradio(v4l2_dev);
@@ -196,7 +197,7 @@ static struct pci_driver maxiradio_driver = {
        .name           = "radio-maxiradio",
        .id_table       = maxiradio_pci_tbl,
        .probe          = maxiradio_probe,
-       .remove         = __devexit_p(maxiradio_remove),
+       .remove         = maxiradio_remove,
 };
 
 static int __init maxiradio_init(void)
index c260a2a354b1d0ab7eabaa3c0166c44df1682c67..637a555649582e1ed8aaa9913d4c66ea47318b0d 100644 (file)
@@ -265,7 +265,7 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
 };
 
 /* ladis: this is my card. does any other types exist? */
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
                /* SF16-FMI */
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
                ISAPNP_VENDOR('M','F','R'), ISAPNP_FUNCTION(0xad10), 0},
index 4efcbec74c52dd0f63532891f4f7ff8e7176e83e..9c0990457a7cd9b6982475072888d7de82fe548c 100644 (file)
@@ -197,13 +197,13 @@ static int fmr2_tea_ext_init(struct snd_tea575x *tea)
        return 0;
 }
 
-static struct pnp_device_id fmr2_pnp_ids[] __devinitdata = {
+static struct pnp_device_id fmr2_pnp_ids[] = {
        { .id = "MFRad13" }, /* tuner subdevice of SF16-FMD2 */
        { .id = "" }
 };
 MODULE_DEVICE_TABLE(pnp, fmr2_pnp_ids);
 
-static int __devinit fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io)
+static int fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io)
 {
        int err, i;
        char *card_name = fmr2->is_fmd2 ? "SF16-FMD2" : "SF16-FMR2";
@@ -249,7 +249,7 @@ static int __devinit fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io)
        return 0;
 }
 
-static int __devinit fmr2_isa_match(struct device *pdev, unsigned int ndev)
+static int fmr2_isa_match(struct device *pdev, unsigned int ndev)
 {
        struct fmr2 *fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL);
        if (!fmr2)
@@ -265,8 +265,7 @@ static int __devinit fmr2_isa_match(struct device *pdev, unsigned int ndev)
        return 1;
 }
 
-static int __devinit fmr2_pnp_probe(struct pnp_dev *pdev,
-                               const struct pnp_device_id *id)
+static int fmr2_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
 {
        int ret;
        struct fmr2 *fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL);
@@ -285,7 +284,7 @@ static int __devinit fmr2_pnp_probe(struct pnp_dev *pdev,
        return 0;
 }
 
-static void __devexit fmr2_remove(struct fmr2 *fmr2)
+static void fmr2_remove(struct fmr2 *fmr2)
 {
        snd_tea575x_exit(&fmr2->tea);
        release_region(fmr2->io, 2);
@@ -293,7 +292,7 @@ static void __devexit fmr2_remove(struct fmr2 *fmr2)
        kfree(fmr2);
 }
 
-static int __devexit fmr2_isa_remove(struct device *pdev, unsigned int ndev)
+static int fmr2_isa_remove(struct device *pdev, unsigned int ndev)
 {
        fmr2_remove(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
@@ -301,7 +300,7 @@ static int __devexit fmr2_isa_remove(struct device *pdev, unsigned int ndev)
        return 0;
 }
 
-static void __devexit fmr2_pnp_remove(struct pnp_dev *pdev)
+static void fmr2_pnp_remove(struct pnp_dev *pdev)
 {
        fmr2_remove(pnp_get_drvdata(pdev));
        pnp_set_drvdata(pdev, NULL);
@@ -309,7 +308,7 @@ static void __devexit fmr2_pnp_remove(struct pnp_dev *pdev)
 
 struct isa_driver fmr2_isa_driver = {
        .match          = fmr2_isa_match,
-       .remove         = __devexit_p(fmr2_isa_remove),
+       .remove         = fmr2_isa_remove,
        .driver         = {
                .name   = "radio-sf16fmr2",
        },
@@ -319,7 +318,7 @@ struct pnp_driver fmr2_pnp_driver = {
        .name           = "radio-sf16fmr2",
        .id_table       = fmr2_pnp_ids,
        .probe          = fmr2_pnp_probe,
-       .remove         = __devexit_p(fmr2_pnp_remove),
+       .remove         = fmr2_pnp_remove,
 };
 
 static int __init fmr2_init(void)
index a082e400ed0f6ed8022fd3562231e5cc969c10d2..1507c9d508d7c59e98ea0f58cbc017726b3329c5 100644 (file)
@@ -250,6 +250,7 @@ static struct video_device radio_si4713_vdev_template = {
        .name                   = "radio-si4713",
        .release                = video_device_release,
        .ioctl_ops              = &radio_si4713_ioctl_ops,
+       .vfl_dir                = VFL_DIR_TX,
 };
 
 /* Platform driver interface */
index 36aec575e0ecd37e3ad7ddab10735684ad1c951b..1978516af67e01510fc849f006dcfdd0d59ba2a1 100644 (file)
@@ -493,8 +493,8 @@ static struct video_device tea5764_radio_template = {
 };
 
 /* I2C probe: check if the device exists and register with v4l if it is */
-static int __devinit tea5764_i2c_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
+static int tea5764_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
 {
        struct tea5764_device *radio;
        struct tea5764_regs *r;
@@ -552,7 +552,7 @@ errfr:
        return ret;
 }
 
-static int __devexit tea5764_i2c_remove(struct i2c_client *client)
+static int tea5764_i2c_remove(struct i2c_client *client)
 {
        struct tea5764_device *radio = i2c_get_clientdata(client);
 
@@ -578,7 +578,7 @@ static struct i2c_driver tea5764_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tea5764_i2c_probe,
-       .remove = __devexit_p(tea5764_i2c_remove),
+       .remove = tea5764_i2c_remove,
        .id_table = tea5764_id,
 };
 
index 5cf07779f4bb2b1ccddad9756f772184e036bed3..b87effeb5dc607ea57bf08bd1ca17cd0afabefff 100644 (file)
@@ -145,7 +145,7 @@ static const struct v4l2_file_operations timbradio_fops = {
        .unlocked_ioctl = video_ioctl2,
 };
 
-static int __devinit timbradio_probe(struct platform_device *pdev)
+static int timbradio_probe(struct platform_device *pdev)
 {
        struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
        struct timbradio *tr;
@@ -201,7 +201,7 @@ err:
        return err;
 }
 
-static int __devexit timbradio_remove(struct platform_device *pdev)
+static int timbradio_remove(struct platform_device *pdev)
 {
        struct timbradio *tr = platform_get_drvdata(pdev);
 
@@ -219,7 +219,7 @@ static struct platform_driver timbradio_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = timbradio_probe,
-       .remove         = __devexit_p(timbradio_remove),
+       .remove         = timbradio_remove,
 };
 
 module_platform_driver(timbradio_platform_driver);
index 9b0c9fa0beb80307ac0a4b95785a2aaaa50fb0f3..cabbe3adf435b6a9f3ef2176109489524565513f 100644 (file)
@@ -1971,6 +1971,7 @@ static struct video_device wl1273_viddev_template = {
        .ioctl_ops              = &wl1273_ioctl_ops,
        .name                   = WL1273_FM_DRIVER_NAME,
        .release                = wl1273_vdev_release,
+       .vfl_dir                = VFL_DIR_TX,
 };
 
 static int wl1273_fm_radio_remove(struct platform_device *pdev)
@@ -1990,7 +1991,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
+static int wl1273_fm_radio_probe(struct platform_device *pdev)
 {
        struct wl1273_core **core = pdev->dev.platform_data;
        struct wl1273_device *radio;
@@ -2145,7 +2146,7 @@ pdata_err:
 
 static struct platform_driver wl1273_fm_radio_driver = {
        .probe          = wl1273_fm_radio_probe,
-       .remove         = __devexit_p(wl1273_fm_radio_remove),
+       .remove         = wl1273_fm_radio_remove,
        .driver         = {
                .name   = "wl1273_fm_radio",
                .owner  = THIS_MODULE,
index 54db36ccb9ee2bb23d3e9615fe7c5b8a7e0967ef..06c06cc9ff254ef767d96dae23ab40912c24d035 100644 (file)
@@ -373,8 +373,8 @@ static const struct v4l2_subdev_ops saa7706h_ops = {
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int __devinit saa7706h_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int saa7706h_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct saa7706h_state *state;
        struct v4l2_subdev *sd;
@@ -418,7 +418,7 @@ err:
        return err;
 }
 
-static int __devexit saa7706h_remove(struct i2c_client *client)
+static int saa7706h_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
@@ -441,7 +441,7 @@ static struct i2c_driver saa7706h_driver = {
                .name   = DRIVER_NAME,
        },
        .probe          = saa7706h_probe,
-       .remove         = __devexit_p(saa7706h_remove),
+       .remove         = saa7706h_remove,
        .id_table       = saa7706h_id,
 };
 
index 4ef55ec8045e432fcc9576e130e902bc92446bed..e5fc9acd0c4f5debdc03cb4645ac2cd3f2a23c6b 100644 (file)
@@ -347,8 +347,8 @@ end:
 /*
  * si470x_i2c_probe - probe for the device
  */
-static int __devinit si470x_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int si470x_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
 {
        struct si470x_device *radio;
        int retval = 0;
@@ -451,7 +451,7 @@ err_initial:
 /*
  * si470x_i2c_remove - remove the device
  */
-static __devexit int si470x_i2c_remove(struct i2c_client *client)
+static int si470x_i2c_remove(struct i2c_client *client)
 {
        struct si470x_device *radio = i2c_get_clientdata(client);
 
@@ -514,7 +514,7 @@ static struct i2c_driver si470x_i2c_driver = {
 #endif
        },
        .probe                  = si470x_i2c_probe,
-       .remove                 = __devexit_p(si470x_i2c_remove),
+       .remove                 = si470x_i2c_remove,
        .id_table               = si470x_i2c_id,
 };
 
index 06d47e5cce9f31433263bde7987033180d427f79..b18c2dc268bab2705ee6cd88cdcea9bb970c71aa 100644 (file)
@@ -165,8 +165,8 @@ static const struct v4l2_subdev_ops tef6862_ops = {
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int __devinit tef6862_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int tef6862_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct tef6862_state *state;
        struct v4l2_subdev *sd;
@@ -189,7 +189,7 @@ static int __devinit tef6862_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit tef6862_remove(struct i2c_client *client)
+static int tef6862_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
@@ -211,7 +211,7 @@ static struct i2c_driver tef6862_driver = {
                .name   = DRIVER_NAME,
        },
        .probe          = tef6862_probe,
-       .remove         = __devexit_p(tef6862_remove),
+       .remove         = tef6862_remove,
        .id_table       = tef6862_id,
 };
 
index 048de45360360251095639d1422f9931853d3fba..0a8ee8fab9242476c14c153b0cc00b51387a7b26 100644 (file)
@@ -518,6 +518,16 @@ static struct video_device fm_viddev_template = {
        .ioctl_ops = &fm_drv_ioctl_ops,
        .name = FM_DRV_NAME,
        .release = video_device_release,
+       /*
+        * To ensure both the tuner and modulator ioctls are accessible we
+        * set the vfl_dir to M2M to indicate this.
+        *
+        * It is not really a mem2mem device of course, but it can both receive
+        * and transmit using the same radio device. It's the only radio driver
+        * that does this and it should really be split in two radio devices,
+        * but that would affect applications using this driver.
+        */
+       .vfl_dir = VFL_DIR_M2M,
 };
 
 int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
index 22231dd4f62b9432039bc41fdf954c86d60415b0..cef04786b52f57bc69eec2658a8712d75ccfd8ee 100644 (file)
@@ -1172,7 +1172,7 @@ static struct pnp_driver ene_driver = {
        .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
 
        .probe = ene_probe,
-       .remove = __devexit_p(ene_remove),
+       .remove = ene_remove,
 #ifdef CONFIG_PM
        .suspend = ene_suspend,
        .resume = ene_resume,
index 936c3f79b62cba500b8e53ba4adffb899bfda007..1df410e136881f3cafad5777bc84096771bc3027 100644 (file)
@@ -590,7 +590,7 @@ failure:
        return ret;
 }
 
-static void __devexit fintek_remove(struct pnp_dev *pdev)
+static void fintek_remove(struct pnp_dev *pdev)
 {
        struct fintek_dev *fintek = pnp_get_drvdata(pdev);
        unsigned long flags;
@@ -678,7 +678,7 @@ static struct pnp_driver fintek_driver = {
        .id_table       = fintek_ids,
        .flags          = PNP_DRIVER_RES_DO_NOT_CHANGE,
        .probe          = fintek_probe,
-       .remove         = __devexit_p(fintek_remove),
+       .remove         = fintek_remove,
        .suspend        = fintek_suspend,
        .resume         = fintek_resume,
        .shutdown       = fintek_shutdown,
index ba1a1eb356cf765d47d48b0e829f37b0133b5259..4f71a7d1f0196f73b2b3547fa30b75eb7afd4bca 100644 (file)
@@ -58,7 +58,7 @@ err_get_value:
        return IRQ_HANDLED;
 }
 
-static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
+static int gpio_ir_recv_probe(struct platform_device *pdev)
 {
        struct gpio_rc_dev *gpio_dev;
        struct rc_dev *rcdev;
@@ -140,7 +140,7 @@ err_allocate_device:
        return rc;
 }
 
-static int __devexit gpio_ir_recv_remove(struct platform_device *pdev)
+static int gpio_ir_recv_remove(struct platform_device *pdev)
 {
        struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
 
@@ -188,7 +188,7 @@ static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
 
 static struct platform_driver gpio_ir_recv_driver = {
        .probe  = gpio_ir_recv_probe,
-       .remove = __devexit_p(gpio_ir_recv_remove),
+       .remove = gpio_ir_recv_remove,
        .driver = {
                .name   = GPIO_IR_DRIVER_NAME,
                .owner  = THIS_MODULE,
index 5a9163da63c36c2fbf8527996d9b24134d5ba79e..b99b096d8a8f11d834b82f36061b47599d687712 100644 (file)
@@ -425,8 +425,8 @@ static void iguanair_close(struct rc_dev *rdev)
        mutex_unlock(&ir->lock);
 }
 
-static int __devinit iguanair_probe(struct usb_interface *intf,
-                                               const struct usb_device_id *id)
+static int iguanair_probe(struct usb_interface *intf,
+                         const struct usb_device_id *id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct iguanair *ir;
@@ -538,7 +538,7 @@ out:
        return ret;
 }
 
-static void __devexit iguanair_disconnect(struct usb_interface *intf)
+static void iguanair_disconnect(struct usb_interface *intf)
 {
        struct iguanair *ir = usb_get_intfdata(intf);
 
@@ -604,7 +604,7 @@ static const struct usb_device_id iguanair_table[] = {
 static struct usb_driver iguanair_driver = {
        .name = DRIVER_NAME,
        .probe = iguanair_probe,
-       .disconnect = __devexit_p(iguanair_disconnect),
+       .disconnect = iguanair_disconnect,
        .suspend = iguanair_suspend,
        .resume = iguanair_resume,
        .reset_resume = iguanair_resume,
index 8f6a28921ed413c718c0efea9ea70e437d2ac9d7..78d109b978ddde799030f20301f4baba97150f0e 100644 (file)
@@ -255,7 +255,7 @@ static struct usb_device_id imon_usb_id_table[] = {
 static struct usb_driver imon_driver = {
        .name           = MOD_NAME,
        .probe          = imon_probe,
-       .disconnect     = __devexit_p(imon_disconnect),
+       .disconnect     = imon_disconnect,
        .suspend        = imon_suspend,
        .resume         = imon_resume,
        .id_table       = imon_usb_id_table,
@@ -2288,8 +2288,8 @@ static void imon_init_display(struct imon_context *ictx,
 /**
  * Callback function for USB core API: Probe
  */
-static int __devinit imon_probe(struct usb_interface *interface,
-                               const struct usb_device_id *id)
+static int imon_probe(struct usb_interface *interface,
+                     const struct usb_device_id *id)
 {
        struct usb_device *usbdev = NULL;
        struct usb_host_interface *iface_desc = NULL;
@@ -2372,7 +2372,7 @@ fail:
 /**
  * Callback function for USB core API: disconnect
  */
-static void __devexit imon_disconnect(struct usb_interface *interface)
+static void imon_disconnect(struct usb_interface *interface)
 {
        struct imon_context *ictx;
        struct device *dev;
index 9e76c7b40af2f63430d69f25299307164b7daf17..8ead492d03aac905f2d1007bd22173c57ab3fc1c 100644 (file)
@@ -443,7 +443,7 @@ static int lirc_rx51_resume(struct platform_device *dev)
 
 #endif /* CONFIG_PM */
 
-static int __devinit lirc_rx51_probe(struct platform_device *dev)
+static int lirc_rx51_probe(struct platform_device *dev)
 {
        lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
        lirc_rx51.pdata = dev->dev.platform_data;
index 5e5a7f2b8184cc992fab2bf0e3e90cb09c65c154..1b8669b6d042ce1110710fdc4a049521733e0c40 100644 (file)
@@ -1620,7 +1620,7 @@ failure:
        return ret;
 }
 
-static void __devexit ite_remove(struct pnp_dev *pdev)
+static void ite_remove(struct pnp_dev *pdev)
 {
        struct ite_dev *dev = pnp_get_drvdata(pdev);
        unsigned long flags;
@@ -1702,7 +1702,7 @@ static struct pnp_driver ite_driver = {
        .name           = ITE_DRIVER_NAME,
        .id_table       = ite_ids,
        .probe          = ite_probe,
-       .remove         = __devexit_p(ite_remove),
+       .remove         = ite_remove,
        .suspend        = ite_suspend,
        .resume         = ite_resume,
        .shutdown       = ite_shutdown,
index b2146cd99fd8a74f65a57c7b11886b27764f8272..9afb9331217ddebe9cb8e122e67473563b0aadc9 100644 (file)
@@ -1229,8 +1229,8 @@ out:
        return NULL;
 }
 
-static int __devinit mceusb_dev_probe(struct usb_interface *intf,
-                                     const struct usb_device_id *id)
+static int mceusb_dev_probe(struct usb_interface *intf,
+                           const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
        struct usb_host_interface *idesc;
@@ -1393,7 +1393,7 @@ mem_alloc_fail:
 }
 
 
-static void __devexit mceusb_dev_disconnect(struct usb_interface *intf)
+static void mceusb_dev_disconnect(struct usb_interface *intf)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
        struct mceusb_dev *ir = usb_get_intfdata(intf);
@@ -1432,7 +1432,7 @@ static int mceusb_dev_resume(struct usb_interface *intf)
 static struct usb_driver mceusb_dev_driver = {
        .name =         DRIVER_NAME,
        .probe =        mceusb_dev_probe,
-       .disconnect =   __devexit_p(mceusb_dev_disconnect),
+       .disconnect =   mceusb_dev_disconnect,
        .suspend =      mceusb_dev_suspend,
        .resume =       mceusb_dev_resume,
        .reset_resume = mceusb_dev_resume,
index e4ea89a11eed451efd967b36a41a4fbbf5a7edf0..b8aa9abb31ffe03161b0a8b99f273afcd8d05df5 100644 (file)
@@ -1113,7 +1113,7 @@ failure:
        return ret;
 }
 
-static void __devexit nvt_remove(struct pnp_dev *pdev)
+static void nvt_remove(struct pnp_dev *pdev)
 {
        struct nvt_dev *nvt = pnp_get_drvdata(pdev);
        unsigned long flags;
@@ -1211,7 +1211,7 @@ static struct pnp_driver nvt_driver = {
        .id_table       = nvt_ids,
        .flags          = PNP_DRIVER_RES_DO_NOT_CHANGE,
        .probe          = nvt_probe,
-       .remove         = __devexit_p(nvt_remove),
+       .remove         = nvt_remove,
        .suspend        = nvt_suspend,
        .resume         = nvt_resume,
        .shutdown       = nvt_shutdown,
index a8887aba9fafe9483267f9122d0b8e39929b5c8c..1800326f93e60a1f30301c2979fadcc8e261c304 100644 (file)
@@ -1102,8 +1102,8 @@ out:
        return NULL;
 }
 
-static int __devinit redrat3_dev_probe(struct usb_interface *intf,
-                                      const struct usb_device_id *id)
+static int redrat3_dev_probe(struct usb_interface *intf,
+                            const struct usb_device_id *id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct device *dev = &intf->dev;
@@ -1241,7 +1241,7 @@ no_endpoints:
        return retval;
 }
 
-static void __devexit redrat3_dev_disconnect(struct usb_interface *intf)
+static void redrat3_dev_disconnect(struct usb_interface *intf)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct redrat3_dev *rr3 = usb_get_intfdata(intf);
@@ -1281,7 +1281,7 @@ static int redrat3_dev_resume(struct usb_interface *intf)
 static struct usb_driver redrat3_dev_driver = {
        .name           = DRIVER_NAME,
        .probe          = redrat3_dev_probe,
-       .disconnect     = __devexit_p(redrat3_dev_disconnect),
+       .disconnect     = redrat3_dev_disconnect,
        .suspend        = redrat3_dev_suspend,
        .resume         = redrat3_dev_resume,
        .reset_resume   = redrat3_dev_resume,
index c720f12f661e5121c7ad0e5d9ba77e13f43d5013..d7b11e6a998253dd362654ed468edcb11cfef103 100644 (file)
@@ -346,8 +346,8 @@ out:
  *     On any failure the return value is the ERROR
  *     On success return 0
  */
-static int __devinit streamzap_probe(struct usb_interface *intf,
-                                    const struct usb_device_id *id)
+static int streamzap_probe(struct usb_interface *intf,
+                          const struct usb_device_id *id)
 {
        struct usb_device *usbdev = interface_to_usbdev(intf);
        struct usb_host_interface *iface_host;
index f0921b5483ebdd34bd967d8f03434c2d843e86b8..78be8a91422533d7c6396dabadabb7af148a31a9 100644 (file)
@@ -194,8 +194,8 @@ static void ttusbir_urb_complete(struct urb *urb)
                dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc);
 }
 
-static int __devinit ttusbir_probe(struct usb_interface *intf,
-                                               const struct usb_device_id *id)
+static int ttusbir_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
 {
        struct ttusbir *tt;
        struct usb_interface_descriptor *idesc;
@@ -367,7 +367,7 @@ out:
        return ret;
 }
 
-static void __devexit ttusbir_disconnect(struct usb_interface *intf)
+static void ttusbir_disconnect(struct usb_interface *intf)
 {
        struct ttusbir *tt = usb_get_intfdata(intf);
        struct usb_device *udev = tt->udev;
@@ -435,7 +435,7 @@ static struct usb_driver ttusbir_driver = {
        .suspend = ttusbir_suspend,
        .resume = ttusbir_resume,
        .reset_resume = ttusbir_resume,
-       .disconnect = __devexit_p(ttusbir_disconnect)
+       .disconnect = ttusbir_disconnect,
 };
 
 module_usb_driver(ttusbir_driver);
index 7f3c476dde05fb712cbb0fbbbc55c36e3150aba4..930c61499037090af51d788e6019be955394e347 100644 (file)
@@ -1008,7 +1008,7 @@ wbcir_resume(struct pnp_dev *device)
        return 0;
 }
 
-static int __devinit
+static int
 wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 {
        struct device *dev = &device->dev;
@@ -1155,7 +1155,7 @@ exit:
        return err;
 }
 
-static void __devexit
+static void
 wbcir_remove(struct pnp_dev *device)
 {
        struct wbcir_data *data = pnp_get_drvdata(device);
@@ -1201,7 +1201,7 @@ static struct pnp_driver wbcir_driver = {
        .name     = WBCIR_NAME,
        .id_table = wbcir_ids,
        .probe    = wbcir_probe,
-       .remove   = __devexit_p(wbcir_remove),
+       .remove   = wbcir_remove,
        .suspend  = wbcir_suspend,
        .resume   = wbcir_resume,
        .shutdown = wbcir_shutdown
index 40ad6687ee5dee1e53cad6489a386438f5d2a483..3773a8a745df9323719d4aaeb6dd949fa0e61cad 100644 (file)
@@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x045e, 0x02ae)},
+       {USB_DEVICE(0x045e, 0x02bf)},
        {}
 };
 
index 70511d5f953857492aca04655cdf079836a998dc..1220340e76028654385ec448c7a98a310d3d89f6 100644 (file)
@@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        }
 }
 
-static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf)
 {
        int retry = 60;
 
@@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
                return;
 
        /* is i2c ready */
-       reg_w(gspca_dev, 0x08, buffer, 8);
+       reg_w(gspca_dev, 0x08, buf, 8);
        while (retry--) {
                if (gspca_dev->usb_err < 0)
                        return;
-               msleep(10);
+               msleep(1);
                reg_r(gspca_dev, 0x08);
                if (gspca_dev->usb_buf[0] & 0x04) {
                        if (gspca_dev->usb_buf[0] & 0x08) {
                                dev_err(gspca_dev->v4l2_dev.dev,
-                                       "i2c write error\n");
+                                       "i2c error writing %02x %02x %02x %02x"
+                                       " %02x %02x %02x %02x\n",
+                                       buf[0], buf[1], buf[2], buf[3],
+                                       buf[4], buf[5], buf[6], buf[7]);
                                gspca_dev->usb_err = -EIO;
                        }
                        return;
@@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev,
        for (;;) {
                if (gspca_dev->usb_err < 0)
                        return;
-               reg_w(gspca_dev, 0x08, *buffer, 8);
+               i2c_w(gspca_dev, *buffer);
                len -= 8;
                if (len <= 0)
                        break;
index 5a86047b846f484c2d1c22d88023878d2249b646..36307a9028a932b6414523e0a189c613479daa90 100644 (file)
@@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
                        0,
                        gspca_dev->usb_buf, 8,
                        500);
+       msleep(2);
        if (ret < 0) {
                pr_err("i2c_w1 err %d\n", ret);
                gspca_dev->usb_err = ret;
index bab01c86c3154933c819d941bbcfe3c6ffea60ef..bcd2c04c770e919d86473adc6282e8f5b0f11c4e 100644 (file)
@@ -590,8 +590,7 @@ static const struct usb_device_id device_table[] = {
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int __devinit sd_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
+static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
                                THIS_MODULE);
index aac622200e99a9e244523b8ead9994d510cac891..de2c10289eecc3d109b534c7bf8b68499c1ec023 100644 (file)
@@ -389,7 +389,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
        return rc;
 }
 
-static int __devinit smsusb_probe(struct usb_interface *intf,
+static int smsusb_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
index 5c36a57e6590d6c731341663296faad17607a7ef..ad7f7448072ef8ba995c10c9f06471a25314bd96 100644 (file)
@@ -1363,7 +1363,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
 }
 
 /* register video4linux devices */
-static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
+static int usbvision_register_video(struct usb_usbvision *usbvision)
 {
        /* Video Device: */
        usbvision->vdev = usbvision_vdev_init(usbvision,
@@ -1510,8 +1510,8 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
  * if it looks like USBVISION video device
  *
  */
-static int __devinit usbvision_probe(struct usb_interface *intf,
-                                    const struct usb_device_id *devid)
+static int usbvision_probe(struct usb_interface *intf,
+                          const struct usb_device_id *devid)
 {
        struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
        struct usb_interface *uif;
@@ -1619,7 +1619,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
  * with no ill consequences.
  *
  */
-static void __devexit usbvision_disconnect(struct usb_interface *intf)
+static void usbvision_disconnect(struct usb_interface *intf)
 {
        struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf));
 
@@ -1664,7 +1664,7 @@ static struct usb_driver usbvision_driver = {
        .name           = "usbvision",
        .id_table       = usbvision_table,
        .probe          = usbvision_probe,
-       .disconnect     = __devexit_p(usbvision_disconnect),
+       .disconnect     = usbvision_disconnect,
 };
 
 /*
index 516a5b188ea5248a48f1cacb64cddb984096d9ea..d5baab17a5ef77b6bbeb85f8cf3e2c1b0127b5b7 100644 (file)
@@ -1061,7 +1061,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 
        ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
        if (ctrl == NULL) {
-               ret = -ENOENT;
+               ret = -EINVAL;
                goto done;
        }
 
@@ -1099,13 +1099,12 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
                return -ERESTARTSYS;
 
        ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL) {
-               ret = -ENOENT;
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
                goto done;
        }
 
-       if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU ||
-           query_menu->index >= mapping->menu_count) {
+       if (query_menu->index >= mapping->menu_count) {
                ret = -EINVAL;
                goto done;
        }
@@ -1264,7 +1263,7 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
 
        ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
        if (ctrl == NULL) {
-               ret = -ENOENT;
+               ret = -EINVAL;
                goto done;
        }
 
@@ -1415,7 +1414,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
 
        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
        if (ctrl == NULL)
-               return -ENOENT;
+               return -EINVAL;
 
        return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
 }
@@ -1433,7 +1432,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
 
        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
        if (ctrl == NULL)
-               return -ENOENT;
+               return -EINVAL;
        if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
                return -EACCES;
 
index 8e056046bc203c4224dd08fa931f56219bdd6157..68d59b52749288e00dcb816f42952516f160f6db 100644 (file)
@@ -607,10 +607,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
                ret = uvc_ctrl_get(chain, &xctrl);
                uvc_ctrl_rollback(handle);
-               if (ret < 0)
-                       return ret == -ENOENT ? -EINVAL : ret;
-
-               ctrl->value = xctrl.value;
+               if (ret >= 0)
+                       ctrl->value = xctrl.value;
                break;
        }
 
@@ -634,7 +632,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                ret = uvc_ctrl_set(chain, &xctrl);
                if (ret < 0) {
                        uvc_ctrl_rollback(handle);
-                       return ret == -ENOENT ? -EINVAL : ret;
+                       return ret;
                }
                ret = uvc_ctrl_commit(handle, &xctrl, 1);
                if (ret == 0)
@@ -659,9 +657,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_get(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = ret == -ENOENT
-                                                ? ctrls->count : i;
-                               return ret == -ENOENT ? -EINVAL : ret;
+                               ctrls->error_idx = i;
+                               return ret;
                        }
                }
                ctrls->error_idx = 0;
@@ -688,10 +685,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_set(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = (ret == -ENOENT &&
-                                                   cmd == VIDIOC_S_EXT_CTRLS)
+                               ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
                                                 ? ctrls->count : i;
-                               return ret == -ENOENT ? -EINVAL : ret;
+                               return ret;
                        }
                }
 
index 9f81be23a81f06a1d527ac792071e1b7a6154979..e02c4797b1c65fe46ef1352fa72f84e05317fe6c 100644 (file)
@@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                 * In videobuf we use our internal V4l2_planes struct for
                 * single-planar buffers as well, for simplicity.
                 */
-               if (V4L2_TYPE_IS_OUTPUT(b->type))
+               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
                        v4l2_planes[0].bytesused = b->bytesused;
+                       v4l2_planes[0].data_offset = 0;
+               }
 
                if (b->memory == V4L2_MEMORY_USERPTR) {
                        v4l2_planes[0].m.userptr = b->m.userptr;
index e6764bb41cb9b5aaf5e46e110d699d8fac3b5047..186f27d9e5f1ac25e2302f04bcedc1c656c19f4f 100644 (file)
@@ -177,7 +177,7 @@ static void tegra20_mc_decode(struct tegra20_mc *mc, int n)
                            "carveout" : "trustzone") : "");
 }
 
-static const struct of_device_id tegra20_mc_of_match[] __devinitconst = {
+static const struct of_device_id tegra20_mc_of_match[] = {
        { .compatible = "nvidia,tegra20-mc", },
        {},
 };
@@ -198,7 +198,7 @@ static irqreturn_t tegra20_mc_isr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit tegra20_mc_probe(struct platform_device *pdev)
+static int tegra20_mc_probe(struct platform_device *pdev)
 {
        struct resource *irq;
        struct tegra20_mc *mc;
index 802b9ea431fa41f3831f13a5d6e8c7a95422b54c..0b7ab9332a182b867ad0375b5c1a31632eb4969e 100644 (file)
@@ -295,7 +295,7 @@ static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
                            tegra30_mc_suspend,
                            tegra30_mc_resume, NULL);
 
-static const struct of_device_id tegra30_mc_of_match[] __devinitconst = {
+static const struct of_device_id tegra30_mc_of_match[] = {
        { .compatible = "nvidia,tegra30-mc", },
        {},
 };
@@ -316,7 +316,7 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit tegra30_mc_probe(struct platform_device *pdev)
+static int tegra30_mc_probe(struct platform_device *pdev)
 {
        struct resource *irq;
        struct tegra30_mc *mc;
index d784c36707c0b12c318c1f2be20fe98b425eabad..c13cd9bc590b91c83a7ab03308acf2bfaa9f7ae7 100644 (file)
@@ -100,7 +100,7 @@ static int mptfc_slave_alloc(struct scsi_device *sdev);
 static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);
 static void mptfc_target_destroy(struct scsi_target *starget);
 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
-static void __devexit mptfc_remove(struct pci_dev *pdev);
+static void mptfc_remove(struct pci_dev *pdev);
 static int mptfc_abort(struct scsi_cmnd *SCpnt);
 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
@@ -1360,7 +1360,7 @@ static struct pci_driver mptfc_driver = {
        .name           = "mptfc",
        .id_table       = mptfc_pci_table,
        .probe          = mptfc_probe,
-       .remove         = __devexit_p(mptfc_remove),
+       .remove         = mptfc_remove,
        .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
@@ -1496,8 +1496,7 @@ mptfc_init(void)
  *     @pdev: Pointer to pci_dev structure
  *
  */
-static void __devexit
-mptfc_remove(struct pci_dev *pdev)
+static void mptfc_remove(struct pci_dev *pdev)
 {
        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct mptfc_rport_info *p, *n;
index 551262e4b96e0829bc4f64c15357f9862f006c76..fa43c391c8ed1072b35200ba671623c933c1df80 100644 (file)
@@ -5332,7 +5332,7 @@ mptsas_shutdown(struct pci_dev *pdev)
        mptsas_cleanup_fw_event_q(ioc);
 }
 
-static void __devexit mptsas_remove(struct pci_dev *pdev)
+static void mptsas_remove(struct pci_dev *pdev)
 {
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        struct mptsas_portinfo *p, *n;
@@ -5387,7 +5387,7 @@ static struct pci_driver mptsas_driver = {
        .name           = "mptsas",
        .id_table       = mptsas_pci_table,
        .probe          = mptsas_probe,
-       .remove         = __devexit_p(mptsas_remove),
+       .remove         = mptsas_remove,
        .shutdown       = mptsas_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
index 8f61ba6aac239c210fbc99b1365e8115650fd2ed..c3aabde2dc4fad50bb0781757bff0605121ba5b0 100644 (file)
@@ -1550,7 +1550,7 @@ static struct pci_driver mptspi_driver = {
        .name           = "mptspi",
        .id_table       = mptspi_pci_table,
        .probe          = mptspi_probe,
-       .remove         = __devexit_p(mptscsih_remove),
+       .remove         = mptscsih_remove,
        .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
index 7190d5239b4fa0e5725169a134ed620b776e25d4..0f9f3e1a2b6b4f75db8c3413dc83a549dc1c8cb4 100644 (file)
@@ -37,7 +37,7 @@
 #define OSM_DESCRIPTION        "I2O-subsystem"
 
 /* PCI device id table for all I2O controllers */
-static struct pci_device_id __devinitdata i2o_pci_ids[] = {
+static struct pci_device_id i2o_pci_ids[] = {
        {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
        {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
        {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
@@ -84,7 +84,7 @@ static void i2o_pci_free(struct i2o_controller *c)
  *
  *     Returns 0 on success or negative error code on failure.
  */
-static int __devinit i2o_pci_alloc(struct i2o_controller *c)
+static int i2o_pci_alloc(struct i2o_controller *c)
 {
        struct pci_dev *pdev = c->pdev;
        struct device *dev = &pdev->dev;
@@ -315,8 +315,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c)
  *
  *     Returns 0 on success or negative error code on failure.
  */
-static int __devinit i2o_pci_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *id)
+static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct i2o_controller *c;
        int rc;
@@ -453,7 +452,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
  *     Reset the I2O controller, disable interrupts and remove all allocated
  *     resources.
  */
-static void __devexit i2o_pci_remove(struct pci_dev *pdev)
+static void i2o_pci_remove(struct pci_dev *pdev)
 {
        struct i2o_controller *c;
        c = pci_get_drvdata(pdev);
@@ -474,7 +473,7 @@ static struct pci_driver i2o_pci_driver = {
        .name = "PCI_I2O",
        .id_table = i2o_pci_ids,
        .probe = i2o_pci_probe,
-       .remove = __devexit_p(i2o_pci_remove),
+       .remove = i2o_pci_remove,
 };
 
 /**
index 1c0abd4dfc43eeef01bb096bb33e5a1bdc08ef5e..ff553babf455025c2a5ce303297a15f404d2d5e3 100644 (file)
@@ -237,6 +237,7 @@ config MFD_TPS65910
        depends on I2C=y && GPIOLIB
        select MFD_CORE
        select REGMAP_I2C
+       select REGMAP_IRQ
        select IRQ_DOMAIN
        help
          if you say yes here you get support for the TPS65910 series of
@@ -292,6 +293,7 @@ config TWL4030_CORE
        bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
        depends on I2C=y && GENERIC_HARDIRQS
        select IRQ_DOMAIN
+       select REGMAP_I2C
        help
          Say yes here if you have TWL4030 / TWL6030 family chip on your board.
          This core driver provides register access and IRQ handling
index e1650badd106da6e3992b219e77fdc35e20ad1c8..4778bb124efe09b27da77446896dfd6ae9e97f0e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/ab8500.h>
 #include <linux/of.h>
index bc8a3edb6bbf2b2fdc9c3f15a425eafb0bcb23af..222c03a5ddc0b3d3e9a37af453d4a1745f1b35e3 100644 (file)
@@ -239,7 +239,12 @@ static int arizona_runtime_resume(struct device *dev)
                return ret;
        }
 
-       regcache_sync(arizona->regmap);
+       ret = regcache_sync(arizona->regmap);
+       if (ret != 0) {
+               dev_err(arizona->dev, "Failed to restore register cache\n");
+               regulator_disable(arizona->dcvdd);
+               return ret;
+       }
 
        return 0;
 }
index 74713bf5371fa42361dbb2342407c0dfe9c039b6..2bec5f0db3ee5e80733a88043d96b3219405d2f0 100644 (file)
@@ -176,14 +176,7 @@ int arizona_irq_init(struct arizona *arizona)
                aod = &wm5102_aod;
                irq = &wm5102_irq;
 
-               switch (arizona->rev) {
-               case 0:
-               case 1:
-                       ctrlif_error = false;
-                       break;
-               default:
-                       break;
-               }
+               ctrlif_error = false;
                break;
 #endif
 #ifdef CONFIG_MFD_WM5110
@@ -191,14 +184,7 @@ int arizona_irq_init(struct arizona *arizona)
                aod = &wm5110_aod;
                irq = &wm5110_irq;
 
-               switch (arizona->rev) {
-               case 0:
-               case 1:
-                       ctrlif_error = false;
-                       break;
-               default:
-                       break;
-               }
+               ctrlif_error = false;
                break;
 #endif
        default:
index ac74a4d1daead1848ef00e9ac096013d69e67a21..885e567803583a42473ffb532beead311ad68cf2 100644 (file)
 #include <linux/of_device.h>
 #endif
 
+/* I2C safe register check */
+static inline bool i2c_safe_reg(unsigned char reg)
+{
+       switch (reg) {
+       case DA9052_STATUS_A_REG:
+       case DA9052_STATUS_B_REG:
+       case DA9052_STATUS_C_REG:
+       case DA9052_STATUS_D_REG:
+       case DA9052_ADC_RES_L_REG:
+       case DA9052_ADC_RES_H_REG:
+       case DA9052_VDD_RES_REG:
+       case DA9052_ICHG_AV_REG:
+       case DA9052_TBAT_RES_REG:
+       case DA9052_ADCIN4_RES_REG:
+       case DA9052_ADCIN5_RES_REG:
+       case DA9052_ADCIN6_RES_REG:
+       case DA9052_TJUNC_RES_REG:
+       case DA9052_TSI_X_MSB_REG:
+       case DA9052_TSI_Y_MSB_REG:
+       case DA9052_TSI_LSB_REG:
+       case DA9052_TSI_Z_MSB_REG:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/*
+ * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC
+ * gets lockup up or fails to respond following a system reset.
+ * This fix is to follow any read or write with a dummy read to a safe
+ * register.
+ */
+int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
+{
+       int val;
+
+       switch (da9052->chip_id) {
+       case DA9052:
+       case DA9053_AA:
+       case DA9053_BA:
+       case DA9053_BB:
+               /* A dummy read to a safe register address. */
+       if (!i2c_safe_reg(reg))
+                       return regmap_read(da9052->regmap,
+                                          DA9052_PARK_REGISTER,
+                                          &val);
+               break;
+       default:
+               /*
+                * For other chips parking of I2C register
+                * to a safe place is not required.
+                */
+               break;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(da9052_i2c_fix);
+
 static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
 {
        int reg_val, ret;
@@ -83,6 +143,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
 
        da9052->dev = &client->dev;
        da9052->chip_irq = client->irq;
+       da9052->fix_io = da9052_i2c_fix;
 
        i2c_set_clientdata(client, da9052);
 
index dc8826d8d69da0d1ee8c29911dc6c95ade7f1da2..268f45d4239427bdb172f65e8c1768d4cd2bd435 100644 (file)
@@ -2524,7 +2524,7 @@ static bool read_mailbox_0(void)
 
                for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
                        if (ev & prcmu_irq_bit[n])
-                               generic_handle_irq(IRQ_PRCMU_BASE + n);
+                               generic_handle_irq(irq_find_mapping(db8500_irq_domain, n));
                }
                r = true;
                break;
@@ -2737,13 +2737,14 @@ static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
 }
 
 static struct irq_domain_ops db8500_irq_ops = {
-        .map    = db8500_irq_map,
-        .xlate  = irq_domain_xlate_twocell,
+       .map    = db8500_irq_map,
+       .xlate  = irq_domain_xlate_twocell,
 };
 
 static int db8500_irq_init(struct device_node *np)
 {
-       int irq_base = -1;
+       int irq_base = 0;
+       int i;
 
        /* In the device tree case, just take some IRQs */
        if (!np)
@@ -2758,6 +2759,10 @@ static int db8500_irq_init(struct device_node *np)
                return -ENOSYS;
        }
 
+       /* All wakeups will be used, so create mappings for all */
+       for (i = 0; i < NUM_PRCMU_WAKEUPS; i++)
+               irq_create_mapping(db8500_irq_domain, i);
+
        return 0;
 }
 
index f6878f8db57d105b663d399bc2830bbb0ce0b4bf..4d73963cd8f0188d2f9e09c9bbdcde0cf5c35007 100644 (file)
@@ -93,15 +93,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
        if (max77686 == NULL)
                return -ENOMEM;
 
-       max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
-       if (IS_ERR(max77686->regmap)) {
-               ret = PTR_ERR(max77686->regmap);
-               dev_err(max77686->dev, "Failed to allocate register map: %d\n",
-                               ret);
-               kfree(max77686);
-               return ret;
-       }
-
        i2c_set_clientdata(i2c, max77686);
        max77686->dev = &i2c->dev;
        max77686->i2c = i2c;
@@ -111,6 +102,15 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
        max77686->irq_gpio = pdata->irq_gpio;
        max77686->irq = i2c->irq;
 
+       max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
+       if (IS_ERR(max77686->regmap)) {
+               ret = PTR_ERR(max77686->regmap);
+               dev_err(max77686->dev, "Failed to allocate register map: %d\n",
+                               ret);
+               kfree(max77686);
+               return ret;
+       }
+
        if (regmap_read(max77686->regmap,
                         MAX77686_REG_DEVICE_ID, &data) < 0) {
                dev_err(max77686->dev,
index cc5155e20494726c2ae6954e64128f61973ebafd..9e60fed5ff82a81dbf774c7d8af7547f12861516 100644 (file)
@@ -114,35 +114,37 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
        u8 reg_data;
        int ret = 0;
 
+       if (!pdata) {
+               dev_err(&i2c->dev, "No platform data found.\n");
+               return -EINVAL;
+       }
+
        max77693 = devm_kzalloc(&i2c->dev,
                        sizeof(struct max77693_dev), GFP_KERNEL);
        if (max77693 == NULL)
                return -ENOMEM;
 
-       max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config);
-       if (IS_ERR(max77693->regmap)) {
-               ret = PTR_ERR(max77693->regmap);
-               dev_err(max77693->dev,"failed to allocate register map: %d\n",
-                               ret);
-               goto err_regmap;
-       }
-
        i2c_set_clientdata(i2c, max77693);
        max77693->dev = &i2c->dev;
        max77693->i2c = i2c;
        max77693->irq = i2c->irq;
        max77693->type = id->driver_data;
 
-       if (!pdata)
-               goto err_regmap;
+       max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config);
+       if (IS_ERR(max77693->regmap)) {
+               ret = PTR_ERR(max77693->regmap);
+               dev_err(max77693->dev, "failed to allocate register map: %d\n",
+                               ret);
+               return ret;
+       }
 
        max77693->wakeup = pdata->wakeup;
 
-       if (max77693_read_reg(max77693->regmap,
-                               MAX77693_PMIC_REG_PMIC_ID2, &reg_data) < 0) {
+       ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
+                               &reg_data);
+       if (ret < 0) {
                dev_err(max77693->dev, "device not found on this channel\n");
-               ret = -ENODEV;
-               goto err_regmap;
+               return ret;
        } else
                dev_info(max77693->dev, "device ID: 0x%x\n", reg_data);
 
@@ -163,7 +165,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                ret = PTR_ERR(max77693->regmap_muic);
                dev_err(max77693->dev,
                        "failed to allocate register map: %d\n", ret);
-               goto err_regmap;
+               goto err_regmap_muic;
        }
 
        ret = max77693_irq_init(max77693);
@@ -184,9 +186,9 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 err_mfd:
        max77693_irq_exit(max77693);
 err_irq:
+err_regmap_muic:
        i2c_unregister_device(max77693->muic);
        i2c_unregister_device(max77693->haptic);
-err_regmap:
        return ret;
 }
 
index abd5c80c7cf5f59c9a3adf78d188482148ecf512..14714058f2d2a673e5b678d950e6184454a189bf 100644 (file)
@@ -50,7 +50,7 @@ static struct mfd_cell max8997_devs[] = {
 };
 
 #ifdef CONFIG_OF
-static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+static struct of_device_id max8997_pmic_dt_match[] = {
        { .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
        {},
 };
index 64803f13bcecc4f6e8f221ecacf814e419d07104..d11567307fbed6c930f955abf198de1157dfb237 100644 (file)
@@ -208,6 +208,8 @@ static int pcf50633_probe(struct i2c_client *client,
        if (!pcf)
                return -ENOMEM;
 
+       i2c_set_clientdata(client, pcf);
+       pcf->dev = &client->dev;
        pcf->pdata = pdata;
 
        mutex_init(&pcf->lock);
@@ -219,9 +221,6 @@ static int pcf50633_probe(struct i2c_client *client,
                return ret;
        }
 
-       i2c_set_clientdata(client, pcf);
-       pcf->dev = &client->dev;
-
        version = pcf50633_reg_read(pcf, 0);
        variant = pcf50633_reg_read(pcf, 1);
        if (version < 0 || variant < 0) {
index 7ff4a37ab0c05e89da349966dccc588a5648061b..3ba048655bf37fe5a9b1f1ff2ad7a2e6748fe0c7 100644 (file)
@@ -171,8 +171,7 @@ static struct regmap_config retu_config = {
        .val_bits = 16,
 };
 
-static int __devinit retu_probe(struct i2c_client *i2c,
-                               const struct i2c_device_id *id)
+static int retu_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
        struct retu_dev *rdev;
        int ret;
@@ -225,7 +224,7 @@ static int __devinit retu_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static int __devexit retu_remove(struct i2c_client *i2c)
+static int retu_remove(struct i2c_client *i2c)
 {
        struct retu_dev *rdev = i2c_get_clientdata(i2c);
 
index 89f046ca9e410292b9b1a51423544ab1a40aebf2..3d3b4addf81a9b73b480ae3874e2675e1678b52b 100644 (file)
@@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
                        BPP_LDO_POWB, BPP_LDO_SUSPEND);
 }
 
+static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       u8 mask, val;
+
+       mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
+       if (voltage == OUTPUT_3V3)
+               val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
+       else if (voltage == OUTPUT_1V8)
+               val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
+       else
+               return -EINVAL;
+
+       return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
+}
+
 static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
 {
        unsigned int card_exist;
@@ -163,6 +178,18 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
        return card_exist;
 }
 
+static int rtl8411_conv_clk_and_div_n(int input, int dir)
+{
+       int output;
+
+       if (dir == CLK_TO_DIV_N)
+               output = input * 4 / 5 - 2;
+       else
+               output = (input + 2) * 5 / 4;
+
+       return output;
+}
+
 static const struct pcr_ops rtl8411_pcr_ops = {
        .extra_init_hw = rtl8411_extra_init_hw,
        .optimize_phy = NULL,
@@ -172,7 +199,9 @@ static const struct pcr_ops rtl8411_pcr_ops = {
        .disable_auto_blink = rtl8411_disable_auto_blink,
        .card_power_on = rtl8411_card_power_on,
        .card_power_off = rtl8411_card_power_off,
+       .switch_output_voltage = rtl8411_switch_output_voltage,
        .cd_deglitch = rtl8411_cd_deglitch,
+       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
 };
 
 /* SD Pull Control Enable:
index 283a4f148084ab29f34d2444d8f264e72345e846..98fe0f39463ed1596f1e0881f5d7352349da400d 100644 (file)
@@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
        return rtsx_pci_send_cmd(pcr, 100);
 }
 
+static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static const struct pcr_ops rts5209_pcr_ops = {
        .extra_init_hw = rts5209_extra_init_hw,
        .optimize_phy = rts5209_optimize_phy,
@@ -153,7 +172,9 @@ static const struct pcr_ops rts5209_pcr_ops = {
        .disable_auto_blink = rts5209_disable_auto_blink,
        .card_power_on = rts5209_card_power_on,
        .card_power_off = rts5209_card_power_off,
+       .switch_output_voltage = rts5209_switch_output_voltage,
        .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
 };
 
 /* SD Pull Control Enable:
index b9dbab266fdadc9f3f60e219f6dc5e25b9322036..29d889cbb9c5183262897bc5e29818c536bb227d 100644 (file)
@@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
        return rtsx_pci_send_cmd(pcr, 100);
 }
 
+static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static const struct pcr_ops rts5229_pcr_ops = {
        .extra_init_hw = rts5229_extra_init_hw,
        .optimize_phy = rts5229_optimize_phy,
@@ -123,7 +142,9 @@ static const struct pcr_ops rts5229_pcr_ops = {
        .disable_auto_blink = rts5229_disable_auto_blink,
        .card_power_on = rts5229_card_power_on,
        .card_power_off = rts5229_card_power_off,
+       .switch_output_voltage = rts5229_switch_output_voltage,
        .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
 };
 
 /* SD Pull Control Enable:
index 3a44efa292036df17261bf7b2c95f35522d9f651..9fc57009e22813fe257481b39352533f2fbd5d45 100644 (file)
@@ -630,7 +630,10 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
        if (clk == pcr->cur_clock)
                return 0;
 
-       N = (u8)(clk - 2);
+       if (pcr->ops->conv_clk_and_div_n)
+               N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
+       else
+               N = (u8)(clk - 2);
        if ((clk <= 2) || (N > max_N))
                return -EINVAL;
 
@@ -641,7 +644,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
        /* Make sure that the SSC clock div_n is equal or greater than min_N */
        div = CLK_DIV_1;
        while ((N < min_N) && (div < max_div)) {
-               N = (N + 2) * 2 - 2;
+               if (pcr->ops->conv_clk_and_div_n) {
+                       int dbl_clk = pcr->ops->conv_clk_and_div_n(N,
+                                       DIV_N_TO_CLK) * 2;
+                       N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk,
+                                       CLK_TO_DIV_N);
+               } else {
+                       N = (N + 2) * 2 - 2;
+               }
                div++;
        }
        dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div);
@@ -703,6 +713,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
 
+int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       if (pcr->ops->switch_output_voltage)
+               return pcr->ops->switch_output_voltage(pcr, voltage);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage);
+
 unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
 {
        unsigned int val;
@@ -767,10 +786,10 @@ static void rtsx_pci_card_detect(struct work_struct *work)
 
        spin_unlock_irqrestore(&pcr->lock, flags);
 
-       if (card_detect & SD_EXIST)
+       if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
                pcr->slots[RTSX_SD_CARD].card_event(
                                pcr->slots[RTSX_SD_CARD].p_dev);
-       if (card_detect & MS_EXIST)
+       if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event)
                pcr->slots[RTSX_MS_CARD].card_event(
                                pcr->slots[RTSX_MS_CARD].p_dev);
 }
@@ -998,8 +1017,8 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
        return 0;
 }
 
-static int __devinit rtsx_pci_probe(struct pci_dev *pcidev,
-                                   const struct pci_device_id *id)
+static int rtsx_pci_probe(struct pci_dev *pcidev,
+                         const struct pci_device_id *id)
 {
        struct rtsx_pcr *pcr;
        struct pcr_handle *handle;
@@ -1123,7 +1142,7 @@ disable:
        return ret;
 }
 
-static void __devexit rtsx_pci_remove(struct pci_dev *pcidev)
+static void rtsx_pci_remove(struct pci_dev *pcidev)
 {
        struct pcr_handle *handle = pci_get_drvdata(pcidev);
        struct rtsx_pcr *pcr = handle->pcr;
@@ -1241,7 +1260,7 @@ static struct pci_driver rtsx_pci_driver = {
        .name = DRV_NAME_RTSX_PCI,
        .id_table = rtsx_pci_ids,
        .probe = rtsx_pci_probe,
-       .remove = __devexit_p(rtsx_pci_remove),
+       .remove = rtsx_pci_remove,
        .suspend = rtsx_pci_suspend,
        .resume = rtsx_pci_resume,
 };
index 1225dcbcfcfcc6fa9db396e1ea47c43b6a9a85b0..9bd33169a1118b835c4e4bd53f7f069d5ae764e5 100644 (file)
@@ -510,19 +510,19 @@ enum mfd1_bar1_cells {
        STA2X11_APB_SOC_REGS = 0,
 };
 
-static const __devinitconst struct resource vic_resources[] = {
+static const struct resource vic_resources[] = {
        CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
 };
 
-static const __devinitconst struct resource apb_soc_regs_resources[] = {
+static const struct resource apb_soc_regs_resources[] = {
        CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
 };
 
-static __devinitdata struct mfd_cell sta2x11_mfd1_bar0[] = {
+static struct mfd_cell sta2x11_mfd1_bar0[] = {
        DEV(STA2X11_MFD_VIC_NAME, vic_resources),
 };
 
-static __devinitdata struct mfd_cell sta2x11_mfd1_bar1[] = {
+static struct mfd_cell sta2x11_mfd1_bar1[] = {
        DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
 };
 
index 5e8e6927cfcd8a78db34c3e7a6efb9858aa9551b..4b11202061bef686b62275f59690e2d4fa29778f 100644 (file)
@@ -892,8 +892,7 @@ static struct irq_domain_ops stmpe_irq_ops = {
         .xlate  = irq_domain_xlate_twocell,
 };
 
-static int __devinit stmpe_irq_init(struct stmpe *stmpe,
-                               struct device_node *np)
+static int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np)
 {
        int base = 0;
        int num_irqs = stmpe->variant->num_irqs;
@@ -911,7 +910,7 @@ static int __devinit stmpe_irq_init(struct stmpe *stmpe,
        return 0;
 }
 
-static int __devinit stmpe_chip_init(struct stmpe *stmpe)
+static int stmpe_chip_init(struct stmpe *stmpe)
 {
        unsigned int irq_trigger = stmpe->pdata->irq_trigger;
        int autosleep_timeout = stmpe->pdata->autosleep_timeout;
@@ -970,14 +969,13 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
        return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
 }
 
-static int __devinit stmpe_add_device(struct stmpe *stmpe,
-                                     struct mfd_cell *cell)
+static int stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell)
 {
        return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
                               NULL, stmpe->irq_base, stmpe->domain);
 }
 
-static int __devinit stmpe_devices_init(struct stmpe *stmpe)
+static int stmpe_devices_init(struct stmpe *stmpe)
 {
        struct stmpe_variant_info *variant = stmpe->variant;
        unsigned int platform_blocks = stmpe->pdata->blocks;
@@ -1013,8 +1011,7 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
        return ret;
 }
 
-void __devinit stmpe_of_probe(struct stmpe_platform_data *pdata,
-                       struct device_node *np)
+void stmpe_of_probe(struct stmpe_platform_data *pdata, struct device_node *np)
 {
        struct device_node *child;
 
@@ -1044,7 +1041,7 @@ void __devinit stmpe_of_probe(struct stmpe_platform_data *pdata,
 }
 
 /* Called from client specific probe routines */
-int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
+int stmpe_probe(struct stmpe_client_info *ci, int partnum)
 {
        struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
        struct device_node *np = ci->dev->of_node;
index a06d66b929b1ea96743826435d18899464fb24b5..ecc092c7f7453e4cfb7146fc222546869239f8b0 100644 (file)
@@ -219,25 +219,18 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
 }
 
 static struct irq_domain_ops tc3589x_irq_ops = {
-        .map    = tc3589x_irq_map,
+       .map    = tc3589x_irq_map,
        .unmap  = tc3589x_irq_unmap,
-        .xlate  = irq_domain_xlate_twocell,
+       .xlate  = irq_domain_xlate_twocell,
 };
 
 static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
 {
        int base = tc3589x->irq_base;
 
-       if (base) {
-               tc3589x->domain = irq_domain_add_legacy(
-                       NULL, TC3589x_NR_INTERNAL_IRQS, base,
-                       0, &tc3589x_irq_ops, tc3589x);
-       }
-       else {
-               tc3589x->domain = irq_domain_add_linear(
-                       np, TC3589x_NR_INTERNAL_IRQS,
-                       &tc3589x_irq_ops, tc3589x);
-       }
+       tc3589x->domain = irq_domain_add_simple(
+               np, TC3589x_NR_INTERNAL_IRQS, base,
+               &tc3589x_irq_ops, tc3589x);
 
        if (!tc3589x->domain) {
                dev_err(tc3589x->dev, "Failed to create irqdomain\n");
index 8ca3bf023fb25a2e70a5d78dd8426e7a3cfa6109..e9f3fb510b44f965795bc87f56c26bffeefe2078 100644 (file)
@@ -58,7 +58,7 @@ static void tscadc_idle_config(struct ti_tscadc_dev *config)
        tscadc_writel(config, REG_IDLECONFIG, idleconfig);
 }
 
-static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+static int ti_tscadc_probe(struct platform_device *pdev)
 {
        struct ti_tscadc_dev    *tscadc;
        struct resource         *res;
@@ -202,7 +202,7 @@ ret:
        return err;
 }
 
-static int __devexit ti_tscadc_remove(struct platform_device *pdev)
+static int ti_tscadc_remove(struct platform_device *pdev)
 {
        struct ti_tscadc_dev    *tscadc = platform_get_drvdata(pdev);
 
@@ -263,7 +263,7 @@ static struct platform_driver ti_tscadc_driver = {
                .pm     = TSCADC_PM_OPS,
        },
        .probe  = ti_tscadc_probe,
-       .remove = __devexit_p(ti_tscadc_remove),
+       .remove = ti_tscadc_remove,
 
 };
 
index 10b51f7dfff39dec18b83ee79eebb484480584ba..c90a2c450f5113c44536eac3b82315be92e9e89d 100644 (file)
@@ -269,8 +269,7 @@ static int tps80031_init_ext_control(struct tps80031 *tps80031,
        return ret;
 }
 
-static int __devinit tps80031_irq_init(struct tps80031 *tps80031, int irq,
-                               int irq_base)
+static int tps80031_irq_init(struct tps80031 *tps80031, int irq, int irq_base)
 {
        struct device *dev = tps80031->dev;
        int i, ret;
@@ -416,8 +415,8 @@ static const struct regmap_config tps80031_regmap_configs[] = {
        },
 };
 
-static int __devinit tps80031_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
+static int tps80031_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct tps80031_platform_data *pdata = client->dev.platform_data;
        struct tps80031 *tps80031;
@@ -519,7 +518,7 @@ fail_client_reg:
        return ret;
 }
 
-static int __devexit tps80031_remove(struct i2c_client *client)
+static int tps80031_remove(struct i2c_client *client)
 {
        struct tps80031 *tps80031 = i2c_get_clientdata(client);
        int i;
@@ -553,7 +552,7 @@ static struct i2c_driver tps80031_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps80031_probe,
-       .remove         = __devexit_p(tps80031_remove),
+       .remove         = tps80031_remove,
        .id_table       = tps80031_id_table,
 };
 
index 4dae241e501734f66c9080283a0c43188729b0b5..dd362c1078e1438b3751ec69dc1c8b1ad3efa0bb 100644 (file)
@@ -159,7 +159,7 @@ out:
 static int twl4030_write_script(u8 address, struct twl4030_ins *script,
                                       int len)
 {
-       int err;
+       int err = -EINVAL;
 
        for (; len; len--, address++, script++) {
                if (len == 1) {
index 583be76e36a804162341b0d23b4e98b4d13f8aff..f361bf38a0aa115ff539f94b740810f22ecb730a 100644 (file)
@@ -517,8 +517,8 @@ static struct regmap_irq_chip twl6040_irq_chip = {
        .mask_base = TWL6040_REG_INTMR,
 };
 
-static int __devinit twl6040_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int twl6040_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct twl6040_platform_data *pdata = client->dev.platform_data;
        struct device_node *node = client->dev.of_node;
@@ -699,7 +699,7 @@ err:
        return ret;
 }
 
-static int __devexit twl6040_remove(struct i2c_client *client)
+static int twl6040_remove(struct i2c_client *client)
 {
        struct twl6040 *twl6040 = i2c_get_clientdata(client);
 
@@ -735,7 +735,7 @@ static struct i2c_driver twl6040_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = twl6040_probe,
-       .remove         = __devexit_p(twl6040_remove),
+       .remove         = twl6040_remove,
        .id_table       = twl6040_i2c_id,
 };
 
index fae15d880758cc197ed0bfe8e095daca74f01bd5..3c1723aa62250c28c61aab4b3f83442e28770dc8 100644 (file)
@@ -67,6 +67,7 @@ struct vexpress_config_bridge *vexpress_config_bridge_register(
 
        return bridge;
 }
+EXPORT_SYMBOL(vexpress_config_bridge_register);
 
 void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
 {
@@ -83,6 +84,7 @@ void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
        while (!list_empty(&__bridge.transactions))
                cpu_relax();
 }
+EXPORT_SYMBOL(vexpress_config_bridge_unregister);
 
 
 struct vexpress_config_func {
@@ -142,6 +144,7 @@ struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
 
        return func;
 }
+EXPORT_SYMBOL(__vexpress_config_func_get);
 
 void vexpress_config_func_put(struct vexpress_config_func *func)
 {
@@ -149,7 +152,7 @@ void vexpress_config_func_put(struct vexpress_config_func *func)
        of_node_put(func->bridge->node);
        kfree(func);
 }
-
+EXPORT_SYMBOL(vexpress_config_func_put);
 
 struct vexpress_config_trans {
        struct vexpress_config_func *func;
@@ -229,6 +232,7 @@ void vexpress_config_complete(struct vexpress_config_bridge *bridge,
 
        complete(&trans->completion);
 }
+EXPORT_SYMBOL(vexpress_config_complete);
 
 int vexpress_config_wait(struct vexpress_config_trans *trans)
 {
@@ -236,7 +240,7 @@ int vexpress_config_wait(struct vexpress_config_trans *trans)
 
        return trans->status;
 }
-
+EXPORT_SYMBOL(vexpress_config_wait);
 
 int vexpress_config_read(struct vexpress_config_func *func, int offset,
                u32 *data)
index 733c06bd2d17808b95b1cc0c21e094720e9743ca..77048b18439e3e6467b79f7ba4b2b3ac06e36a6e 100644 (file)
@@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data)
 }
 
 
-void __init vexpress_sysreg_early_init(void __iomem *base)
+void __init vexpress_sysreg_setup(struct device_node *node)
 {
-       struct device_node *node = of_find_compatible_node(NULL, NULL,
-                       "arm,vexpress-sysreg");
-
-       if (node)
-               base = of_iomap(node, 0);
-
-       if (WARN_ON(!base))
+       if (WARN_ON(!vexpress_sysreg_base))
                return;
 
-       vexpress_sysreg_base = base;
-
        if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
                vexpress_master_site = VEXPRESS_SITE_DB2;
        else
@@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base)
        WARN_ON(!vexpress_sysreg_config_bridge);
 }
 
+void __init vexpress_sysreg_early_init(void __iomem *base)
+{
+       vexpress_sysreg_base = base;
+       vexpress_sysreg_setup(NULL);
+}
+
 void __init vexpress_sysreg_of_early_init(void)
 {
-       vexpress_sysreg_early_init(NULL);
+       struct device_node *node = of_find_compatible_node(NULL, NULL,
+                       "arm,vexpress-sysreg");
+
+       if (node) {
+               vexpress_sysreg_base = of_iomap(node, 0);
+               vexpress_sysreg_setup(node);
+       } else {
+               pr_info("vexpress-sysreg: No Device Tree node found.");
+       }
 }
 
 
@@ -414,7 +420,7 @@ static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
 
 DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
 
-static int __devinit vexpress_sysreg_probe(struct platform_device *pdev)
+static int vexpress_sysreg_probe(struct platform_device *pdev)
 {
        int err;
        struct resource *res = platform_get_resource(pdev,
@@ -426,9 +432,11 @@ static int __devinit vexpress_sysreg_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
-       if (!vexpress_sysreg_base)
+       if (!vexpress_sysreg_base) {
                vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
                                resource_size(res));
+               vexpress_sysreg_setup(pdev->dev.of_node);
+       }
 
        if (!vexpress_sysreg_base) {
                dev_err(&pdev->dev, "Failed to obtain base address!\n");
index 088872ab63389e49d04dd3f38fb02664fdc929ba..1133a64c2dc9388609ff125c480a82840d9285d1 100644 (file)
@@ -1882,7 +1882,7 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
        }
 }
 
-#define WM5102_MAX_REGISTER 0x1a8fff
+#define WM5102_MAX_REGISTER 0x1a9800
 
 const struct regmap_config wm5102_spi_regmap = {
        .reg_bits = 32,
index 158da5a81a661824a2dca0ee2a9fe93fb5cacfb6..3c09cbb70b1dc01e45f1d6f4fdb93d7e351ad880 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 
 #include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
 
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
@@ -131,6 +132,13 @@ static int ssc_probe(struct platform_device *pdev)
        struct resource *regs;
        struct ssc_device *ssc;
        const struct atmel_ssc_platform_data *plat_dat;
+       struct pinctrl *pinctrl;
+
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(&pdev->dev, "Failed to request pinctrl\n");
+               return PTR_ERR(pinctrl);
+       }
 
        ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
        if (!ssc) {
index 18794aea606282a8925a4ef93d9596948760c3f0..e40ffd9502d17eddaf7f41618d3f33d41b8012af 100644 (file)
@@ -187,13 +187,13 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
                wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
                        (cb = mei_amthif_find_read_list_entry(dev, file)));
 
+               /* Locking again the Mutex */
+               mutex_lock(&dev->device_lock);
+
                if (wait_ret)
                        return -ERESTARTSYS;
 
                dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
-
-               /* Locking again the Mutex */
-               mutex_lock(&dev->device_lock);
        }
 
 
index 636409f9667f397c7ea3ea972fda636cf171e81d..9299a8c29a6fbe4846a06647955ea864ea1921de 100644 (file)
@@ -370,7 +370,7 @@ void mei_watchdog_register(struct mei_device *dev)
 
 void mei_watchdog_unregister(struct mei_device *dev)
 {
-       if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status))
+       if (watchdog_get_drvdata(&amt_wd_dev) == NULL)
                return;
 
        watchdog_set_drvdata(&amt_wd_dev, NULL);
index 8d082b46426b756681c0590581501b8d8cac198a..d971817182f79b92e5136e64eebf79351a40f0d7 100644 (file)
 #include <linux/kthread.h>
 #include "xpc.h"
 
+#ifdef CONFIG_X86_64
+#include <asm/traps.h>
+#endif
+
 /* define two XPC debug device structures to be used with dev_dbg() et al */
 
 struct device_driver xpc_dbg_name = {
@@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
        return NOTIFY_DONE;
 }
 
+/* Used to only allow one cpu to complete disconnect */
+static unsigned int xpc_die_disconnecting;
+
 /*
  * Notify other partitions to deactivate from us by first disengaging from all
  * references to our memory.
@@ -1092,6 +1099,9 @@ xpc_die_deactivate(void)
        long keep_waiting;
        long wait_to_print;
 
+       if (cmpxchg(&xpc_die_disconnecting, 0, 1))
+               return;
+
        /* keep xpc_hb_checker thread from doing anything (just in case) */
        xpc_exiting = 1;
 
@@ -1159,7 +1169,7 @@ xpc_die_deactivate(void)
  * about the lack of a heartbeat.
  */
 static int
-xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
+xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
 {
 #ifdef CONFIG_IA64             /* !!! temporary kludge */
        switch (event) {
@@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
                break;
        }
 #else
-       xpc_die_deactivate();
+       struct die_args *die_args = _die_args;
+
+       switch (event) {
+       case DIE_TRAP:
+               if (die_args->trapnr == X86_TRAP_DF)
+                       xpc_die_deactivate();
+
+               if (((die_args->trapnr == X86_TRAP_MF) ||
+                    (die_args->trapnr == X86_TRAP_XF)) &&
+                   !user_mode_vm(die_args->regs))
+                       xpc_die_deactivate();
+
+               break;
+       case DIE_INT3:
+       case DIE_DEBUG:
+               break;
+       case DIE_OOPS:
+       case DIE_GPF:
+       default:
+               xpc_die_deactivate();
+       }
 #endif
 
        return NOTIFY_DONE;
index 9ff942a346edb59ff05d3a3fec52f052ab8849bb..83269f1d16e380e7b7c4e9ff234b456973c19f72 100644 (file)
@@ -468,6 +468,11 @@ long st_kim_start(void *kim_data)
                if (pdata->chip_enable)
                        pdata->chip_enable(kim_gdata);
 
+               /* Configure BT nShutdown to HIGH state */
+               gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+               mdelay(5);      /* FIXME: a proper toggle */
+               gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+               mdelay(100);
                /* re-initialize the completion */
                INIT_COMPLETION(kim_gdata->ldisc_installed);
                /* send notification to UIM */
@@ -509,7 +514,8 @@ long st_kim_start(void *kim_data)
  *     (b) upon failure to either install ldisc or download firmware.
  *     The function is responsible to (a) notify UIM about un-installation,
  *     (b) flush UART if the ldisc was installed.
- *     (c) invoke platform's chip disabling routine.
+ *     (c) reset BT_EN - pull down nshutdown at the end.
+ *     (d) invoke platform's chip disabling routine.
  */
 long st_kim_stop(void *kim_data)
 {
@@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data)
                err = -ETIMEDOUT;
        }
 
+       /* By default configure BT nShutdown to LOW state */
+       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+       mdelay(1);
+       gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+       mdelay(1);
+       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+
        /* platform specific disable */
        if (pdata->chip_disable)
                pdata->chip_disable(kim_gdata);
@@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev)
        /* refer to itself */
        kim_gdata->core_data->kim_data = kim_gdata;
 
+       /* Claim the chip enable nShutdown gpio from the system */
+       kim_gdata->nshutdown = pdata->nshutdown_gpio;
+       err = gpio_request(kim_gdata->nshutdown, "kim");
+       if (unlikely(err)) {
+               pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
+               return err;
+       }
+
+       /* Configure nShutdown GPIO as output=0 */
+       err = gpio_direction_output(kim_gdata->nshutdown, 0);
+       if (unlikely(err)) {
+               pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
+               return err;
+       }
        /* get reference of pdev for request_firmware
         */
        kim_gdata->kim_pdev = pdev;
@@ -779,10 +806,18 @@ err_core_init:
 
 static int kim_remove(struct platform_device *pdev)
 {
+       /* free the GPIOs requested */
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
        struct kim_data_s       *kim_gdata;
 
        kim_gdata = dev_get_drvdata(&pdev->dev);
 
+       /* Free the Bluetooth/FM/GPIO
+        * nShutdown gpio from the system
+        */
+       gpio_free(pdata->nshutdown_gpio);
+       pr_info("nshutdown GPIO Freed");
+
        debugfs_remove_recursive(kim_debugfs_dir);
        sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
        pr_info("sysfs entries removed");
index 8ee0f74f9374b834f88bcd328c8d233369e61b14..083fcd29c9c60dd89f8cd935589a5501aabbc541 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         = __devexit_p(dw_mci_pci_remove),
+       .remove         = dw_mci_pci_remove,
        .driver         =       {
                .pm =   &dw_mci_pci_pmops
        },
index 222036c9e053b6cc783aa1faf322283d0e257971..5e1fb1d2c422447b62c5c264f1a7be014a5c2f87 100644 (file)
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
 static struct platform_driver dw_mci_pltfm_driver = {
        .probe          = dw_mci_pltfm_probe,
-       .remove         = __devexit_p(dw_mci_pltfm_remove),
+       .remove         = dw_mci_pltfm_remove,
        .driver         = {
                .name           = "dw_mmc",
                .of_match_table = of_match_ptr(dw_mci_pltfm_match),
index de4c20b3936c0fb46d207f4a8896e97b4927be67..f8dd36102949a17bc9cdd7e1651053d5b2f01ed2 100644 (file)
@@ -50,8 +50,6 @@ struct mvsd_host {
        struct timer_list timer;
        struct mmc_host *mmc;
        struct device *dev;
-       struct resource *res;
-       int irq;
        struct clk *clk;
        int gpio_card_detect;
        int gpio_write_protect;
@@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev)
        if (!r || irq < 0 || !mvsd_data)
                return -ENXIO;
 
-       r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
-       if (!r)
-               return -EBUSY;
-
        mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
@@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
        host = mmc_priv(mmc);
        host->mmc = mmc;
        host->dev = &pdev->dev;
-       host->res = r;
        host->base_clock = mvsd_data->clock / 2;
+       host->clk = ERR_PTR(-EINVAL);
 
        mmc->ops = &mvsd_ops;
 
@@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        spin_lock_init(&host->lock);
 
-       host->base = ioremap(r->start, SZ_4K);
+       host->base = devm_request_and_ioremap(&pdev->dev, r);
        if (!host->base) {
                ret = -ENOMEM;
                goto out;
@@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        mvsd_power_down(host);
 
-       ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
+       ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
        if (ret) {
                pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
                goto out;
-       } else
-               host->irq = irq;
+       }
 
        /* Not all platforms can gate the clock, so it is not
           an error if the clock does not exists. */
-       host->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(host->clk)) {
+       host->clk = devm_clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(host->clk))
                clk_prepare_enable(host->clk);
-       }
 
        if (mvsd_data->gpio_card_detect) {
-               ret = gpio_request(mvsd_data->gpio_card_detect,
-                                  DRIVER_NAME " cd");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_card_detect,
+                                           GPIOF_IN, DRIVER_NAME " cd");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_card_detect);
                        irq = gpio_to_irq(mvsd_data->gpio_card_detect);
-                       ret = request_irq(irq, mvsd_card_detect_irq,
-                                         IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
-                                         DRIVER_NAME " cd", host);
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                              mvsd_card_detect_irq,
+                                              IRQ_TYPE_EDGE_RISING |
+                                              IRQ_TYPE_EDGE_FALLING,
+                                              DRIVER_NAME " cd", host);
                        if (ret == 0)
                                host->gpio_card_detect =
                                        mvsd_data->gpio_card_detect;
                        else
-                               gpio_free(mvsd_data->gpio_card_detect);
+                               devm_gpio_free(&pdev->dev,
+                                              mvsd_data->gpio_card_detect);
                }
        }
        if (!host->gpio_card_detect)
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        if (mvsd_data->gpio_write_protect) {
-               ret = gpio_request(mvsd_data->gpio_write_protect,
-                                  DRIVER_NAME " wp");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_write_protect,
+                                           GPIOF_IN, DRIVER_NAME " wp");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_write_protect);
                        host->gpio_write_protect =
                                mvsd_data->gpio_write_protect;
                }
@@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
        return 0;
 
 out:
-       if (host) {
-               if (host->irq)
-                       free_irq(host->irq, host);
-               if (host->gpio_card_detect) {
-                       free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
-               if (host->base)
-                       iounmap(host->base);
-       }
-       if (r)
-               release_resource(r);
-       if (mmc)
-               if (!IS_ERR_OR_NULL(host->clk)) {
+       if (mmc) {
+               if (!IS_ERR(host->clk))
                        clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
                mmc_free_host(mmc);
+       }
 
        return ret;
 }
@@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev)
 {
        struct mmc_host *mmc = platform_get_drvdata(pdev);
 
-       if (mmc) {
-               struct mvsd_host *host = mmc_priv(mmc);
+       struct mvsd_host *host = mmc_priv(mmc);
 
-               if (host->gpio_card_detect) {
-                       free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
-               mmc_remove_host(mmc);
-               free_irq(host->irq, host);
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
-               del_timer_sync(&host->timer);
-               mvsd_power_down(host);
-               iounmap(host->base);
-               release_resource(host->res);
+       mmc_remove_host(mmc);
+       del_timer_sync(&host->timer);
+       mvsd_power_down(host);
+
+       if (!IS_ERR(host->clk))
+               clk_disable_unprepare(host->clk);
+       mmc_free_host(mmc);
 
-               if (!IS_ERR(host->clk)) {
-                       clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
-               mmc_free_host(mmc);
-       }
        platform_set_drvdata(pdev, NULL);
        return 0;
 }
index 571915dfb218382f0d29ea72136b05669b9271ea..f74b5adca64232dd4a8ab7d4a397281b8f02c7a0 100644 (file)
@@ -1060,26 +1060,6 @@ static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host)
        return 0;
 }
 
-static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage)
-{
-       struct rtsx_pcr *pcr = host->pcr;
-       int err;
-
-       if (voltage == SD_IO_3V3) {
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
-               if (err < 0)
-                       return err;
-       } else if (voltage == SD_IO_1V8) {
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
-               if (err < 0)
-                       return err;
-       } else {
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct realtek_pci_sdmmc *host = mmc_priv(mmc);
@@ -1098,11 +1078,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
        rtsx_pci_start_run(pcr);
 
        if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
-               voltage = SD_IO_3V3;
+               voltage = OUTPUT_3V3;
        else
-               voltage = SD_IO_1V8;
+               voltage = OUTPUT_1V8;
 
-       if (voltage == SD_IO_1V8) {
+       if (voltage == OUTPUT_1V8) {
                err = rtsx_pci_write_register(pcr,
                                SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
                if (err < 0)
@@ -1113,11 +1093,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
                        goto out;
        }
 
-       err = sd_change_bank_voltage(host, voltage);
+       err = rtsx_pci_switch_output_voltage(pcr, voltage);
        if (err < 0)
                goto out;
 
-       if (voltage == SD_IO_1V8) {
+       if (voltage == OUTPUT_1V8) {
                err = sd_wait_voltage_stable_2(host);
                if (err < 0)
                        goto out;
index 12b0a78497f68a3563785ebb1e558f96530fa132..2592dddbd965933f10a627073f48ef1caef4e4ba 100644 (file)
@@ -111,7 +111,7 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
        return NULL;
 }
 
-static int __devinit sdhci_acpi_probe(struct platform_device *pdev)
+static int sdhci_acpi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        acpi_handle handle = ACPI_HANDLE(dev);
@@ -214,7 +214,7 @@ err_free:
        return err;
 }
 
-static int __devexit sdhci_acpi_remove(struct platform_device *pdev)
+static int sdhci_acpi_remove(struct platform_device *pdev)
 {
        struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -302,7 +302,7 @@ static struct platform_driver sdhci_acpi_driver = {
                .pm                     = &sdhci_acpi_pm_ops,
        },
        .probe  = sdhci_acpi_probe,
-       .remove = __devexit_p(sdhci_acpi_remove),
+       .remove = sdhci_acpi_remove,
 };
 
 module_platform_driver(sdhci_acpi_driver);
index 5ba4605e4f8017e8f77e285157a7c0abbac4af91..154f0e8e931c5db0ccbdf3a418695aca0a72343c 100644 (file)
@@ -766,7 +766,7 @@ static struct of_device_id wmt_mci_dt_ids[] = {
        { /* Sentinel */ },
 };
 
-static int __devinit wmt_mci_probe(struct platform_device *pdev)
+static int wmt_mci_probe(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
        struct wmt_mci_priv *priv;
@@ -892,7 +892,7 @@ fail1:
        return ret;
 }
 
-static int __devexit wmt_mci_remove(struct platform_device *pdev)
+static int wmt_mci_remove(struct platform_device *pdev)
 {
        struct mmc_host *mmc;
        struct wmt_mci_priv *priv;
index 27f80cd8aef3770ee1d5c67c030088407c0967ba..46dcb54c32ec7994610e3c4a20fbaf85aa879b09 100644 (file)
@@ -272,6 +272,7 @@ config MTD_DOCG3
        tristate "M-Systems Disk-On-Chip G3"
        select BCH
        select BCH_CONST_PARAMS
+       select BITREVERSE
        ---help---
          This provides an MTD device driver for the M-Systems DiskOnChip
          G3 devices.
index ea7ea7b595d86eff7eb8bd3f8952c25b90764150..945c9f7623499fb3798314e508ad65779755b863 100644 (file)
@@ -618,9 +618,8 @@ static char *otp_setup(struct mtd_info *device, char revision)
 /*
  * Register DataFlash device with MTD subsystem.
  */
-static int
-add_dataflash_otp(struct spi_device *spi, char *name,
-               int nr_pages, int pagesize, int pageoffset, char revision)
+static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
+                            int pagesize, int pageoffset, char revision)
 {
        struct dataflash                *priv;
        struct mtd_info                 *device;
@@ -679,9 +678,8 @@ add_dataflash_otp(struct spi_device *spi, char *name,
        return err;
 }
 
-static inline int
-add_dataflash(struct spi_device *spi, char *name,
-               int nr_pages, int pagesize, int pageoffset)
+static inline int add_dataflash(struct spi_device *spi, char *name,
+                               int nr_pages, int pagesize, int pageoffset)
 {
        return add_dataflash_otp(spi, name, nr_pages, pagesize,
                        pageoffset, 0);
index 2d2c2a5d4d2ac0e7df2698b7002f53608fbd9c79..2aabd96bf0fff57381efb499a83d88d4c17e476d 100644 (file)
@@ -757,7 +757,7 @@ err_probe:
 
 #ifdef CONFIG_OF
 static int spear_smi_probe_config_dt(struct platform_device *pdev,
-                                              struct device_node *np)
+                                    struct device_node *np)
 {
        struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *pp = NULL;
@@ -800,7 +800,7 @@ static int spear_smi_probe_config_dt(struct platform_device *pdev,
 }
 #else
 static int spear_smi_probe_config_dt(struct platform_device *pdev,
-                                              struct device_node *np)
+                                    struct device_node *np)
 {
        return -ENOSYS;
 }
index ff8681a25831052f0773b1829fec9336f2844aba..f784cf0caa13b03d7a24542befe1a29e3638e35f 100644 (file)
@@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
 }
 
 static int esb2rom_init_one(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+                           const struct pci_device_id *ent)
 {
        static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
        struct esb2rom_window *window = &esb2rom_window;
index 3ee2ad1dcbe76cb327b3e0c6b94e33e30db7d3c1..b14053b2502618e89fc7889ff385bc68db8f074d 100644 (file)
@@ -189,8 +189,7 @@ static void vr_nor_pci_remove(struct pci_dev *dev)
        pci_disable_device(dev);
 }
 
-static int
-vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct vr_nor_mtd *p = NULL;
        unsigned int exp_timing_cs0;
index ed82914966f52db7ebdd0d5524d5595ec0af9d72..c3aebd5da5d61046c9f9047148d3d7347a00ec2a 100644 (file)
@@ -253,8 +253,7 @@ static struct pci_device_id mtd_pci_ids[] = {
  * Generic code follows.
  */
 
-static int
-mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
        struct map_pci_info *map = NULL;
@@ -308,8 +307,7 @@ out:
        return err;
 }
 
-static void
-mtd_pci_remove(struct pci_dev *dev)
+static void mtd_pci_remove(struct pci_dev *dev)
 {
        struct mtd_info *mtd = pci_get_drvdata(dev);
        struct map_pci_info *map = mtd->priv;
index 37cdc201652f612406883f60243121fc78d55a60..7901d72c92425dc41485947468231cf7776db372 100644 (file)
@@ -78,7 +78,7 @@ static int of_flash_remove(struct platform_device *dev)
  * compatible binding, which has an extra "probe-type" property
  * describing the type of flash probe necessary. */
 static struct mtd_info *obsolete_probe(struct platform_device *dev,
-                                                 struct map_info *map)
+                                      struct map_info *map)
 {
        struct device_node *dp = dev->dev.of_node;
        const char *of_probe;
@@ -170,7 +170,7 @@ static int of_flash_probe(struct platform_device *dev)
        resource_size_t res_size;
        struct mtd_part_parser_data ppdata;
        bool map_indirect;
-       const char *mtd_name;
+       const char *mtd_name = NULL;
 
        match = of_match_device(of_flash_match, &dev->dev);
        if (!match)
index afea93b515d5c70e93974b5f02b29ca8c6e6dd7b..dc6df9abea0bb51666566b06800ba84d7fee6fe9 100644 (file)
@@ -66,8 +66,8 @@ static unsigned int pismo_width_to_bytes(unsigned int width)
        return 1 << width;
 }
 
-static int pismo_eeprom_read(struct i2c_client *client, void *buf,
-       u8 addr, size_t size)
+static int pismo_eeprom_read(struct i2c_client *client, void *buf, u8 addr,
+                            size_t size)
 {
        int ret;
        struct i2c_msg msg[] = {
@@ -89,7 +89,8 @@ static int pismo_eeprom_read(struct i2c_client *client, void *buf,
 }
 
 static int pismo_add_device(struct pismo_data *pismo, int i,
-       struct pismo_mem *region, const char *name, void *pdata, size_t psize)
+                           struct pismo_mem *region, const char *name,
+                           void *pdata, size_t psize)
 {
        struct platform_device *dev;
        struct resource res = { };
@@ -130,7 +131,7 @@ static int pismo_add_device(struct pismo_data *pismo, int i,
 }
 
 static int pismo_add_nor(struct pismo_data *pismo, int i,
-       struct pismo_mem *region)
+                        struct pismo_mem *region)
 {
        struct physmap_flash_data data = {
                .width = region->width,
@@ -144,7 +145,7 @@ static int pismo_add_nor(struct pismo_data *pismo, int i,
 }
 
 static int pismo_add_sram(struct pismo_data *pismo, int i,
-       struct pismo_mem *region)
+                         struct pismo_mem *region)
 {
        struct platdata_mtd_ram data = {
                .bankwidth = region->width,
@@ -155,7 +156,7 @@ static int pismo_add_sram(struct pismo_data *pismo, int i,
 }
 
 static void pismo_add_one(struct pismo_data *pismo, int i,
-       const struct pismo_cs_block *cs, phys_addr_t base)
+                         const struct pismo_cs_block *cs, phys_addr_t base)
 {
        struct device *dev = &pismo->client->dev;
        struct pismo_mem region;
@@ -211,7 +212,7 @@ static int pismo_remove(struct i2c_client *client)
 }
 
 static int pismo_probe(struct i2c_client *client,
-                                const struct i2c_device_id *id)
+                      const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct pismo_pdata *pdata = client->dev.platform_data;
index 71796137e97b12c2061640e3e3a2a9aa0784800d..c77b68c9412f8631955f6b52df633a6ab3fbce07 100644 (file)
@@ -69,8 +69,7 @@ static struct map_info scb2_map = {
 };
 static int region_fail;
 
-static int
-scb2_fixup_mtd(struct mtd_info *mtd)
+static int scb2_fixup_mtd(struct mtd_info *mtd)
 {
        int i;
        int done = 0;
@@ -133,8 +132,8 @@ scb2_fixup_mtd(struct mtd_info *mtd)
 /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
 #define CSB5_FCR       0x41
 #define CSB5_FCR_DECODE_ALL 0x0e
-static int
-scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int scb2_flash_probe(struct pci_dev *dev,
+                           const struct pci_device_id *ent)
 {
        u8 reg;
 
@@ -197,8 +196,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        return 0;
 }
 
-static void
-scb2_flash_remove(struct pci_dev *dev)
+static void scb2_flash_remove(struct pci_dev *dev)
 {
        if (!scb2_mtd)
                return;
index 90bdca61c797d9f4be16ea8ac6e71956363e1914..c516a9408087921a9d8c40b243e2f9005964b2e6 100644 (file)
@@ -338,7 +338,7 @@ static int pmecc_get_ecc_bytes(int cap, int sector_size)
 }
 
 static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
-       int oobsize, int ecc_len)
+                                   int oobsize, int ecc_len)
 {
        int i;
 
@@ -1213,7 +1213,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 
 #if defined(CONFIG_OF)
 static int atmel_of_init_port(struct atmel_nand_host *host,
-                                        struct device_node *np)
+                             struct device_node *np)
 {
        u32 val, table_offset;
        u32 offset[2];
@@ -1300,7 +1300,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
 }
 #else
 static int atmel_of_init_port(struct atmel_nand_host *host,
-                                        struct device_node *np)
+                             struct device_node *np)
 {
        return -EINVAL;
 }
index 2b8b05bec3ddf3b530653f4a006caecba443dc40..8363a9a5fa3f7984ca4c1706be76544eb18254c4 100644 (file)
@@ -66,7 +66,7 @@ out:
        return err;
 }
 
-static int __devexit bcm47xxnflash_remove(struct platform_device *pdev)
+static int bcm47xxnflash_remove(struct platform_device *pdev)
 {
        struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
 
@@ -77,7 +77,7 @@ static int __devexit bcm47xxnflash_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver bcm47xxnflash_driver = {
-       .remove = __devexit_p(bcm47xxnflash_remove),
+       .remove = bcm47xxnflash_remove,
        .driver = {
                .name = "bcma_nflash",
                .owner = THIS_MODULE,
index 86c9a79b89b3e863f9377eebb8c9b6ae18500dd9..595de4012e71971c6453a5499334c28e6185390b 100644 (file)
@@ -17,8 +17,8 @@
 #include "bcm47xxnflash.h"
 
 /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
- * shown 164 retries as maxiumum. */
-#define NFLASH_READY_RETRIES           1000
+ * shown ~1000 retries as maxiumum. */
+#define NFLASH_READY_RETRIES           10000
 
 #define NFLASH_SECTOR_SIZE             512
 
index 3502606f64806a06ad426a112174c0117482e8dc..feae55c7b88046b3169820449b002d0ae562a5c4 100644 (file)
@@ -523,7 +523,7 @@ static struct nand_ecclayout hwecc4_2048 __initconst = {
 static const struct of_device_id davinci_nand_of_match[] = {
        {.compatible = "ti,davinci-nand", },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
 
 static struct davinci_nand_pdata
index 5a8f5c4ce512255ed38a30b245149d618d044c0e..04e07252d74b82684532ad713e5e9fcfbd4e04aa 100644 (file)
@@ -153,8 +153,8 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 }
 
 static int fun_chip_init(struct fsl_upm_nand *fun,
-                                  const struct device_node *upm_np,
-                                  const struct resource *io_res)
+                        const struct device_node *upm_np,
+                        const struct resource *io_res)
 {
        int ret;
        struct device_node *flash_np;
index 1d7446434b0ea4cf42a983de97661cfdc6a2dc33..67e62d3d495cce93a4d633937466c4c6a9524177 100644 (file)
@@ -865,7 +865,7 @@ static bool filter(struct dma_chan *chan, void *slave)
 
 #ifdef CONFIG_OF
 static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
-                                              struct device_node *np)
+                                    struct device_node *np)
 {
        struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
        u32 val;
@@ -887,7 +887,7 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 }
 #else
 static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
-                                              struct device_node *np)
+                                    struct device_node *np)
 {
        return -ENOSYS;
 }
index 5cd141f7bfc262bae10e7bfadc5b8a7e2b8dc848..e9b1c47e3cf96111183b210967b3b824b7efdbe6 100644 (file)
@@ -319,8 +319,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
        return 0;
 }
 
-static int
-acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
+static int acquire_register_block(struct gpmi_nand_data *this,
+                                 const char *res_name)
 {
        struct platform_device *pdev = this->pdev;
        struct resources *res = &this->resources;
@@ -360,8 +360,7 @@ static void release_register_block(struct gpmi_nand_data *this)
        res->bch_regs = NULL;
 }
 
-static int
-acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
+static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 {
        struct platform_device *pdev = this->pdev;
        struct resources *res = &this->resources;
index 8d415f014e1dbda06e78b4091f1533878b5bf57f..b76460eeaf2253f7db3e69404ff4afb51298f84b 100644 (file)
@@ -326,7 +326,8 @@ static inline void jz_nand_iounmap_resource(struct resource *res,
 static int jz_nand_detect_bank(struct platform_device *pdev,
                               struct jz_nand *nand, unsigned char bank,
                               size_t chipnr, uint8_t *nand_maf_id,
-                              uint8_t *nand_dev_id) {
+                              uint8_t *nand_dev_id)
+{
        int ret;
        int gpio;
        char gpio_name[9];
index 8323ac991ad154d7304958059cab37af6f2d6541..3766682a02898135ce4274b5a0baeac0eee772c9 100644 (file)
@@ -2857,8 +2857,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        int i;
        int val;
 
-       /* ONFI need to be probed in 8 bits mode */
-       WARN_ON(chip->options & NAND_BUSWIDTH_16);
+       /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */
+       if (chip->options & NAND_BUSWIDTH_16) {
+               pr_err("Trying ONFI probe in 16 bits mode, aborting !\n");
+               return 0;
+       }
        /* Try ONFI for unknown chip or LP */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
        if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
index 1877ed7ca0864ed4adfb614de862ed40dde730bd..1c9e09fbdff8346e99413e0313d03ed401f463e2 100644 (file)
@@ -1053,6 +1053,7 @@ static ssize_t bonding_store_primary(struct device *d,
                pr_info("%s: Setting primary slave to None.\n",
                        bond->dev->name);
                bond->primary_slave = NULL;
+               memset(bond->params.primary, 0, sizeof(bond->params.primary));
                bond_select_active_slave(bond);
                goto out;
        }
index 5233b8f58d773b6edb44f306f477674f05415084..2282b1ae97653d825fe6f37c2b22cf7ecd37a945 100644 (file)
@@ -488,8 +488,12 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 
        priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),
                        IFX_WRITE_LOW_16BIT(mask));
+
+       /* According to C_CAN documentation, the reserved bit
+        * in IFx_MASK2 register is fixed 1
+        */
        priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface),
-                       IFX_WRITE_HIGH_16BIT(mask));
+                       IFX_WRITE_HIGH_16BIT(mask) | BIT(13));
 
        priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
                        IFX_WRITE_LOW_16BIT(id));
@@ -960,7 +964,7 @@ static int c_can_handle_bus_err(struct net_device *dev,
                break;
        case LEC_ACK_ERROR:
                netdev_dbg(dev, "ack error\n");
-               cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
+               cf->data[3] |= (CAN_ERR_PROT_LOC_ACK |
                                CAN_ERR_PROT_LOC_ACK_DEL);
                break;
        case LEC_BIT1_ERROR:
@@ -973,7 +977,7 @@ static int c_can_handle_bus_err(struct net_device *dev,
                break;
        case LEC_CRC_ERROR:
                netdev_dbg(dev, "CRC error\n");
-               cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+               cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
                                CAN_ERR_PROT_LOC_CRC_DEL);
                break;
        default:
index 7d1748575b1fffc45f38351ea3f071269545548a..5c314a961970b0041c7776da283979f00c4114f8 100644 (file)
@@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)
                stats->rx_errors++;
                break;
        case PCH_CRC_ERR:
-               cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+               cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ |
                               CAN_ERR_PROT_LOC_CRC_DEL;
                priv->can.can_stats.bus_error++;
                stats->rx_errors++;
index f898c6363729b2a41be58c824f3f3bb145a95897..300581b24ff32860447e3646079024646e77a592 100644 (file)
@@ -746,12 +746,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
                }
                if (err_status & HECC_CANES_CRCE) {
                        hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE);
-                       cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+                       cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ |
                                        CAN_ERR_PROT_LOC_CRC_DEL;
                }
                if (err_status & HECC_CANES_ACKE) {
                        hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE);
-                       cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
+                       cf->data[3] |= CAN_ERR_PROT_LOC_ACK |
                                        CAN_ERR_PROT_LOC_ACK_DEL;
                }
        }
index 66df936380859b55ab0b8b15595319bfeb98c98a..ffd8de28a76ad2c69a96daab3c59dbe29127faa1 100644 (file)
@@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link)
        netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
                    cardname, dev->base_addr, dev->irq, dev->dev_addr);
        netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
-                   8 << config & Ram_size,
+                   8 << (config & Ram_size),
                    ram_split[(config & Ram_split) >> Ram_split_shift],
                    config & Autoselect ? "autoselect " : "");
 
index e49c0eff040b50a95bdacc050f8ff3a83f172a8e..a9481606bbcd713f6fa446325521b2309b64c856 100644 (file)
@@ -61,6 +61,7 @@ config BFIN_RX_DESC_NUM
 
 config BFIN_MAC_USE_HWSTAMP
        bool "Use IEEE 1588 hwstamp"
+       depends on BFIN_MAC && BF518
        select PTP_1588_CLOCK
        default y
        ---help---
index 56d3f697e0c7f0a05d8044a37f954c8d536f1c0a..0035c01660b6149bc3177ada829a39d4720c805b 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "atl1c.h"
 
-#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
+#define ATL1C_DRV_VERSION "1.0.1.1-NAPI"
 char atl1c_driver_name[] = "atl1c";
 char atl1c_driver_version[] = ATL1C_DRV_VERSION;
 
@@ -1652,6 +1652,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
        u16 num_alloc = 0;
        u16 rfd_next_to_use, next_next;
        struct atl1c_rx_free_desc *rfd_desc;
+       dma_addr_t mapping;
 
        next_next = rfd_next_to_use = rfd_ring->next_to_use;
        if (++next_next == rfd_ring->count)
@@ -1678,9 +1679,18 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
                ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
                buffer_info->skb = skb;
                buffer_info->length = adapter->rx_buffer_len;
-               buffer_info->dma = pci_map_single(pdev, vir_addr,
+               mapping = pci_map_single(pdev, vir_addr,
                                                buffer_info->length,
                                                PCI_DMA_FROMDEVICE);
+               if (unlikely(pci_dma_mapping_error(pdev, mapping))) {
+                       dev_kfree_skb(skb);
+                       buffer_info->skb = NULL;
+                       buffer_info->length = 0;
+                       ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
+                       netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed");
+                       break;
+               }
+               buffer_info->dma = mapping;
                ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
                        ATL1C_PCIMAP_FROMDEVICE);
                rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -2015,7 +2025,29 @@ check_sum:
        return 0;
 }
 
-static void atl1c_tx_map(struct atl1c_adapter *adapter,
+static void atl1c_tx_rollback(struct atl1c_adapter *adpt,
+                             struct atl1c_tpd_desc *first_tpd,
+                             enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type];
+       struct atl1c_buffer *buffer_info;
+       struct atl1c_tpd_desc *tpd;
+       u16 first_index, index;
+
+       first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc;
+       index = first_index;
+       while (index != tpd_ring->next_to_use) {
+               tpd = ATL1C_TPD_DESC(tpd_ring, index);
+               buffer_info = &tpd_ring->buffer_info[index];
+               atl1c_clean_buffer(adpt->pdev, buffer_info, 0);
+               memset(tpd, 0, sizeof(struct atl1c_tpd_desc));
+               if (++index == tpd_ring->count)
+                       index = 0;
+       }
+       tpd_ring->next_to_use = first_index;
+}
+
+static int atl1c_tx_map(struct atl1c_adapter *adapter,
                      struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
                        enum atl1c_trans_queue type)
 {
@@ -2040,7 +2072,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
                buffer_info->length = map_len;
                buffer_info->dma = pci_map_single(adapter->pdev,
                                        skb->data, hdr_len, PCI_DMA_TODEVICE);
-               ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
+               if (unlikely(pci_dma_mapping_error(adapter->pdev,
+                                                  buffer_info->dma)))
+                       goto err_dma;
+
                ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
                        ATL1C_PCIMAP_TODEVICE);
                mapped_len += map_len;
@@ -2062,6 +2097,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
                buffer_info->dma =
                        pci_map_single(adapter->pdev, skb->data + mapped_len,
                                        buffer_info->length, PCI_DMA_TODEVICE);
+               if (unlikely(pci_dma_mapping_error(adapter->pdev,
+                                                  buffer_info->dma)))
+                       goto err_dma;
+
                ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
                ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
                        ATL1C_PCIMAP_TODEVICE);
@@ -2083,6 +2122,9 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
                                                    frag, 0,
                                                    buffer_info->length,
                                                    DMA_TO_DEVICE);
+               if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma))
+                       goto err_dma;
+
                ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
                ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
                        ATL1C_PCIMAP_TODEVICE);
@@ -2095,6 +2137,13 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
        /* The last buffer info contain the skb address,
           so it will be free after unmap */
        buffer_info->skb = skb;
+
+       return 0;
+
+err_dma:
+       buffer_info->dma = 0;
+       buffer_info->length = 0;
+       return -1;
 }
 
 static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
@@ -2157,10 +2206,18 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
        if (skb_network_offset(skb) != ETH_HLEN)
                tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
 
-       atl1c_tx_map(adapter, skb, tpd, type);
-       atl1c_tx_queue(adapter, skb, tpd, type);
+       if (atl1c_tx_map(adapter, skb, tpd, type) < 0) {
+               netif_info(adapter, tx_done, adapter->netdev,
+                          "tx-skb droppted due to dma error\n");
+               /* roll back tpd/buffer */
+               atl1c_tx_rollback(adapter, tpd, type);
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+               dev_kfree_skb(skb);
+       } else {
+               atl1c_tx_queue(adapter, skb, tpd, type);
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+       }
 
-       spin_unlock_irqrestore(&adapter->tx_lock, flags);
        return NETDEV_TX_OK;
 }
 
index 01588b66a38c0fea2d489b869d730fb8966c3419..a5edac8df67bb44576f61a70ab4ca9e825d644e7 100644 (file)
@@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
                new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET;
        }
 
-       memcpy(&bp->bnx2x_txq[old_txdata_index],
-              &bp->bnx2x_txq[new_txdata_index],
+       memcpy(&bp->bnx2x_txq[new_txdata_index],
+              &bp->bnx2x_txq[old_txdata_index],
               sizeof(struct bnx2x_fp_txdata));
        to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index];
 }
 
+/**
+ * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact
+ *
+ * @bp:        driver handle
+ * @delta:     number of eth queues which were not allocated
+ */
+static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta)
+{
+       int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp);
+
+       /* Queue pointer cannot be re-set on an fp-basis, as moving pointer
+        * backward along the array could cause memory to be overriden
+        */
+       for (cos = 1; cos < bp->max_cos; cos++) {
+               for (i = 0; i < old_eth_num - delta; i++) {
+                       struct bnx2x_fastpath *fp = &bp->fp[i];
+                       int new_idx = cos * (old_eth_num - delta) + i;
+
+                       memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos],
+                              sizeof(struct bnx2x_fp_txdata));
+                       fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx];
+               }
+       }
+}
+
 int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
 
 /* free skb in the packet ring at pos idx
@@ -479,13 +504,11 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
                                        tpa_info->parsing_flags, len_on_bd);
 
-               /* set for GRO */
-               if (fp->mode == TPA_MODE_GRO)
-                       skb_shinfo(skb)->gso_type =
-                           (GET_FLAG(tpa_info->parsing_flags,
-                                     PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
-                                               PRS_FLAG_OVERETH_IPV6) ?
-                               SKB_GSO_TCPV6 : SKB_GSO_TCPV4;
+               skb_shinfo(skb)->gso_type =
+                       (GET_FLAG(tpa_info->parsing_flags,
+                                 PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
+                        PRS_FLAG_OVERETH_IPV6) ?
+                       SKB_GSO_TCPV6 : SKB_GSO_TCPV4;
        }
 
 
@@ -3863,6 +3886,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
                int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
 
                WARN_ON(delta < 0);
+               bnx2x_shrink_eth_fp(bp, delta);
                if (CNIC_SUPPORT(bp))
                        /* move non eth FPs next to last eth FP
                         * must be done in that order
index 277f17e3c8f850bac954db7d99c55b7f06d194eb..a427b49a886ccea8a6d904daa473a59f5a676c5b 100644 (file)
@@ -2777,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
                } else if ((info->flow_type == UDP_V6_FLOW) &&
                           (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
                        bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
-                       return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
                        DP(BNX2X_MSG_ETHTOOL,
                           "rss re-configured, UDP 4-tupple %s\n",
                           udp_rss_requested ? "enabled" : "disabled");
+                       return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
                } else {
                        return 0;
                }
index 940ef859dc6054338b884abce2c519e0ba4a89ea..5523da3afcdccd23f4b90c6191f722d02063c1d3 100644 (file)
@@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel");
 
 struct workqueue_struct *bnx2x_wq;
 
+struct bnx2x_mac_vals {
+       u32 xmac_addr;
+       u32 xmac_val;
+       u32 emac_addr;
+       u32 emac_val;
+       u32 umac_addr;
+       u32 umac_val;
+       u32 bmac_addr;
+       u32 bmac_val[2];
+};
+
 enum bnx2x_board_type {
        BCM57710 = 0,
        BCM57711,
@@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
                bnx2x_undi_int_disable_e1h(bp);
 }
 
-static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
+                                       struct bnx2x_mac_vals *vals)
 {
        u32 val, base_addr, offset, mask, reset_reg;
        bool mac_stopped = false;
        u8 port = BP_PORT(bp);
 
+       /* reset addresses as they also mark which values were changed */
+       vals->bmac_addr = 0;
+       vals->umac_addr = 0;
+       vals->xmac_addr = 0;
+       vals->emac_addr = 0;
+
        reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
 
        if (!CHIP_IS_E3(bp)) {
@@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
                         */
                        wb_data[0] = REG_RD(bp, base_addr + offset);
                        wb_data[1] = REG_RD(bp, base_addr + offset + 0x4);
+                       vals->bmac_addr = base_addr + offset;
+                       vals->bmac_val[0] = wb_data[0];
+                       vals->bmac_val[1] = wb_data[1];
                        wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
-                       REG_WR(bp, base_addr + offset, wb_data[0]);
-                       REG_WR(bp, base_addr + offset + 0x4, wb_data[1]);
+                       REG_WR(bp, vals->bmac_addr, wb_data[0]);
+                       REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]);
 
                }
                BNX2X_DEV_INFO("Disable emac Rx\n");
-               REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0);
-
+               vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4;
+               vals->emac_val = REG_RD(bp, vals->emac_addr);
+               REG_WR(bp, vals->emac_addr, 0);
                mac_stopped = true;
        } else {
                if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) {
@@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
                               val & ~(1 << 1));
                        REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
                               val | (1 << 1));
-                       REG_WR(bp, base_addr + XMAC_REG_CTRL, 0);
+                       vals->xmac_addr = base_addr + XMAC_REG_CTRL;
+                       vals->xmac_val = REG_RD(bp, vals->xmac_addr);
+                       REG_WR(bp, vals->xmac_addr, 0);
                        mac_stopped = true;
                }
                mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
                if (mask & reset_reg) {
                        BNX2X_DEV_INFO("Disable umac Rx\n");
                        base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
-                       REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0);
+                       vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG;
+                       vals->umac_val = REG_RD(bp, vals->umac_addr);
+                       REG_WR(bp, vals->umac_addr, 0);
                        mac_stopped = true;
                }
        }
@@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
 {
        u32 reset_reg, tmp_reg = 0, rc;
        bool prev_undi = false;
+       struct bnx2x_mac_vals mac_vals;
+
        /* It is possible a previous function received 'common' answer,
         * but hasn't loaded yet, therefore creating a scenario of
         * multiple functions receiving 'common' on the same path.
         */
        BNX2X_DEV_INFO("Common unload Flow\n");
 
+       memset(&mac_vals, 0, sizeof(mac_vals));
+
        if (bnx2x_prev_is_path_marked(bp))
                return bnx2x_prev_mcp_done(bp);
 
@@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
                u32 timer_count = 1000;
 
                /* Close the MAC Rx to prevent BRB from filling up */
-               bnx2x_prev_unload_close_mac(bp);
+               bnx2x_prev_unload_close_mac(bp, &mac_vals);
+
+               /* close LLH filters towards the BRB */
+               bnx2x_set_rx_filter(&bp->link_params, 0);
 
                /* Check if the UNDI driver was previously loaded
                 * UNDI driver initializes CID offset for normal bell to 0x7
@@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
        /* No packets are in the pipeline, path is ready for reset */
        bnx2x_reset_common(bp);
 
+       if (mac_vals.xmac_addr)
+               REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val);
+       if (mac_vals.umac_addr)
+               REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val);
+       if (mac_vals.emac_addr)
+               REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val);
+       if (mac_vals.bmac_addr) {
+               REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]);
+               REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]);
+       }
+
        rc = bnx2x_prev_mark_path(bp, prev_undi);
        if (rc) {
                bnx2x_prev_mcp_done(bp);
index 78ea90c40e1902af09272a80b09010da52ae6c6b..bdb086934cd95de72cd1aa02cf1cb4b6baaaafc3 100644 (file)
@@ -1283,14 +1283,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
        return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
 }
 
-#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
-       tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
-                            MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
-                            MII_TG3_AUXCTL_ACTL_TX_6DB)
+static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
+{
+       u32 val;
+       int err;
 
-#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
-       tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
-                            MII_TG3_AUXCTL_ACTL_TX_6DB);
+       err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
+
+       if (err)
+               return err;
+       if (enable)
+
+               val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
+       else
+               val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
+
+       err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
+                                  val | MII_TG3_AUXCTL_ACTL_TX_6DB);
+
+       return err;
+}
 
 static int tg3_bmcr_reset(struct tg3 *tp)
 {
@@ -2223,7 +2235,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
 
        otp = tp->phy_otp;
 
-       if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
+       if (tg3_phy_toggle_auxctl_smdsp(tp, true))
                return;
 
        phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
@@ -2248,7 +2260,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
              ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
        tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
 
-       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+       tg3_phy_toggle_auxctl_smdsp(tp, false);
 }
 
 static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
@@ -2284,9 +2296,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
 
        if (!tp->setlpicnt) {
                if (current_link_up == 1 &&
-                  !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+                  !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                        tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
-                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+                       tg3_phy_toggle_auxctl_smdsp(tp, false);
                }
 
                val = tr32(TG3_CPMU_EEE_MODE);
@@ -2302,11 +2314,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp)
            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
             tg3_flag(tp, 57765_CLASS)) &&
-           !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+           !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                val = MII_TG3_DSP_TAP26_ALNOKO |
                      MII_TG3_DSP_TAP26_RMRXSTO;
                tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
-               TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               tg3_phy_toggle_auxctl_smdsp(tp, false);
        }
 
        val = tr32(TG3_CPMU_EEE_MODE);
@@ -2450,7 +2462,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
                tg3_writephy(tp, MII_CTRL1000,
                             CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
 
-               err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+               err = tg3_phy_toggle_auxctl_smdsp(tp, true);
                if (err)
                        return err;
 
@@ -2471,7 +2483,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
        tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
 
-       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+       tg3_phy_toggle_auxctl_smdsp(tp, false);
 
        tg3_writephy(tp, MII_CTRL1000, phy9_orig);
 
@@ -2572,10 +2584,10 @@ static int tg3_phy_reset(struct tg3 *tp)
 
 out:
        if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
-           !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+           !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                tg3_phydsp_write(tp, 0x201f, 0x2aaa);
                tg3_phydsp_write(tp, 0x000a, 0x0323);
-               TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               tg3_phy_toggle_auxctl_smdsp(tp, false);
        }
 
        if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
@@ -2584,14 +2596,14 @@ out:
        }
 
        if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
-               if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+               if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                        tg3_phydsp_write(tp, 0x000a, 0x310b);
                        tg3_phydsp_write(tp, 0x201f, 0x9506);
                        tg3_phydsp_write(tp, 0x401f, 0x14e2);
-                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+                       tg3_phy_toggle_auxctl_smdsp(tp, false);
                }
        } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
-               if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+               if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                        tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
                        if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
@@ -2600,7 +2612,7 @@ out:
                        } else
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
 
-                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+                       tg3_phy_toggle_auxctl_smdsp(tp, false);
                }
        }
 
@@ -4009,7 +4021,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
        tw32(TG3_CPMU_EEE_MODE,
             tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 
-       err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+       err = tg3_phy_toggle_auxctl_smdsp(tp, true);
        if (!err) {
                u32 err2;
 
@@ -4042,7 +4054,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
                                                 MII_TG3_DSP_CH34TP2_HIBW01);
                }
 
-               err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               err2 = tg3_phy_toggle_auxctl_smdsp(tp, false);
                if (!err)
                        err = err2;
        }
@@ -6950,6 +6962,9 @@ static void tg3_poll_controller(struct net_device *dev)
        int i;
        struct tg3 *tp = netdev_priv(dev);
 
+       if (tg3_irq_sync(tp))
+               return;
+
        for (i = 0; i < tp->irq_cnt; i++)
                tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]);
 }
@@ -16367,6 +16382,7 @@ static int tg3_init_one(struct pci_dev *pdev,
        tp->pm_cap = pm_cap;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
+       tp->irq_sync = 1;
 
        if (tg3_debug > 0)
                tp->msg_enable = tg3_debug;
index a9b0830fb39d90b3227fe14741c8a4a3f09dc2d6..b9d4bb9530e5da5e2f30958a2fad6e5347b8af99 100644 (file)
@@ -693,6 +693,11 @@ static int macb_poll(struct napi_struct *napi, int budget)
                 * get notified when new packets arrive.
                 */
                macb_writel(bp, IER, MACB_RX_INT_FLAGS);
+
+               /* Packets received while interrupts were disabled */
+               status = macb_readl(bp, RSR);
+               if (unlikely(status))
+                       napi_reschedule(napi);
        }
 
        /* TODO: Handle errors */
index b407043ce9b0df3c1286fb3c0051f012cfa5e5b0..f7f02900f6508f0c8a7f8b6b41558aa85550e291 100644 (file)
@@ -548,6 +548,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p)
                return -1;
        }
 
+       /* All frames should fit into a single buffer */
+       if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG))
+               return -1;
+
        /* Check if packet has checksum already */
        if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) &&
                !(ext_status & RXDESC_IP_PAYLOAD_MASK))
index 378988b5709a2262b98c0a790072be38b837cdf3..6db997c78a5fa2cf3b281acb1ed2887f8b62aa72 100644 (file)
@@ -35,6 +35,8 @@
 #ifndef __CXGB4_H__
 #define __CXGB4_H__
 
+#include "t4_hw.h"
+
 #include <linux/bitops.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
@@ -212,6 +214,8 @@ struct tp_err_stats {
 struct tp_params {
        unsigned int ntxchan;        /* # of Tx channels */
        unsigned int tre;            /* log2 of core clocks per TP tick */
+       unsigned short tx_modq_map;  /* TX modulation scheduler queue to */
+                                    /* channel map */
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
@@ -526,6 +530,7 @@ struct adapter {
        struct net_device *port[MAX_NPORTS];
        u8 chan_map[NCHAN];                   /* channel -> port map */
 
+       u32 filter_mode;
        unsigned int l2t_start;
        unsigned int l2t_end;
        struct l2t_data *l2t;
@@ -545,6 +550,129 @@ struct adapter {
        spinlock_t stats_lock;
 };
 
+/* Defined bit width of user definable filter tuples
+ */
+#define ETHTYPE_BITWIDTH 16
+#define FRAG_BITWIDTH 1
+#define MACIDX_BITWIDTH 9
+#define FCOE_BITWIDTH 1
+#define IPORT_BITWIDTH 3
+#define MATCHTYPE_BITWIDTH 3
+#define PROTO_BITWIDTH 8
+#define TOS_BITWIDTH 8
+#define PF_BITWIDTH 8
+#define VF_BITWIDTH 8
+#define IVLAN_BITWIDTH 16
+#define OVLAN_BITWIDTH 16
+
+/* Filter matching rules.  These consist of a set of ingress packet field
+ * (value, mask) tuples.  The associated ingress packet field matches the
+ * tuple when ((field & mask) == value).  (Thus a wildcard "don't care" field
+ * rule can be constructed by specifying a tuple of (0, 0).)  A filter rule
+ * matches an ingress packet when all of the individual individual field
+ * matching rules are true.
+ *
+ * Partial field masks are always valid, however, while it may be easy to
+ * understand their meanings for some fields (e.g. IP address to match a
+ * subnet), for others making sensible partial masks is less intuitive (e.g.
+ * MPS match type) ...
+ *
+ * Most of the following data structures are modeled on T4 capabilities.
+ * Drivers for earlier chips use the subsets which make sense for those chips.
+ * We really need to come up with a hardware-independent mechanism to
+ * represent hardware filter capabilities ...
+ */
+struct ch_filter_tuple {
+       /* Compressed header matching field rules.  The TP_VLAN_PRI_MAP
+        * register selects which of these fields will participate in the
+        * filter match rules -- up to a maximum of 36 bits.  Because
+        * TP_VLAN_PRI_MAP is a global register, all filters must use the same
+        * set of fields.
+        */
+       uint32_t ethtype:ETHTYPE_BITWIDTH;      /* Ethernet type */
+       uint32_t frag:FRAG_BITWIDTH;            /* IP fragmentation header */
+       uint32_t ivlan_vld:1;                   /* inner VLAN valid */
+       uint32_t ovlan_vld:1;                   /* outer VLAN valid */
+       uint32_t pfvf_vld:1;                    /* PF/VF valid */
+       uint32_t macidx:MACIDX_BITWIDTH;        /* exact match MAC index */
+       uint32_t fcoe:FCOE_BITWIDTH;            /* FCoE packet */
+       uint32_t iport:IPORT_BITWIDTH;          /* ingress port */
+       uint32_t matchtype:MATCHTYPE_BITWIDTH;  /* MPS match type */
+       uint32_t proto:PROTO_BITWIDTH;          /* protocol type */
+       uint32_t tos:TOS_BITWIDTH;              /* TOS/Traffic Type */
+       uint32_t pf:PF_BITWIDTH;                /* PCI-E PF ID */
+       uint32_t vf:VF_BITWIDTH;                /* PCI-E VF ID */
+       uint32_t ivlan:IVLAN_BITWIDTH;          /* inner VLAN */
+       uint32_t ovlan:OVLAN_BITWIDTH;          /* outer VLAN */
+
+       /* Uncompressed header matching field rules.  These are always
+        * available for field rules.
+        */
+       uint8_t lip[16];        /* local IP address (IPv4 in [3:0]) */
+       uint8_t fip[16];        /* foreign IP address (IPv4 in [3:0]) */
+       uint16_t lport;         /* local port */
+       uint16_t fport;         /* foreign port */
+};
+
+/* A filter ioctl command.
+ */
+struct ch_filter_specification {
+       /* Administrative fields for filter.
+        */
+       uint32_t hitcnts:1;     /* count filter hits in TCB */
+       uint32_t prio:1;        /* filter has priority over active/server */
+
+       /* Fundamental filter typing.  This is the one element of filter
+        * matching that doesn't exist as a (value, mask) tuple.
+        */
+       uint32_t type:1;        /* 0 => IPv4, 1 => IPv6 */
+
+       /* Packet dispatch information.  Ingress packets which match the
+        * filter rules will be dropped, passed to the host or switched back
+        * out as egress packets.
+        */
+       uint32_t action:2;      /* drop, pass, switch */
+
+       uint32_t rpttid:1;      /* report TID in RSS hash field */
+
+       uint32_t dirsteer:1;    /* 0 => RSS, 1 => steer to iq */
+       uint32_t iq:10;         /* ingress queue */
+
+       uint32_t maskhash:1;    /* dirsteer=0: store RSS hash in TCB */
+       uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */
+                               /*             1 => TCB contains IQ ID */
+
+       /* Switch proxy/rewrite fields.  An ingress packet which matches a
+        * filter with "switch" set will be looped back out as an egress
+        * packet -- potentially with some Ethernet header rewriting.
+        */
+       uint32_t eport:2;       /* egress port to switch packet out */
+       uint32_t newdmac:1;     /* rewrite destination MAC address */
+       uint32_t newsmac:1;     /* rewrite source MAC address */
+       uint32_t newvlan:2;     /* rewrite VLAN Tag */
+       uint8_t dmac[ETH_ALEN]; /* new destination MAC address */
+       uint8_t smac[ETH_ALEN]; /* new source MAC address */
+       uint16_t vlan;          /* VLAN Tag to insert */
+
+       /* Filter rule value/mask pairs.
+        */
+       struct ch_filter_tuple val;
+       struct ch_filter_tuple mask;
+};
+
+enum {
+       FILTER_PASS = 0,        /* default */
+       FILTER_DROP,
+       FILTER_SWITCH
+};
+
+enum {
+       VLAN_NOCHANGE = 0,      /* default */
+       VLAN_REMOVE,
+       VLAN_INSERT,
+       VLAN_REWRITE
+};
+
 static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
 {
        return readl(adap->regs + reg_addr);
@@ -701,6 +829,12 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd,
 void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
                       unsigned int data_reg, const u32 *vals,
                       unsigned int nregs, unsigned int start_idx);
+void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
+                     unsigned int data_reg, u32 *vals, unsigned int nregs,
+                     unsigned int start_idx);
+
+struct fw_filter_wr;
+
 void t4_intr_enable(struct adapter *adapter);
 void t4_intr_disable(struct adapter *adapter);
 int t4_slow_intr_handler(struct adapter *adapter);
@@ -737,6 +871,8 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
 void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
                  const unsigned short *alpha, const unsigned short *beta);
 
+void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid);
+
 void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
                         const u8 *addr);
 int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
index a27b4ae20f43486f57fef3cf3f9d08e93bcf0c6e..c306df7d45684ce1fcd2f25012e8100da98abdd2 100644 (file)
@@ -175,6 +175,30 @@ enum {
        MIN_FL_ENTRIES       = 16
 };
 
+/* Host shadow copy of ingress filter entry.  This is in host native format
+ * and doesn't match the ordering or bit order, etc. of the hardware of the
+ * firmware command.  The use of bit-field structure elements is purely to
+ * remind ourselves of the field size limitations and save memory in the case
+ * where the filter table is large.
+ */
+struct filter_entry {
+       /* Administrative fields for filter.
+        */
+       u32 valid:1;            /* filter allocated and valid */
+       u32 locked:1;           /* filter is administratively locked */
+
+       u32 pending:1;          /* filter action is pending firmware reply */
+       u32 smtidx:8;           /* Source MAC Table index for smac */
+       struct l2t_entry *l2t;  /* Layer Two Table entry for dmac */
+
+       /* The filter itself.  Most of this is a straight copy of information
+        * provided by the extended ioctl().  Some fields are translated to
+        * internal forms -- for instance the Ingress Queue ID passed in from
+        * the ioctl() is translated into the Absolute Ingress Queue ID.
+        */
+       struct ch_filter_specification fs;
+};
+
 #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
                         NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
                         NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -325,6 +349,9 @@ enum {
 
 static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT;
 
+module_param(tp_vlan_pri_map, uint, 0644);
+MODULE_PARM_DESC(tp_vlan_pri_map, "global compressed filter configuration");
+
 static struct dentry *cxgb4_debugfs_root;
 
 static LIST_HEAD(adapter_list);
@@ -506,8 +533,67 @@ static int link_start(struct net_device *dev)
        return ret;
 }
 
-/*
- * Response queue handler for the FW event queue.
+/* Clear a filter and release any of its resources that we own.  This also
+ * clears the filter's "pending" status.
+ */
+static void clear_filter(struct adapter *adap, struct filter_entry *f)
+{
+       /* If the new or old filter have loopback rewriteing rules then we'll
+        * need to free any existing Layer Two Table (L2T) entries of the old
+        * filter rule.  The firmware will handle freeing up any Source MAC
+        * Table (SMT) entries used for rewriting Source MAC Addresses in
+        * loopback rules.
+        */
+       if (f->l2t)
+               cxgb4_l2t_release(f->l2t);
+
+       /* The zeroing of the filter rule below clears the filter valid,
+        * pending, locked flags, l2t pointer, etc. so it's all we need for
+        * this operation.
+        */
+       memset(f, 0, sizeof(*f));
+}
+
+/* Handle a filter write/deletion reply.
+ */
+static void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
+{
+       unsigned int idx = GET_TID(rpl);
+       unsigned int nidx = idx - adap->tids.ftid_base;
+       unsigned int ret;
+       struct filter_entry *f;
+
+       if (idx >= adap->tids.ftid_base && nidx <
+          (adap->tids.nftids + adap->tids.nsftids)) {
+               idx = nidx;
+               ret = GET_TCB_COOKIE(rpl->cookie);
+               f = &adap->tids.ftid_tab[idx];
+
+               if (ret == FW_FILTER_WR_FLT_DELETED) {
+                       /* Clear the filter when we get confirmation from the
+                        * hardware that the filter has been deleted.
+                        */
+                       clear_filter(adap, f);
+               } else if (ret == FW_FILTER_WR_SMT_TBL_FULL) {
+                       dev_err(adap->pdev_dev, "filter %u setup failed due to full SMT\n",
+                               idx);
+                       clear_filter(adap, f);
+               } else if (ret == FW_FILTER_WR_FLT_ADDED) {
+                       f->smtidx = (be64_to_cpu(rpl->oldval) >> 24) & 0xff;
+                       f->pending = 0;  /* asynchronous setup completed */
+                       f->valid = 1;
+               } else {
+                       /* Something went wrong.  Issue a warning about the
+                        * problem and clear everything out.
+                        */
+                       dev_err(adap->pdev_dev, "filter %u setup failed with error %u\n",
+                               idx, ret);
+                       clear_filter(adap, f);
+               }
+       }
+}
+
+/* Response queue handler for the FW event queue.
  */
 static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
                          const struct pkt_gl *gl)
@@ -542,6 +628,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
                const struct cpl_l2t_write_rpl *p = (void *)rsp;
 
                do_l2t_write_rpl(q->adap, p);
+       } else if (opcode == CPL_SET_TCB_RPL) {
+               const struct cpl_set_tcb_rpl *p = (void *)rsp;
+
+               filter_rpl(q->adap, p);
        } else
                dev_err(q->adap->pdev_dev,
                        "unexpected CPL %#x on FW event queue\n", opcode);
@@ -983,6 +1073,148 @@ static void t4_free_mem(void *addr)
                kfree(addr);
 }
 
+/* Send a Work Request to write the filter at a specified index.  We construct
+ * a Firmware Filter Work Request to have the work done and put the indicated
+ * filter into "pending" mode which will prevent any further actions against
+ * it till we get a reply from the firmware on the completion status of the
+ * request.
+ */
+static int set_filter_wr(struct adapter *adapter, int fidx)
+{
+       struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
+       struct sk_buff *skb;
+       struct fw_filter_wr *fwr;
+       unsigned int ftid;
+
+       /* If the new filter requires loopback Destination MAC and/or VLAN
+        * rewriting then we need to allocate a Layer 2 Table (L2T) entry for
+        * the filter.
+        */
+       if (f->fs.newdmac || f->fs.newvlan) {
+               /* allocate L2T entry for new filter */
+               f->l2t = t4_l2t_alloc_switching(adapter->l2t);
+               if (f->l2t == NULL)
+                       return -EAGAIN;
+               if (t4_l2t_set_switching(adapter, f->l2t, f->fs.vlan,
+                                       f->fs.eport, f->fs.dmac)) {
+                       cxgb4_l2t_release(f->l2t);
+                       f->l2t = NULL;
+                       return -ENOMEM;
+               }
+       }
+
+       ftid = adapter->tids.ftid_base + fidx;
+
+       skb = alloc_skb(sizeof(*fwr), GFP_KERNEL | __GFP_NOFAIL);
+       fwr = (struct fw_filter_wr *)__skb_put(skb, sizeof(*fwr));
+       memset(fwr, 0, sizeof(*fwr));
+
+       /* It would be nice to put most of the following in t4_hw.c but most
+        * of the work is translating the cxgbtool ch_filter_specification
+        * into the Work Request and the definition of that structure is
+        * currently in cxgbtool.h which isn't appropriate to pull into the
+        * common code.  We may eventually try to come up with a more neutral
+        * filter specification structure but for now it's easiest to simply
+        * put this fairly direct code in line ...
+        */
+       fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
+       fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16));
+       fwr->tid_to_iq =
+               htonl(V_FW_FILTER_WR_TID(ftid) |
+                     V_FW_FILTER_WR_RQTYPE(f->fs.type) |
+                     V_FW_FILTER_WR_NOREPLY(0) |
+                     V_FW_FILTER_WR_IQ(f->fs.iq));
+       fwr->del_filter_to_l2tix =
+               htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) |
+                     V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
+                     V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
+                     V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) |
+                     V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) |
+                     V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
+                     V_FW_FILTER_WR_DMAC(f->fs.newdmac) |
+                     V_FW_FILTER_WR_SMAC(f->fs.newsmac) |
+                     V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT ||
+                                            f->fs.newvlan == VLAN_REWRITE) |
+                     V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE ||
+                                           f->fs.newvlan == VLAN_REWRITE) |
+                     V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
+                     V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
+                     V_FW_FILTER_WR_PRIO(f->fs.prio) |
+                     V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
+       fwr->ethtype = htons(f->fs.val.ethtype);
+       fwr->ethtypem = htons(f->fs.mask.ethtype);
+       fwr->frag_to_ovlan_vldm =
+               (V_FW_FILTER_WR_FRAG(f->fs.val.frag) |
+                V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) |
+                V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) |
+                V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) |
+                V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) |
+                V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));
+       fwr->smac_sel = 0;
+       fwr->rx_chan_rx_rpl_iq =
+               htons(V_FW_FILTER_WR_RX_CHAN(0) |
+                     V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id));
+       fwr->maci_to_matchtypem =
+               htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |
+                     V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |
+                     V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) |
+                     V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) |
+                     V_FW_FILTER_WR_PORT(f->fs.val.iport) |
+                     V_FW_FILTER_WR_PORTM(f->fs.mask.iport) |
+                     V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) |
+                     V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype));
+       fwr->ptcl = f->fs.val.proto;
+       fwr->ptclm = f->fs.mask.proto;
+       fwr->ttyp = f->fs.val.tos;
+       fwr->ttypm = f->fs.mask.tos;
+       fwr->ivlan = htons(f->fs.val.ivlan);
+       fwr->ivlanm = htons(f->fs.mask.ivlan);
+       fwr->ovlan = htons(f->fs.val.ovlan);
+       fwr->ovlanm = htons(f->fs.mask.ovlan);
+       memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
+       memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));
+       memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));
+       memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm));
+       fwr->lp = htons(f->fs.val.lport);
+       fwr->lpm = htons(f->fs.mask.lport);
+       fwr->fp = htons(f->fs.val.fport);
+       fwr->fpm = htons(f->fs.mask.fport);
+       if (f->fs.newsmac)
+               memcpy(fwr->sma, f->fs.smac, sizeof(fwr->sma));
+
+       /* Mark the filter as "pending" and ship off the Filter Work Request.
+        * When we get the Work Request Reply we'll clear the pending status.
+        */
+       f->pending = 1;
+       set_wr_txq(skb, CPL_PRIORITY_CONTROL, f->fs.val.iport & 0x3);
+       t4_ofld_send(adapter, skb);
+       return 0;
+}
+
+/* Delete the filter at a specified index.
+ */
+static int del_filter_wr(struct adapter *adapter, int fidx)
+{
+       struct filter_entry *f = &adapter->tids.ftid_tab[fidx];
+       struct sk_buff *skb;
+       struct fw_filter_wr *fwr;
+       unsigned int len, ftid;
+
+       len = sizeof(*fwr);
+       ftid = adapter->tids.ftid_base + fidx;
+
+       skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL);
+       fwr = (struct fw_filter_wr *)__skb_put(skb, len);
+       t4_mk_filtdelwr(ftid, fwr, adapter->sge.fw_evtq.abs_id);
+
+       /* Mark the filter as "pending" and ship off the Filter Work Request.
+        * When we get the Work Request Reply we'll clear the pending status.
+        */
+       f->pending = 1;
+       t4_mgmt_tx(adapter, skb);
+       return 0;
+}
+
 static inline int is_offload(const struct adapter *adap)
 {
        return adap->params.offload;
@@ -1762,9 +1994,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
 {
        const struct port_info *pi = netdev_priv(dev);
        struct adapter *adap = pi->adapter;
-
-       return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq,
-                       c->rx_coalesce_usecs, c->rx_max_coalesced_frames);
+       struct sge_rspq *q;
+       int i;
+       int r = 0;
+
+       for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) {
+               q = &adap->sge.ethrxq[i].rspq;
+               r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs,
+                       c->rx_max_coalesced_frames);
+               if (r) {
+                       dev_err(&dev->dev, "failed to set coalesce %d\n", r);
+                       break;
+               }
+       }
+       return r;
 }
 
 static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
@@ -2195,7 +2438,7 @@ int cxgb4_alloc_atid(struct tid_info *t, void *data)
        if (t->afree) {
                union aopen_entry *p = t->afree;
 
-               atid = p - t->atid_tab;
+               atid = (p - t->atid_tab) + t->atid_base;
                t->afree = p->next;
                p->data = data;
                t->atids_in_use++;
@@ -2210,7 +2453,7 @@ EXPORT_SYMBOL(cxgb4_alloc_atid);
  */
 void cxgb4_free_atid(struct tid_info *t, unsigned int atid)
 {
-       union aopen_entry *p = &t->atid_tab[atid];
+       union aopen_entry *p = &t->atid_tab[atid - t->atid_base];
 
        spin_lock_bh(&t->atid_lock);
        p->next = t->afree;
@@ -2249,8 +2492,34 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
 }
 EXPORT_SYMBOL(cxgb4_alloc_stid);
 
-/*
- * Release a server TID.
+/* Allocate a server filter TID and set it to the supplied value.
+ */
+int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
+{
+       int stid;
+
+       spin_lock_bh(&t->stid_lock);
+       if (family == PF_INET) {
+               stid = find_next_zero_bit(t->stid_bmap,
+                               t->nstids + t->nsftids, t->nstids);
+               if (stid < (t->nstids + t->nsftids))
+                       __set_bit(stid, t->stid_bmap);
+               else
+                       stid = -1;
+       } else {
+               stid = -1;
+       }
+       if (stid >= 0) {
+               t->stid_tab[stid].data = data;
+               stid += t->stid_base;
+               t->stids_in_use++;
+       }
+       spin_unlock_bh(&t->stid_lock);
+       return stid;
+}
+EXPORT_SYMBOL(cxgb4_alloc_sftid);
+
+/* Release a server TID.
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
@@ -2362,18 +2631,26 @@ EXPORT_SYMBOL(cxgb4_remove_tid);
 static int tid_init(struct tid_info *t)
 {
        size_t size;
+       unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
 
-       size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) +
+       stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
+       size = t->ntids * sizeof(*t->tid_tab) +
+              natids * sizeof(*t->atid_tab) +
               t->nstids * sizeof(*t->stid_tab) +
-              BITS_TO_LONGS(t->nstids) * sizeof(long);
+              t->nsftids * sizeof(*t->stid_tab) +
+              stid_bmap_size * sizeof(long) +
+              t->nftids * sizeof(*t->ftid_tab) +
+              t->nsftids * sizeof(*t->ftid_tab);
+
        t->tid_tab = t4_alloc_mem(size);
        if (!t->tid_tab)
                return -ENOMEM;
 
        t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
        t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
-       t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids];
+       t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids];
+       t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size];
        spin_lock_init(&t->stid_lock);
        spin_lock_init(&t->atid_lock);
 
@@ -2388,7 +2665,7 @@ static int tid_init(struct tid_info *t)
                        t->atid_tab[natids - 1].next = &t->atid_tab[natids];
                t->afree = t->atid_tab;
        }
-       bitmap_zero(t->stid_bmap, t->nstids);
+       bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
        return 0;
 }
 
@@ -2404,7 +2681,8 @@ static int tid_init(struct tid_info *t)
  *     Returns <0 on error and one of the %NET_XMIT_* values on success.
  */
 int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
-                       __be32 sip, __be16 sport, unsigned int queue)
+                       __be32 sip, __be16 sport, __be16 vlan,
+                       unsigned int queue)
 {
        unsigned int chan;
        struct sk_buff *skb;
@@ -2750,6 +3028,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
 {
        void *handle;
        struct cxgb4_lld_info lli;
+       unsigned short i;
 
        lli.pdev = adap->pdev;
        lli.l2t = adap->l2t;
@@ -2776,10 +3055,16 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
+       lli.filt_mode = adap->filter_mode;
+       /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
+       for (i = 0; i < NCHAN; i++)
+               lli.tx_modq[i] = i;
        lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
        lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
        lli.fw_vers = adap->params.fw_vers;
        lli.dbfifo_int_thresh = dbfifo_int_thresh;
+       lli.sge_pktshift = adap->sge.pktshift;
+       lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
 
        handle = ulds[uld].add(&lli);
        if (IS_ERR(handle)) {
@@ -2999,6 +3284,126 @@ static int cxgb_close(struct net_device *dev)
        return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false);
 }
 
+/* Return an error number if the indicated filter isn't writable ...
+ */
+static int writable_filter(struct filter_entry *f)
+{
+       if (f->locked)
+               return -EPERM;
+       if (f->pending)
+               return -EBUSY;
+
+       return 0;
+}
+
+/* Delete the filter at the specified index (if valid).  The checks for all
+ * the common problems with doing this like the filter being locked, currently
+ * pending in another operation, etc.
+ */
+static int delete_filter(struct adapter *adapter, unsigned int fidx)
+{
+       struct filter_entry *f;
+       int ret;
+
+       if (fidx >= adapter->tids.nftids + adapter->tids.nsftids)
+               return -EINVAL;
+
+       f = &adapter->tids.ftid_tab[fidx];
+       ret = writable_filter(f);
+       if (ret)
+               return ret;
+       if (f->valid)
+               return del_filter_wr(adapter, fidx);
+
+       return 0;
+}
+
+int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
+               __be32 sip, __be16 sport, __be16 vlan,
+               unsigned int queue, unsigned char port, unsigned char mask)
+{
+       int ret;
+       struct filter_entry *f;
+       struct adapter *adap;
+       int i;
+       u8 *val;
+
+       adap = netdev2adap(dev);
+
+       /* Adjust stid to correct filter index */
+       stid -= adap->tids.nstids;
+       stid += adap->tids.nftids;
+
+       /* Check to make sure the filter requested is writable ...
+        */
+       f = &adap->tids.ftid_tab[stid];
+       ret = writable_filter(f);
+       if (ret)
+               return ret;
+
+       /* Clear out any old resources being used by the filter before
+        * we start constructing the new filter.
+        */
+       if (f->valid)
+               clear_filter(adap, f);
+
+       /* Clear out filter specifications */
+       memset(&f->fs, 0, sizeof(struct ch_filter_specification));
+       f->fs.val.lport = cpu_to_be16(sport);
+       f->fs.mask.lport  = ~0;
+       val = (u8 *)&sip;
+       if ((val[0] | val[1] | val[2] | val[3]) != 0) {
+               for (i = 0; i < 4; i++) {
+                       f->fs.val.lip[i] = val[i];
+                       f->fs.mask.lip[i] = ~0;
+               }
+               if (adap->filter_mode & F_PORT) {
+                       f->fs.val.iport = port;
+                       f->fs.mask.iport = mask;
+               }
+       }
+
+       f->fs.dirsteer = 1;
+       f->fs.iq = queue;
+       /* Mark filter as locked */
+       f->locked = 1;
+       f->fs.rpttid = 1;
+
+       ret = set_filter_wr(adap, stid);
+       if (ret) {
+               clear_filter(adap, f);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(cxgb4_create_server_filter);
+
+int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
+               unsigned int queue, bool ipv6)
+{
+       int ret;
+       struct filter_entry *f;
+       struct adapter *adap;
+
+       adap = netdev2adap(dev);
+
+       /* Adjust stid to correct filter index */
+       stid -= adap->tids.nstids;
+       stid += adap->tids.nftids;
+
+       f = &adap->tids.ftid_tab[stid];
+       /* Unlock the filter */
+       f->locked = 0;
+
+       ret = delete_filter(adap, stid);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL(cxgb4_remove_server_filter);
+
 static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
                                                struct rtnl_link_stats64 *ns)
 {
@@ -3245,6 +3650,34 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
        v = t4_read_reg(adap, TP_PIO_DATA);
        t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR);
 
+       /* first 4 Tx modulation queues point to consecutive Tx channels */
+       adap->params.tp.tx_modq_map = 0xE4;
+       t4_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP,
+                    V_TX_MOD_QUEUE_REQ_MAP(adap->params.tp.tx_modq_map));
+
+       /* associate each Tx modulation queue with consecutive Tx channels */
+       v = 0x84218421;
+       t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                         &v, 1, A_TP_TX_SCHED_HDR);
+       t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                         &v, 1, A_TP_TX_SCHED_FIFO);
+       t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                         &v, 1, A_TP_TX_SCHED_PCMD);
+
+#define T4_TX_MODQ_10G_WEIGHT_DEFAULT 16 /* in KB units */
+       if (is_offload(adap)) {
+               t4_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0,
+                            V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT));
+               t4_write_reg(adap, A_TP_TX_MOD_CHANNEL_WEIGHT,
+                            V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
+                            V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT));
+       }
+
        /* get basic stuff going */
        return t4_early_init(adap, adap->fn);
 }
@@ -4035,6 +4468,10 @@ static int adap_init0(struct adapter *adap)
        for (j = 0; j < NCHAN; j++)
                adap->params.tp.tx_modq[j] = j;
 
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->filter_mode, 1,
+                        TP_VLAN_PRI_MAP);
+
        adap->flags |= FW_OK;
        return 0;
 
@@ -4661,6 +5098,17 @@ static void remove_one(struct pci_dev *pdev)
                if (adapter->debugfs_root)
                        debugfs_remove_recursive(adapter->debugfs_root);
 
+               /* If we allocated filters, free up state associated with any
+                * valid filters ...
+                */
+               if (adapter->tids.ftid_tab) {
+                       struct filter_entry *f = &adapter->tids.ftid_tab[0];
+                       for (i = 0; i < (adapter->tids.nftids +
+                                       adapter->tids.nsftids); i++, f++)
+                               if (f->valid)
+                                       clear_filter(adapter, f);
+               }
+
                if (adapter->flags & FULL_INIT_DONE)
                        cxgb_down(adapter);
 
index 39bec73ff87c5879a9b1f6ca9ad1425d4d78c9b2..e2bbc7f3e2de7cb331e80d7134a9ef64c02c04aa 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
+#include <linux/inetdevice.h>
 #include <linux/atomic.h>
 
 /* CPL message priority levels */
@@ -97,7 +98,9 @@ struct tid_info {
 
        union aopen_entry *atid_tab;
        unsigned int natids;
+       unsigned int atid_base;
 
+       struct filter_entry *ftid_tab;
        unsigned int nftids;
        unsigned int ftid_base;
        unsigned int aftid_base;
@@ -129,7 +132,7 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
        stid -= t->stid_base;
-       return stid < t->nstids ? t->stid_tab[stid].data : NULL;
+       return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
 static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
@@ -141,6 +144,7 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
 
 int cxgb4_alloc_atid(struct tid_info *t, void *data);
 int cxgb4_alloc_stid(struct tid_info *t, int family, void *data);
+int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data);
 void cxgb4_free_atid(struct tid_info *t, unsigned int atid);
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family);
 void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
@@ -148,8 +152,14 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
 struct in6_addr;
 
 int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
-                       __be32 sip, __be16 sport, unsigned int queue);
-
+                       __be32 sip, __be16 sport, __be16 vlan,
+                       unsigned int queue);
+int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
+                              __be32 sip, __be16 sport, __be16 vlan,
+                              unsigned int queue,
+                              unsigned char port, unsigned char mask);
+int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
+                              unsigned int queue, bool ipv6);
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
        skb_set_queue_mapping(skb, (queue << 1) | prio);
@@ -221,9 +231,16 @@ struct cxgb4_lld_info {
        unsigned int iscsi_iolen;            /* iSCSI max I/O length */
        unsigned short udb_density;          /* # of user DB/page */
        unsigned short ucq_density;          /* # of user CQs/page */
+       unsigned short filt_mode;            /* filter optional components */
+       unsigned short tx_modq[NCHAN];       /* maps each tx channel to a */
+                                            /* scheduler queue */
        void __iomem *gts_reg;               /* address of GTS register */
        void __iomem *db_reg;                /* address of kernel doorbell */
        int dbfifo_int_thresh;               /* doorbell fifo int threshold */
+       unsigned int sge_pktshift;           /* Padding between CPL and */
+                                            /* packet data */
+       bool enable_fw_ofld_conn;            /* Enable connection through fw */
+                                            /* WR */
 };
 
 struct cxgb4_uld_info {
index 6ac77a62f361ab6e02e1b90645b17bc37dbb580f..29878098101eb07771626399a1c5050a9544d055 100644 (file)
@@ -484,6 +484,38 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
                handle_failed_resolution(adap, arpq);
 }
 
+/* Allocate an L2T entry for use by a switching rule.  Such need to be
+ * explicitly freed and while busy they are not on any hash chain, so normal
+ * address resolution updates do not see them.
+ */
+struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d)
+{
+       struct l2t_entry *e;
+
+       write_lock_bh(&d->lock);
+       e = alloc_l2e(d);
+       if (e) {
+               spin_lock(&e->lock);          /* avoid race with t4_l2t_free */
+               e->state = L2T_STATE_SWITCHING;
+               atomic_set(&e->refcnt, 1);
+               spin_unlock(&e->lock);
+       }
+       write_unlock_bh(&d->lock);
+       return e;
+}
+
+/* Sets/updates the contents of a switching L2T entry that has been allocated
+ * with an earlier call to @t4_l2t_alloc_switching.
+ */
+int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
+               u8 port, u8 *eth_addr)
+{
+       e->vlan = vlan;
+       e->lport = port;
+       memcpy(e->dmac, eth_addr, ETH_ALEN);
+       return write_l2e(adap, e, 0);
+}
+
 struct l2t_data *t4_init_l2t(void)
 {
        int i;
index 02b31d0c6410af48f292e244273101943dc3560a..108c0f1fce1c4e5776b687538d741cd6f771a909 100644 (file)
@@ -100,6 +100,9 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                unsigned int priority);
 
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
+struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
+int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
+                        u8 port, u8 *eth_addr);
 struct l2t_data *t4_init_l2t(void);
 void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
 
index 8d9c7547b07004778388171ef3b58bcd46b81d35..22f3af5166bf50ec7d2c6b7d2bd8778b6e15e963 100644 (file)
@@ -109,7 +109,7 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
  *     Reads registers that are accessed indirectly through an address/data
  *     register pair.
  */
-static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
+void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
                             unsigned int data_reg, u32 *vals,
                             unsigned int nregs, unsigned int start_idx)
 {
@@ -2268,6 +2268,26 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
        return 0;
 }
 
+/*     t4_mk_filtdelwr - create a delete filter WR
+ *     @ftid: the filter ID
+ *     @wr: the filter work request to populate
+ *     @qid: ingress queue to receive the delete notification
+ *
+ *     Creates a filter work request to delete the supplied filter.  If @qid is
+ *     negative the delete notification is suppressed.
+ */
+void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
+{
+       memset(wr, 0, sizeof(*wr));
+       wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
+       wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16));
+       wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) |
+                       V_FW_FILTER_WR_NOREPLY(qid < 0));
+       wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER);
+       if (qid >= 0)
+               wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid));
+}
+
 #define INIT_CMD(var, cmd, rd_wr) do { \
        (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \
                                  FW_CMD_REQUEST | FW_CMD_##rd_wr); \
index b760808fd6d9831e1c56edf09fd5038dbf7f9f23..261d17703adcf72c6b1449c02081552ef1ed3e56 100644 (file)
@@ -193,8 +193,24 @@ struct work_request_hdr {
        __be64 wr_lo;
 };
 
+/* wr_hi fields */
+#define S_WR_OP    24
+#define V_WR_OP(x) ((__u64)(x) << S_WR_OP)
+
 #define WR_HDR struct work_request_hdr wr
 
+/* option 0 fields */
+#define S_MSS_IDX    60
+#define M_MSS_IDX    0xF
+#define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX)
+#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX)
+
+/* option 2 fields */
+#define S_RSS_QUEUE    0
+#define M_RSS_QUEUE    0x3FF
+#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE)
+#define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE)
+
 struct cpl_pass_open_req {
        WR_HDR;
        union opcode_tid ot;
@@ -204,12 +220,14 @@ struct cpl_pass_open_req {
        __be32 peer_ip;
        __be64 opt0;
 #define TX_CHAN(x)    ((x) << 2)
+#define NO_CONG(x)    ((x) << 4)
 #define DELACK(x)     ((x) << 5)
 #define ULP_MODE(x)   ((x) << 8)
 #define RCV_BUFSIZ(x) ((x) << 12)
 #define DSCP(x)       ((x) << 22)
 #define SMAC_SEL(x)   ((u64)(x) << 28)
 #define L2T_IDX(x)    ((u64)(x) << 36)
+#define TCAM_BYPASS(x) ((u64)(x) << 48)
 #define NAGLE(x)      ((u64)(x) << 49)
 #define WND_SCALE(x)  ((u64)(x) << 50)
 #define KEEP_ALIVE(x) ((u64)(x) << 54)
@@ -247,8 +265,10 @@ struct cpl_pass_accept_rpl {
 #define RSS_QUEUE_VALID      (1 << 10)
 #define RX_COALESCE_VALID(x) ((x) << 11)
 #define RX_COALESCE(x)       ((x) << 12)
+#define PACE(x)              ((x) << 16)
 #define TX_QUEUE(x)          ((x) << 23)
 #define RX_CHANNEL(x)        ((x) << 26)
+#define CCTRL_ECN(x)         ((x) << 27)
 #define WND_SCALE_EN(x)      ((x) << 28)
 #define TSTAMPS_EN(x)        ((x) << 29)
 #define SACK_EN(x)           ((x) << 30)
@@ -292,6 +312,9 @@ struct cpl_pass_establish {
        union opcode_tid ot;
        __be32 rsvd;
        __be32 tos_stid;
+#define PASS_OPEN_TID(x) ((x) << 0)
+#define PASS_OPEN_TOS(x) ((x) << 24)
+#define GET_PASS_OPEN_TID(x)   (((x) >> 0) & 0xFFFFFF)
 #define GET_POPEN_TID(x) ((x) & 0xffffff)
 #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff)
        __be16 mac_idx;
@@ -332,6 +355,7 @@ struct cpl_set_tcb_field {
        __be16 word_cookie;
 #define TCB_WORD(x)   ((x) << 0)
 #define TCB_COOKIE(x) ((x) << 5)
+#define GET_TCB_COOKIE(x) (((x) >> 5) & 7)
        __be64 mask;
        __be64 val;
 };
@@ -536,6 +560,37 @@ struct cpl_rx_pkt {
        __be16 err_vec;
 };
 
+/* rx_pkt.l2info fields */
+#define S_RX_ETHHDR_LEN    0
+#define M_RX_ETHHDR_LEN    0x1F
+#define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN)
+#define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN)
+
+#define S_RX_MACIDX    8
+#define M_RX_MACIDX    0x1FF
+#define V_RX_MACIDX(x) ((x) << S_RX_MACIDX)
+#define G_RX_MACIDX(x) (((x) >> S_RX_MACIDX) & M_RX_MACIDX)
+
+#define S_RXF_SYN    21
+#define V_RXF_SYN(x) ((x) << S_RXF_SYN)
+#define F_RXF_SYN    V_RXF_SYN(1U)
+
+#define S_RX_CHAN    28
+#define M_RX_CHAN    0xF
+#define V_RX_CHAN(x) ((x) << S_RX_CHAN)
+#define G_RX_CHAN(x) (((x) >> S_RX_CHAN) & M_RX_CHAN)
+
+/* rx_pkt.hdr_len fields */
+#define S_RX_TCPHDR_LEN    0
+#define M_RX_TCPHDR_LEN    0x3F
+#define V_RX_TCPHDR_LEN(x) ((x) << S_RX_TCPHDR_LEN)
+#define G_RX_TCPHDR_LEN(x) (((x) >> S_RX_TCPHDR_LEN) & M_RX_TCPHDR_LEN)
+
+#define S_RX_IPHDR_LEN    6
+#define M_RX_IPHDR_LEN    0x3FF
+#define V_RX_IPHDR_LEN(x) ((x) << S_RX_IPHDR_LEN)
+#define G_RX_IPHDR_LEN(x) (((x) >> S_RX_IPHDR_LEN) & M_RX_IPHDR_LEN)
+
 struct cpl_trace_pkt {
        u8 opcode;
        u8 intf;
@@ -634,6 +689,17 @@ struct cpl_fw6_msg {
 /* cpl_fw6_msg.type values */
 enum {
        FW6_TYPE_CMD_RPL = 0,
+       FW6_TYPE_WR_RPL = 1,
+       FW6_TYPE_CQE = 2,
+       FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3,
+};
+
+struct cpl_fw6_msg_ofld_connection_wr_rpl {
+       __u64   cookie;
+       __be32  tid;    /* or atid in case of active failure */
+       __u8    t_state;
+       __u8    retval;
+       __u8    rsvd[2];
 };
 
 enum {
index 75393f5cff41877d18b3e04ed6294ae351107e94..83ec5f7844ac4e11b696a8e8a1ebfd8bd0dd41a0 100644 (file)
 #define  ADDRESS(x)     ((x) << ADDRESS_SHIFT)
 
 #define XGMAC_PORT_INT_CAUSE 0x10dc
+
+#define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28
+
+#define A_TP_TX_MOD_CHANNEL_WEIGHT 0x7e34
+
+#define S_TX_MOD_QUEUE_REQ_MAP    0
+#define M_TX_MOD_QUEUE_REQ_MAP    0xffffU
+#define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP)
+
+#define A_TP_TX_MOD_QUEUE_WEIGHT0 0x7e30
+
+#define S_TX_MODQ_WEIGHT3    24
+#define M_TX_MODQ_WEIGHT3    0xffU
+#define V_TX_MODQ_WEIGHT3(x) ((x) << S_TX_MODQ_WEIGHT3)
+
+#define S_TX_MODQ_WEIGHT2    16
+#define M_TX_MODQ_WEIGHT2    0xffU
+#define V_TX_MODQ_WEIGHT2(x) ((x) << S_TX_MODQ_WEIGHT2)
+
+#define S_TX_MODQ_WEIGHT1    8
+#define M_TX_MODQ_WEIGHT1    0xffU
+#define V_TX_MODQ_WEIGHT1(x) ((x) << S_TX_MODQ_WEIGHT1)
+
+#define S_TX_MODQ_WEIGHT0    0
+#define M_TX_MODQ_WEIGHT0    0xffU
+#define V_TX_MODQ_WEIGHT0(x) ((x) << S_TX_MODQ_WEIGHT0)
+
+#define A_TP_TX_SCHED_HDR 0x23
+
+#define A_TP_TX_SCHED_FIFO 0x24
+
+#define A_TP_TX_SCHED_PCMD 0x25
+
+#define S_PORT    1
+#define V_PORT(x) ((x) << S_PORT)
+#define F_PORT    V_PORT(1U)
+
 #endif /* __T4_REGS_H */
index 0abc864cdd3ae89a40fed822029a38e1e9b7f953..a0dcccd846c9a0185b748a0c88ee836bccd48a3e 100644 (file)
 #ifndef _T4FW_INTERFACE_H_
 #define _T4FW_INTERFACE_H_
 
+enum fw_retval {
+       FW_SUCCESS              = 0,    /* completed sucessfully */
+       FW_EPERM                = 1,    /* operation not permitted */
+       FW_ENOENT               = 2,    /* no such file or directory */
+       FW_EIO                  = 5,    /* input/output error; hw bad */
+       FW_ENOEXEC              = 8,    /* exec format error; inv microcode */
+       FW_EAGAIN               = 11,   /* try again */
+       FW_ENOMEM               = 12,   /* out of memory */
+       FW_EFAULT               = 14,   /* bad address; fw bad */
+       FW_EBUSY                = 16,   /* resource busy */
+       FW_EEXIST               = 17,   /* file exists */
+       FW_EINVAL               = 22,   /* invalid argument */
+       FW_ENOSPC               = 28,   /* no space left on device */
+       FW_ENOSYS               = 38,   /* functionality not implemented */
+       FW_EPROTO               = 71,   /* protocol error */
+       FW_EADDRINUSE           = 98,   /* address already in use */
+       FW_EADDRNOTAVAIL        = 99,   /* cannot assigned requested address */
+       FW_ENETDOWN             = 100,  /* network is down */
+       FW_ENETUNREACH          = 101,  /* network is unreachable */
+       FW_ENOBUFS              = 105,  /* no buffer space available */
+       FW_ETIMEDOUT            = 110,  /* timeout */
+       FW_EINPROGRESS          = 115,  /* fw internal */
+       FW_SCSI_ABORT_REQUESTED = 128,  /* */
+       FW_SCSI_ABORT_TIMEDOUT  = 129,  /* */
+       FW_SCSI_ABORTED         = 130,  /* */
+       FW_SCSI_CLOSE_REQUESTED = 131,  /* */
+       FW_ERR_LINK_DOWN        = 132,  /* */
+       FW_RDEV_NOT_READY       = 133,  /* */
+       FW_ERR_RDEV_LOST        = 134,  /* */
+       FW_ERR_RDEV_LOGO        = 135,  /* */
+       FW_FCOE_NO_XCHG         = 136,  /* */
+       FW_SCSI_RSP_ERR         = 137,  /* */
+       FW_ERR_RDEV_IMPL_LOGO   = 138,  /* */
+       FW_SCSI_UNDER_FLOW_ERR  = 139,  /* */
+       FW_SCSI_OVER_FLOW_ERR   = 140,  /* */
+       FW_SCSI_DDP_ERR         = 141,  /* DDP error*/
+       FW_SCSI_TASK_ERR        = 142,  /* No SCSI tasks available */
+};
+
 #define FW_T4VF_SGE_BASE_ADDR      0x0000
 #define FW_T4VF_MPS_BASE_ADDR      0x0100
 #define FW_T4VF_PL_BASE_ADDR       0x0200
@@ -46,6 +85,7 @@ enum fw_wr_opcodes {
        FW_ULPTX_WR                    = 0x04,
        FW_TP_WR                       = 0x05,
        FW_ETH_TX_PKT_WR               = 0x08,
+       FW_OFLD_CONNECTION_WR          = 0x2f,
        FW_FLOWC_WR                    = 0x0a,
        FW_OFLD_TX_DATA_WR             = 0x0b,
        FW_CMD_WR                      = 0x10,
@@ -81,6 +121,282 @@ struct fw_wr_hdr {
 #define FW_WR_LEN16(x) ((x) << 0)
 
 #define HW_TPL_FR_MT_PR_IV_P_FC         0X32B
+#define HW_TPL_FR_MT_PR_OV_P_FC         0X327
+
+/* filter wr reply code in cookie in CPL_SET_TCB_RPL */
+enum fw_filter_wr_cookie {
+       FW_FILTER_WR_SUCCESS,
+       FW_FILTER_WR_FLT_ADDED,
+       FW_FILTER_WR_FLT_DELETED,
+       FW_FILTER_WR_SMT_TBL_FULL,
+       FW_FILTER_WR_EINVAL,
+};
+
+struct fw_filter_wr {
+       __be32 op_pkd;
+       __be32 len16_pkd;
+       __be64 r3;
+       __be32 tid_to_iq;
+       __be32 del_filter_to_l2tix;
+       __be16 ethtype;
+       __be16 ethtypem;
+       __u8   frag_to_ovlan_vldm;
+       __u8   smac_sel;
+       __be16 rx_chan_rx_rpl_iq;
+       __be32 maci_to_matchtypem;
+       __u8   ptcl;
+       __u8   ptclm;
+       __u8   ttyp;
+       __u8   ttypm;
+       __be16 ivlan;
+       __be16 ivlanm;
+       __be16 ovlan;
+       __be16 ovlanm;
+       __u8   lip[16];
+       __u8   lipm[16];
+       __u8   fip[16];
+       __u8   fipm[16];
+       __be16 lp;
+       __be16 lpm;
+       __be16 fp;
+       __be16 fpm;
+       __be16 r7;
+       __u8   sma[6];
+};
+
+#define S_FW_FILTER_WR_TID      12
+#define M_FW_FILTER_WR_TID      0xfffff
+#define V_FW_FILTER_WR_TID(x)   ((x) << S_FW_FILTER_WR_TID)
+#define G_FW_FILTER_WR_TID(x)   \
+       (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID)
+
+#define S_FW_FILTER_WR_RQTYPE           11
+#define M_FW_FILTER_WR_RQTYPE           0x1
+#define V_FW_FILTER_WR_RQTYPE(x)        ((x) << S_FW_FILTER_WR_RQTYPE)
+#define G_FW_FILTER_WR_RQTYPE(x)        \
+       (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE)
+#define F_FW_FILTER_WR_RQTYPE   V_FW_FILTER_WR_RQTYPE(1U)
+
+#define S_FW_FILTER_WR_NOREPLY          10
+#define M_FW_FILTER_WR_NOREPLY          0x1
+#define V_FW_FILTER_WR_NOREPLY(x)       ((x) << S_FW_FILTER_WR_NOREPLY)
+#define G_FW_FILTER_WR_NOREPLY(x)       \
+       (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY)
+#define F_FW_FILTER_WR_NOREPLY  V_FW_FILTER_WR_NOREPLY(1U)
+
+#define S_FW_FILTER_WR_IQ       0
+#define M_FW_FILTER_WR_IQ       0x3ff
+#define V_FW_FILTER_WR_IQ(x)    ((x) << S_FW_FILTER_WR_IQ)
+#define G_FW_FILTER_WR_IQ(x)    \
+       (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ)
+
+#define S_FW_FILTER_WR_DEL_FILTER       31
+#define M_FW_FILTER_WR_DEL_FILTER       0x1
+#define V_FW_FILTER_WR_DEL_FILTER(x)    ((x) << S_FW_FILTER_WR_DEL_FILTER)
+#define G_FW_FILTER_WR_DEL_FILTER(x)    \
+       (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER)
+#define F_FW_FILTER_WR_DEL_FILTER       V_FW_FILTER_WR_DEL_FILTER(1U)
+
+#define S_FW_FILTER_WR_RPTTID           25
+#define M_FW_FILTER_WR_RPTTID           0x1
+#define V_FW_FILTER_WR_RPTTID(x)        ((x) << S_FW_FILTER_WR_RPTTID)
+#define G_FW_FILTER_WR_RPTTID(x)        \
+       (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID)
+#define F_FW_FILTER_WR_RPTTID   V_FW_FILTER_WR_RPTTID(1U)
+
+#define S_FW_FILTER_WR_DROP     24
+#define M_FW_FILTER_WR_DROP     0x1
+#define V_FW_FILTER_WR_DROP(x)  ((x) << S_FW_FILTER_WR_DROP)
+#define G_FW_FILTER_WR_DROP(x)  \
+       (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP)
+#define F_FW_FILTER_WR_DROP     V_FW_FILTER_WR_DROP(1U)
+
+#define S_FW_FILTER_WR_DIRSTEER         23
+#define M_FW_FILTER_WR_DIRSTEER         0x1
+#define V_FW_FILTER_WR_DIRSTEER(x)      ((x) << S_FW_FILTER_WR_DIRSTEER)
+#define G_FW_FILTER_WR_DIRSTEER(x)      \
+       (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER)
+#define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U)
+
+#define S_FW_FILTER_WR_MASKHASH         22
+#define M_FW_FILTER_WR_MASKHASH         0x1
+#define V_FW_FILTER_WR_MASKHASH(x)      ((x) << S_FW_FILTER_WR_MASKHASH)
+#define G_FW_FILTER_WR_MASKHASH(x)      \
+       (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH)
+#define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U)
+
+#define S_FW_FILTER_WR_DIRSTEERHASH     21
+#define M_FW_FILTER_WR_DIRSTEERHASH     0x1
+#define V_FW_FILTER_WR_DIRSTEERHASH(x)  ((x) << S_FW_FILTER_WR_DIRSTEERHASH)
+#define G_FW_FILTER_WR_DIRSTEERHASH(x)  \
+       (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH)
+#define F_FW_FILTER_WR_DIRSTEERHASH     V_FW_FILTER_WR_DIRSTEERHASH(1U)
+
+#define S_FW_FILTER_WR_LPBK     20
+#define M_FW_FILTER_WR_LPBK     0x1
+#define V_FW_FILTER_WR_LPBK(x)  ((x) << S_FW_FILTER_WR_LPBK)
+#define G_FW_FILTER_WR_LPBK(x)  \
+       (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK)
+#define F_FW_FILTER_WR_LPBK     V_FW_FILTER_WR_LPBK(1U)
+
+#define S_FW_FILTER_WR_DMAC     19
+#define M_FW_FILTER_WR_DMAC     0x1
+#define V_FW_FILTER_WR_DMAC(x)  ((x) << S_FW_FILTER_WR_DMAC)
+#define G_FW_FILTER_WR_DMAC(x)  \
+       (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC)
+#define F_FW_FILTER_WR_DMAC     V_FW_FILTER_WR_DMAC(1U)
+
+#define S_FW_FILTER_WR_SMAC     18
+#define M_FW_FILTER_WR_SMAC     0x1
+#define V_FW_FILTER_WR_SMAC(x)  ((x) << S_FW_FILTER_WR_SMAC)
+#define G_FW_FILTER_WR_SMAC(x)  \
+       (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC)
+#define F_FW_FILTER_WR_SMAC     V_FW_FILTER_WR_SMAC(1U)
+
+#define S_FW_FILTER_WR_INSVLAN          17
+#define M_FW_FILTER_WR_INSVLAN          0x1
+#define V_FW_FILTER_WR_INSVLAN(x)       ((x) << S_FW_FILTER_WR_INSVLAN)
+#define G_FW_FILTER_WR_INSVLAN(x)       \
+       (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN)
+#define F_FW_FILTER_WR_INSVLAN  V_FW_FILTER_WR_INSVLAN(1U)
+
+#define S_FW_FILTER_WR_RMVLAN           16
+#define M_FW_FILTER_WR_RMVLAN           0x1
+#define V_FW_FILTER_WR_RMVLAN(x)        ((x) << S_FW_FILTER_WR_RMVLAN)
+#define G_FW_FILTER_WR_RMVLAN(x)        \
+       (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN)
+#define F_FW_FILTER_WR_RMVLAN   V_FW_FILTER_WR_RMVLAN(1U)
+
+#define S_FW_FILTER_WR_HITCNTS          15
+#define M_FW_FILTER_WR_HITCNTS          0x1
+#define V_FW_FILTER_WR_HITCNTS(x)       ((x) << S_FW_FILTER_WR_HITCNTS)
+#define G_FW_FILTER_WR_HITCNTS(x)       \
+       (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS)
+#define F_FW_FILTER_WR_HITCNTS  V_FW_FILTER_WR_HITCNTS(1U)
+
+#define S_FW_FILTER_WR_TXCHAN           13
+#define M_FW_FILTER_WR_TXCHAN           0x3
+#define V_FW_FILTER_WR_TXCHAN(x)        ((x) << S_FW_FILTER_WR_TXCHAN)
+#define G_FW_FILTER_WR_TXCHAN(x)        \
+       (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN)
+
+#define S_FW_FILTER_WR_PRIO     12
+#define M_FW_FILTER_WR_PRIO     0x1
+#define V_FW_FILTER_WR_PRIO(x)  ((x) << S_FW_FILTER_WR_PRIO)
+#define G_FW_FILTER_WR_PRIO(x)  \
+       (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO)
+#define F_FW_FILTER_WR_PRIO     V_FW_FILTER_WR_PRIO(1U)
+
+#define S_FW_FILTER_WR_L2TIX    0
+#define M_FW_FILTER_WR_L2TIX    0xfff
+#define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX)
+#define G_FW_FILTER_WR_L2TIX(x) \
+       (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX)
+
+#define S_FW_FILTER_WR_FRAG     7
+#define M_FW_FILTER_WR_FRAG     0x1
+#define V_FW_FILTER_WR_FRAG(x)  ((x) << S_FW_FILTER_WR_FRAG)
+#define G_FW_FILTER_WR_FRAG(x)  \
+       (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG)
+#define F_FW_FILTER_WR_FRAG     V_FW_FILTER_WR_FRAG(1U)
+
+#define S_FW_FILTER_WR_FRAGM    6
+#define M_FW_FILTER_WR_FRAGM    0x1
+#define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM)
+#define G_FW_FILTER_WR_FRAGM(x) \
+       (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM)
+#define F_FW_FILTER_WR_FRAGM    V_FW_FILTER_WR_FRAGM(1U)
+
+#define S_FW_FILTER_WR_IVLAN_VLD        5
+#define M_FW_FILTER_WR_IVLAN_VLD        0x1
+#define V_FW_FILTER_WR_IVLAN_VLD(x)     ((x) << S_FW_FILTER_WR_IVLAN_VLD)
+#define G_FW_FILTER_WR_IVLAN_VLD(x)     \
+       (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD)
+#define F_FW_FILTER_WR_IVLAN_VLD        V_FW_FILTER_WR_IVLAN_VLD(1U)
+
+#define S_FW_FILTER_WR_OVLAN_VLD        4
+#define M_FW_FILTER_WR_OVLAN_VLD        0x1
+#define V_FW_FILTER_WR_OVLAN_VLD(x)     ((x) << S_FW_FILTER_WR_OVLAN_VLD)
+#define G_FW_FILTER_WR_OVLAN_VLD(x)     \
+       (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD)
+#define F_FW_FILTER_WR_OVLAN_VLD        V_FW_FILTER_WR_OVLAN_VLD(1U)
+
+#define S_FW_FILTER_WR_IVLAN_VLDM       3
+#define M_FW_FILTER_WR_IVLAN_VLDM       0x1
+#define V_FW_FILTER_WR_IVLAN_VLDM(x)    ((x) << S_FW_FILTER_WR_IVLAN_VLDM)
+#define G_FW_FILTER_WR_IVLAN_VLDM(x)    \
+       (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM)
+#define F_FW_FILTER_WR_IVLAN_VLDM       V_FW_FILTER_WR_IVLAN_VLDM(1U)
+
+#define S_FW_FILTER_WR_OVLAN_VLDM       2
+#define M_FW_FILTER_WR_OVLAN_VLDM       0x1
+#define V_FW_FILTER_WR_OVLAN_VLDM(x)    ((x) << S_FW_FILTER_WR_OVLAN_VLDM)
+#define G_FW_FILTER_WR_OVLAN_VLDM(x)    \
+       (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM)
+#define F_FW_FILTER_WR_OVLAN_VLDM       V_FW_FILTER_WR_OVLAN_VLDM(1U)
+
+#define S_FW_FILTER_WR_RX_CHAN          15
+#define M_FW_FILTER_WR_RX_CHAN          0x1
+#define V_FW_FILTER_WR_RX_CHAN(x)       ((x) << S_FW_FILTER_WR_RX_CHAN)
+#define G_FW_FILTER_WR_RX_CHAN(x)       \
+       (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN)
+#define F_FW_FILTER_WR_RX_CHAN  V_FW_FILTER_WR_RX_CHAN(1U)
+
+#define S_FW_FILTER_WR_RX_RPL_IQ        0
+#define M_FW_FILTER_WR_RX_RPL_IQ        0x3ff
+#define V_FW_FILTER_WR_RX_RPL_IQ(x)     ((x) << S_FW_FILTER_WR_RX_RPL_IQ)
+#define G_FW_FILTER_WR_RX_RPL_IQ(x)     \
+       (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ)
+
+#define S_FW_FILTER_WR_MACI     23
+#define M_FW_FILTER_WR_MACI     0x1ff
+#define V_FW_FILTER_WR_MACI(x)  ((x) << S_FW_FILTER_WR_MACI)
+#define G_FW_FILTER_WR_MACI(x)  \
+       (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI)
+
+#define S_FW_FILTER_WR_MACIM    14
+#define M_FW_FILTER_WR_MACIM    0x1ff
+#define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM)
+#define G_FW_FILTER_WR_MACIM(x) \
+       (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM)
+
+#define S_FW_FILTER_WR_FCOE     13
+#define M_FW_FILTER_WR_FCOE     0x1
+#define V_FW_FILTER_WR_FCOE(x)  ((x) << S_FW_FILTER_WR_FCOE)
+#define G_FW_FILTER_WR_FCOE(x)  \
+       (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE)
+#define F_FW_FILTER_WR_FCOE     V_FW_FILTER_WR_FCOE(1U)
+
+#define S_FW_FILTER_WR_FCOEM    12
+#define M_FW_FILTER_WR_FCOEM    0x1
+#define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM)
+#define G_FW_FILTER_WR_FCOEM(x) \
+       (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM)
+#define F_FW_FILTER_WR_FCOEM    V_FW_FILTER_WR_FCOEM(1U)
+
+#define S_FW_FILTER_WR_PORT     9
+#define M_FW_FILTER_WR_PORT     0x7
+#define V_FW_FILTER_WR_PORT(x)  ((x) << S_FW_FILTER_WR_PORT)
+#define G_FW_FILTER_WR_PORT(x)  \
+       (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT)
+
+#define S_FW_FILTER_WR_PORTM    6
+#define M_FW_FILTER_WR_PORTM    0x7
+#define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM)
+#define G_FW_FILTER_WR_PORTM(x) \
+       (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM)
+
+#define S_FW_FILTER_WR_MATCHTYPE        3
+#define M_FW_FILTER_WR_MATCHTYPE        0x7
+#define V_FW_FILTER_WR_MATCHTYPE(x)     ((x) << S_FW_FILTER_WR_MATCHTYPE)
+#define G_FW_FILTER_WR_MATCHTYPE(x)     \
+       (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE)
+
+#define S_FW_FILTER_WR_MATCHTYPEM       0
+#define M_FW_FILTER_WR_MATCHTYPEM       0x7
+#define V_FW_FILTER_WR_MATCHTYPEM(x)    ((x) << S_FW_FILTER_WR_MATCHTYPEM)
+#define G_FW_FILTER_WR_MATCHTYPEM(x)    \
+       (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM)
 
 struct fw_ulptx_wr {
        __be32 op_to_compl;
@@ -100,6 +416,108 @@ struct fw_eth_tx_pkt_wr {
        __be64 r3;
 };
 
+struct fw_ofld_connection_wr {
+       __be32 op_compl;
+       __be32 len16_pkd;
+       __u64  cookie;
+       __be64 r2;
+       __be64 r3;
+       struct fw_ofld_connection_le {
+               __be32 version_cpl;
+               __be32 filter;
+               __be32 r1;
+               __be16 lport;
+               __be16 pport;
+               union fw_ofld_connection_leip {
+                       struct fw_ofld_connection_le_ipv4 {
+                               __be32 pip;
+                               __be32 lip;
+                               __be64 r0;
+                               __be64 r1;
+                               __be64 r2;
+                       } ipv4;
+                       struct fw_ofld_connection_le_ipv6 {
+                               __be64 pip_hi;
+                               __be64 pip_lo;
+                               __be64 lip_hi;
+                               __be64 lip_lo;
+                       } ipv6;
+               } u;
+       } le;
+       struct fw_ofld_connection_tcb {
+               __be32 t_state_to_astid;
+               __be16 cplrxdataack_cplpassacceptrpl;
+               __be16 rcv_adv;
+               __be32 rcv_nxt;
+               __be32 tx_max;
+               __be64 opt0;
+               __be32 opt2;
+               __be32 r1;
+               __be64 r2;
+               __be64 r3;
+       } tcb;
+};
+
+#define S_FW_OFLD_CONNECTION_WR_VERSION                31
+#define M_FW_OFLD_CONNECTION_WR_VERSION                0x1
+#define V_FW_OFLD_CONNECTION_WR_VERSION(x)     \
+       ((x) << S_FW_OFLD_CONNECTION_WR_VERSION)
+#define G_FW_OFLD_CONNECTION_WR_VERSION(x)     \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_VERSION) & \
+       M_FW_OFLD_CONNECTION_WR_VERSION)
+#define F_FW_OFLD_CONNECTION_WR_VERSION        \
+       V_FW_OFLD_CONNECTION_WR_VERSION(1U)
+
+#define S_FW_OFLD_CONNECTION_WR_CPL    30
+#define M_FW_OFLD_CONNECTION_WR_CPL    0x1
+#define V_FW_OFLD_CONNECTION_WR_CPL(x) ((x) << S_FW_OFLD_CONNECTION_WR_CPL)
+#define G_FW_OFLD_CONNECTION_WR_CPL(x) \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_CPL) & M_FW_OFLD_CONNECTION_WR_CPL)
+#define F_FW_OFLD_CONNECTION_WR_CPL    V_FW_OFLD_CONNECTION_WR_CPL(1U)
+
+#define S_FW_OFLD_CONNECTION_WR_T_STATE                28
+#define M_FW_OFLD_CONNECTION_WR_T_STATE                0xf
+#define V_FW_OFLD_CONNECTION_WR_T_STATE(x)     \
+       ((x) << S_FW_OFLD_CONNECTION_WR_T_STATE)
+#define G_FW_OFLD_CONNECTION_WR_T_STATE(x)     \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_T_STATE) & \
+       M_FW_OFLD_CONNECTION_WR_T_STATE)
+
+#define S_FW_OFLD_CONNECTION_WR_RCV_SCALE      24
+#define M_FW_OFLD_CONNECTION_WR_RCV_SCALE      0xf
+#define V_FW_OFLD_CONNECTION_WR_RCV_SCALE(x)   \
+       ((x) << S_FW_OFLD_CONNECTION_WR_RCV_SCALE)
+#define G_FW_OFLD_CONNECTION_WR_RCV_SCALE(x)   \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_RCV_SCALE) & \
+       M_FW_OFLD_CONNECTION_WR_RCV_SCALE)
+
+#define S_FW_OFLD_CONNECTION_WR_ASTID          0
+#define M_FW_OFLD_CONNECTION_WR_ASTID          0xffffff
+#define V_FW_OFLD_CONNECTION_WR_ASTID(x)       \
+       ((x) << S_FW_OFLD_CONNECTION_WR_ASTID)
+#define G_FW_OFLD_CONNECTION_WR_ASTID(x)       \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_ASTID) & M_FW_OFLD_CONNECTION_WR_ASTID)
+
+#define S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK   15
+#define M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK   0x1
+#define V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x)        \
+       ((x) << S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK)
+#define G_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x)        \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) & \
+       M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK)
+#define F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK   \
+       V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(1U)
+
+#define S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL       14
+#define M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL       0x1
+#define V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x)    \
+       ((x) << S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL)
+#define G_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x)    \
+       (((x) >> S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) & \
+       M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL)
+#define F_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL       \
+       V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(1U)
+
 enum fw_flowc_mnem {
        FW_FLOWC_MNEM_PFNVFN,           /* PFN [15:8] VFN [7:0] */
        FW_FLOWC_MNEM_CH,
index 3bc1912afba936a629b16c7193b2ccacedbe9f76..f1b3df167ff29a8c68fccce991e43f714d82daf3 100644 (file)
 
 #define DRV_VER                        "4.4.161.0u"
 #define DRV_NAME               "be2net"
-#define BE_NAME                        "ServerEngines BladeEngine2 10Gbps NIC"
-#define BE3_NAME               "ServerEngines BladeEngine3 10Gbps NIC"
-#define OC_NAME                        "Emulex OneConnect 10Gbps NIC"
+#define BE_NAME                        "Emulex BladeEngine2"
+#define BE3_NAME               "Emulex BladeEngine3"
+#define OC_NAME                        "Emulex OneConnect"
 #define OC_NAME_BE             OC_NAME "(be3)"
 #define OC_NAME_LANCER         OC_NAME "(Lancer)"
 #define OC_NAME_SH             OC_NAME "(Skyhawk)"
-#define DRV_DESC               "ServerEngines BladeEngine 10Gbps NIC Driver"
+#define DRV_DESC               "Emulex OneConnect 10Gbps NIC Driver"
 
 #define BE_VENDOR_ID           0x19a2
 #define EMULEX_VENDOR_ID       0x10df
@@ -190,6 +190,7 @@ struct be_eq_obj {
 
        u8 idx;                 /* array index */
        u16 tx_budget;
+       u16 spurious_intr;
        struct napi_struct napi;
        struct be_adapter *adapter;
 } ____cacheline_aligned_in_smp;
index 9dca22be81253bc1a66f5e9e136c4462acdeaed9..4d6f3c54427a903f34189fb7abe74795028fb46f 100644 (file)
@@ -25,7 +25,7 @@
 MODULE_VERSION(DRV_VER);
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
 MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
-MODULE_AUTHOR("ServerEngines Corporation");
+MODULE_AUTHOR("Emulex Corporation");
 MODULE_LICENSE("GPL");
 
 static unsigned int num_vfs;
@@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev)
        struct be_adapter *adapter = eqo->adapter;
        int num_evts = 0;
 
-       /* On Lancer, clear-intr bit of the EQ DB does not work.
-        * INTx is de-asserted only on notifying num evts.
+       /* IRQ is not expected when NAPI is scheduled as the EQ
+        * will not be armed.
+        * But, this can happen on Lancer INTx where it takes
+        * a while to de-assert INTx or in BE2 where occasionaly
+        * an interrupt may be raised even when EQ is unarmed.
+        * If NAPI is already scheduled, then counting & notifying
+        * events will orphan them.
         */
-       if (lancer_chip(adapter))
+       if (napi_schedule_prep(&eqo->napi)) {
                num_evts = events_get(eqo);
+               __napi_schedule(&eqo->napi);
+               if (num_evts)
+                       eqo->spurious_intr = 0;
+       }
+       be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
 
-       /* The EQ-notify may not de-assert INTx rightaway, causing
-        * the ISR to be invoked again. So, return HANDLED even when
-        * num_evts is zero.
+       /* Return IRQ_HANDLED only for the the first spurious intr
+        * after a valid intr to stop the kernel from branding
+        * this irq as a bad one!
         */
-       be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
-       napi_schedule(&eqo->napi);
-       return IRQ_HANDLED;
+       if (num_evts || eqo->spurious_intr++ == 0)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
 }
 
 static irqreturn_t be_msix(int irq, void *dev)
index 02a12b69555f6fb5d71fe2089992f5fad5e354cc..4dab6fc265a27450a26664e1417c804961358a4a 100644 (file)
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
 #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
 #define E1000_CTRL_LANPHYPC_VALUE    0x00020000 /* SW value of LANPHYPC */
+#define E1000_CTRL_MEHE     0x00080000  /* Memory Error Handling Enable */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
 
 #define E1000_PBS_16K E1000_PBA_16K
 
+/* Uncorrectable/correctable ECC Error counts and enable bits */
+#define E1000_PBECCSTS_CORR_ERR_CNT_MASK       0x000000FF
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK     0x0000FF00
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT    8
+#define E1000_PBECCSTS_ECC_ENABLE              0x00010000
+
 #define IFS_MAX       80
 #define IFS_MIN       40
 #define IFS_RATIO     4
 #define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */
 #define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
 #define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
+#define E1000_ICR_ECCER         0x00400000 /* Uncorrectable ECC Error */
 #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
 #define E1000_ICR_RXQ0          0x00100000 /* Rx Queue 0 Interrupt */
 #define E1000_ICR_RXQ1          0x00200000 /* Rx Queue 1 Interrupt */
 #define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
 #define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
 #define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
+#define E1000_IMS_ECCER     E1000_ICR_ECCER     /* Uncorrectable ECC Error */
 #define E1000_IMS_RXQ0      E1000_ICR_RXQ0      /* Rx Queue 0 Interrupt */
 #define E1000_IMS_RXQ1      E1000_ICR_RXQ1      /* Rx Queue 1 Interrupt */
 #define E1000_IMS_TXQ0      E1000_ICR_TXQ0      /* Tx Queue 0 Interrupt */
index 6782a2eea1bcbfb893681b8d26428d8b0410981b..7e95f221d60b15e58b17d177ee870ecdfd2b0352 100644 (file)
@@ -309,6 +309,8 @@ struct e1000_adapter {
 
        struct napi_struct napi;
 
+       unsigned int uncorr_errors;     /* uncorrectable ECC errors */
+       unsigned int corr_errors;       /* correctable ECC errors */
        unsigned int restart_queue;
        u32 txd_cmd;
 
index f95bc6ee1c227c89a2e158fde491dc03ef173b4b..fd4772a2691c510fb83e5e2c9b9211c55f116465 100644 (file)
@@ -108,6 +108,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        E1000_STAT("dropped_smbus", stats.mgpdc),
        E1000_STAT("rx_dma_failed", rx_dma_failed),
        E1000_STAT("tx_dma_failed", tx_dma_failed),
+       E1000_STAT("uncorr_ecc_errors", uncorr_errors),
+       E1000_STAT("corr_ecc_errors", corr_errors),
 };
 
 #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
index cf217777586c246561120c0877516f22d3ff6b89..b88676ff3d86d19f365f94e4a9cc973c7ea3f092 100644 (file)
@@ -77,6 +77,7 @@ enum e1e_registers {
 #define E1000_POEMB    E1000_PHY_CTRL  /* PHY OEM Bits */
        E1000_PBA      = 0x01000, /* Packet Buffer Allocation - RW */
        E1000_PBS      = 0x01008, /* Packet Buffer Size */
+       E1000_PBECCSTS = 0x0100C, /* Packet Buffer ECC Status - RW */
        E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
        E1000_EEWR     = 0x0102C, /* EEPROM Write Register - RW */
        E1000_FLOP     = 0x0103C, /* FLASH Opcode Register */
index 976336547607e31caef68c8eaf528ddac78682da..24d9f61956f095ccfd5937ebba5ed35e8c2dc5d0 100644 (file)
@@ -3624,6 +3624,17 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
        if (hw->mac.type == e1000_ich8lan)
                reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
        ew32(RFCTL, reg);
+
+       /* Enable ECC on Lynxpoint */
+       if (hw->mac.type == e1000_pch_lpt) {
+               reg = er32(PBECCSTS);
+               reg |= E1000_PBECCSTS_ECC_ENABLE;
+               ew32(PBECCSTS, reg);
+
+               reg = er32(CTRL);
+               reg |= E1000_CTRL_MEHE;
+               ew32(CTRL, reg);
+       }
 }
 
 /**
index fbf75fdca99422743f35d3d9a114fcdef235563f..643c883dd795a48384c95dcd0795f3bbe95f6291 100644 (file)
@@ -1678,6 +1678,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
+       /* Reset on uncorrectable ECC error */
+       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+               u32 pbeccsts = er32(PBECCSTS);
+
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+
+               /* Do the reset outside of interrupt context */
+               schedule_work(&adapter->reset_task);
+
+               /* return immediately since reset is imminent */
+               return IRQ_HANDLED;
+       }
+
        if (napi_schedule_prep(&adapter->napi)) {
                adapter->total_tx_bytes = 0;
                adapter->total_tx_packets = 0;
@@ -1741,6 +1758,23 @@ static irqreturn_t e1000_intr(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
+       /* Reset on uncorrectable ECC error */
+       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+               u32 pbeccsts = er32(PBECCSTS);
+
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+
+               /* Do the reset outside of interrupt context */
+               schedule_work(&adapter->reset_task);
+
+               /* return immediately since reset is imminent */
+               return IRQ_HANDLED;
+       }
+
        if (napi_schedule_prep(&adapter->napi)) {
                adapter->total_tx_bytes = 0;
                adapter->total_tx_packets = 0;
@@ -2104,6 +2138,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
        if (adapter->msix_entries) {
                ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
                ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
+       } else if (hw->mac.type == e1000_pch_lpt) {
+               ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
        } else {
                ew32(IMS, IMS_ENABLE_MASK);
        }
@@ -4251,6 +4287,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.mgptc += er32(MGTPTC);
        adapter->stats.mgprc += er32(MGTPRC);
        adapter->stats.mgpdc += er32(MGTPDC);
+
+       /* Correctable ECC Errors */
+       if (hw->mac.type == e1000_pch_lpt) {
+               u32 pbeccsts = er32(PBECCSTS);
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+       }
 }
 
 /**
index f3a632bf8d96f8bd76983e8990c80f1cefe984ac..687c83d1bdabb7589ac4492e9763b863ac5fcef0 100644 (file)
@@ -32,7 +32,7 @@
 
 obj-$(CONFIG_IXGBE) += ixgbe.o
 
-ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\
+ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
               ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
               ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o
 
@@ -40,4 +40,5 @@ ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
 
 ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
+ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o
 ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
index 50aa546b8c7a589100be6bd88eac590adf314d98..3504686d3af515ed7f5e04924be29cd9098f2061 100644 (file)
@@ -24,9 +24,6 @@
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
-
-#ifdef CONFIG_DEBUG_FS
-
 #include <linux/debugfs.h>
 #include <linux/module.h>
 
@@ -277,5 +274,3 @@ void ixgbe_dbg_exit(void)
 {
        debugfs_remove_recursive(ixgbe_dbg_root);
 }
-
-#endif /* CONFIG_DEBUG_FS */
index 20a5af6d87d0e8747027964ba01a03bd7e3ca24c..b3e3294cfe53320f4b70a9484e39bd317583f8fc 100644 (file)
@@ -1401,6 +1401,7 @@ static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring,
        /* set gso_size to avoid messing up TCP MSS */
        skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len),
                                                 IXGBE_CB(skb)->append_cnt);
+       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 }
 
 static void ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring,
index 1a751c9d09c47f319e45d76a9c2bbad8573016d3..bb9256a1b0a9b467412ce127911ed3cfb53a7053 100644 (file)
@@ -660,11 +660,11 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
-               tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
+               tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG;
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
-               tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
+               tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
                break;
        case HWTSTAMP_FILTER_PTP_V2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
index 6d6002bab060dadd2cdff65fc6525c1153979f2e..74f1c157a4803311a61d2cddd4b1b4e4ece9ac1d 100644 (file)
@@ -141,7 +141,7 @@ static int orion_mdio_reset(struct mii_bus *bus)
        return 0;
 }
 
-static int __devinit orion_mdio_probe(struct platform_device *pdev)
+static int orion_mdio_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct mii_bus *bus;
@@ -197,7 +197,7 @@ static int __devinit orion_mdio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit orion_mdio_remove(struct platform_device *pdev)
+static int orion_mdio_remove(struct platform_device *pdev)
 {
        struct mii_bus *bus = platform_get_drvdata(pdev);
        mdiobus_unregister(bus);
@@ -214,7 +214,7 @@ MODULE_DEVICE_TABLE(of, orion_mdio_match);
 
 static struct platform_driver orion_mdio_driver = {
        .probe = orion_mdio_probe,
-       .remove = __devexit_p(orion_mdio_remove),
+       .remove = orion_mdio_remove,
        .driver = {
                .name = "orion-mdio",
                .of_match_table = orion_mdio_match,
index 3f8086b9f5e5d9f1c1810a985b1777107195160c..b6025c305e1086e5a45beeac14cf10a93b41c0fe 100644 (file)
@@ -635,7 +635,7 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
 
 
 /* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
-static void __devinit mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
+static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
 {
        u32  val;
 
@@ -650,7 +650,7 @@ static void __devinit mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
 }
 
 /* Config SGMII port */
-static void __devinit mvneta_port_sgmii_config(struct mvneta_port *pp)
+static void mvneta_port_sgmii_config(struct mvneta_port *pp)
 {
        u32 val;
 
@@ -2564,7 +2564,7 @@ const struct ethtool_ops mvneta_eth_tool_ops = {
 };
 
 /* Initialize hw */
-static int __devinit mvneta_init(struct mvneta_port *pp, int phy_addr)
+static int mvneta_init(struct mvneta_port *pp, int phy_addr)
 {
        int queue;
 
@@ -2613,9 +2613,8 @@ static void mvneta_deinit(struct mvneta_port *pp)
 }
 
 /* platform glue : initialize decoding windows */
-static void __devinit
-mvneta_conf_mbus_windows(struct mvneta_port *pp,
-                        const struct mbus_dram_target_info *dram)
+static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
+                                    const struct mbus_dram_target_info *dram)
 {
        u32 win_enable;
        u32 win_protect;
@@ -2648,7 +2647,7 @@ mvneta_conf_mbus_windows(struct mvneta_port *pp,
 }
 
 /* Power up the port */
-static void __devinit mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
+static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 {
        u32 val;
 
@@ -2671,7 +2670,7 @@ static void __devinit mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 }
 
 /* Device initialization routine */
-static int __devinit mvneta_probe(struct platform_device *pdev)
+static int mvneta_probe(struct platform_device *pdev)
 {
        const struct mbus_dram_target_info *dram_target_info;
        struct device_node *dn = pdev->dev.of_node;
@@ -2803,7 +2802,7 @@ err_free_netdev:
 }
 
 /* Device removal routine */
-static int __devexit mvneta_remove(struct platform_device *pdev)
+static int mvneta_remove(struct platform_device *pdev)
 {
        struct net_device  *dev = platform_get_drvdata(pdev);
        struct mvneta_port *pp = netdev_priv(dev);
@@ -2828,7 +2827,7 @@ MODULE_DEVICE_TABLE(of, mvneta_match);
 
 static struct platform_driver mvneta_driver = {
        .probe = mvneta_probe,
-       .remove = __devexit_p(mvneta_remove),
+       .remove = mvneta_remove,
        .driver = {
                .name = MVNETA_DRIVER_NAME,
                .of_match_table = mvneta_match,
index 2b799f4f1c37100f06eab93aef628d4124182230..6771b69f40d562bf58909a1f806bddd1ace9ea65 100644 (file)
@@ -630,10 +630,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
                ring->tx_csum++;
        }
 
-       /* Copy dst mac address to wqe */
-       ethh = (struct ethhdr *)skb->data;
-       tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest);
-       tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2));
+       if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) {
+               /* Copy dst mac address to wqe. This allows loopback in eSwitch,
+                * so that VFs and PF can communicate with each other
+                */
+               ethh = (struct ethhdr *)skb->data;
+               tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest);
+               tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2));
+       }
+
        /* Handle LSO (TSO) packets */
        if (lso_header_size) {
                /* Mark opcode as LSO */
index 9a9de51ecc91f72f1ea309385744ed21319fa6bf..8b3d0512a46bd90f5d8678f127069c17f04460a2 100644 (file)
@@ -1338,6 +1338,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 {
        struct mlx4_cmd_mailbox *mailbox;
        __be32 *outbox;
+       u32 dword_field;
        int err;
        u8 byte_field;
 
@@ -1372,10 +1373,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
        MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
 
+       MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
+       if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
+               param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
+       } else {
+               MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET);
+               if (byte_field & 0x8)
+                       param->steering_mode = MLX4_STEERING_MODE_B0;
+               else
+                       param->steering_mode = MLX4_STEERING_MODE_A0;
+       }
        /* steering attributes */
-       if (dev->caps.steering_mode ==
-           MLX4_STEERING_MODE_DEVICE_MANAGED) {
-
+       if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
                MLX4_GET(param->log_mc_entry_sz, outbox,
                         INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
index 2c2e7ade2a34c2912dab6ac92acc4ef90d3d675e..dbf2f69cc59fcb5efeefd7b50bce07ba975812eb 100644 (file)
@@ -172,6 +172,7 @@ struct mlx4_init_hca_param {
        u8  log_uar_sz;
        u8  uar_page_sz; /* log pg sz in 4k chunks */
        u8  fs_hash_enable_bits;
+       u8  steering_mode; /* for QUERY_HCA */
        u64 dev_cap_enabled;
 };
 
index b2acbe7706a34c667d20ca4a58e7057e4c0866b0..5163af314990d2793d529b7db24e752490eb9645 100644 (file)
@@ -85,15 +85,15 @@ static int probe_vf;
 module_param(probe_vf, int, 0644);
 MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)");
 
-int mlx4_log_num_mgm_entry_size = 10;
+int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;
 module_param_named(log_num_mgm_entry_size,
                        mlx4_log_num_mgm_entry_size, int, 0444);
 MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
                                         " of qp per mcg, for example:"
-                                        " 10 gives 248.range: 9<="
+                                        " 10 gives 248.range: <="
                                         " log_num_mgm_entry_size <= 12."
-                                        " Not in use with device managed"
-                                        " flow steering");
+                                        " To activate device managed"
+                                        " flow steering when available, set to -1");
 
 static bool enable_64b_cqe_eqe;
 module_param(enable_64b_cqe_eqe, bool, 0444);
@@ -281,28 +281,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev->caps.max_gso_sz         = dev_cap->max_gso_sz;
        dev->caps.max_rss_tbl_sz     = dev_cap->max_rss_tbl_sz;
 
-       if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) {
-               dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
-               dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
-               dev->caps.fs_log_max_ucast_qp_range_size =
-                       dev_cap->fs_log_max_ucast_qp_range_size;
-       } else {
-               if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
-                   dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) {
-                       dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
-               } else {
-                       dev->caps.steering_mode = MLX4_STEERING_MODE_A0;
-
-                       if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER ||
-                           dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
-                               mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags "
-                                               "set to use B0 steering. Falling back to A0 steering mode.\n");
-               }
-               dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
-       }
-       mlx4_dbg(dev, "Steering mode is: %s\n",
-                mlx4_steering_mode_str(dev->caps.steering_mode));
-
        /* Sense port always allowed on supported devices for ConnectX-1 and -2 */
        if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT)
                dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
@@ -402,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                }
        }
 
-       if ((dev_cap->flags &
+       if ((dev->caps.flags &
            (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&
            mlx4_is_master(dev))
                dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
@@ -493,6 +471,23 @@ int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
 }
 EXPORT_SYMBOL(mlx4_is_slave_active);
 
+static void slave_adjust_steering_mode(struct mlx4_dev *dev,
+                                      struct mlx4_dev_cap *dev_cap,
+                                      struct mlx4_init_hca_param *hca_param)
+{
+       dev->caps.steering_mode = hca_param->steering_mode;
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
+               dev->caps.fs_log_max_ucast_qp_range_size =
+                       dev_cap->fs_log_max_ucast_qp_range_size;
+       } else
+               dev->caps.num_qp_per_mgm =
+                       4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2);
+
+       mlx4_dbg(dev, "Steering mode is: %s\n",
+                mlx4_steering_mode_str(dev->caps.steering_mode));
+}
+
 static int mlx4_slave_cap(struct mlx4_dev *dev)
 {
        int                        err;
@@ -635,6 +630,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                dev->caps.cqe_size   = 32;
        }
 
+       slave_adjust_steering_mode(dev, &dev_cap, &hca_param);
+
        return 0;
 
 err_mem:
@@ -1321,6 +1318,59 @@ static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev)
        }
 }
 
+static int choose_log_fs_mgm_entry_size(int qp_per_entry)
+{
+       int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE;
+
+       for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE;
+             i++) {
+               if (qp_per_entry <= 4 * ((1 << i) / 16 - 2))
+                       break;
+       }
+
+       return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1;
+}
+
+static void choose_steering_mode(struct mlx4_dev *dev,
+                                struct mlx4_dev_cap *dev_cap)
+{
+       if (mlx4_log_num_mgm_entry_size == -1 &&
+           dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN &&
+           (!mlx4_is_mfunc(dev) ||
+            (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) &&
+           choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >=
+               MLX4_MIN_MGM_LOG_ENTRY_SIZE) {
+               dev->oper_log_mgm_entry_size =
+                       choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry);
+               dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
+               dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
+               dev->caps.fs_log_max_ucast_qp_range_size =
+                       dev_cap->fs_log_max_ucast_qp_range_size;
+       } else {
+               if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
+                   dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
+                       dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
+               else {
+                       dev->caps.steering_mode = MLX4_STEERING_MODE_A0;
+
+                       if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER ||
+                           dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
+                               mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags "
+                                         "set to use B0 steering. Falling back to A0 steering mode.\n");
+               }
+               dev->oper_log_mgm_entry_size =
+                       mlx4_log_num_mgm_entry_size > 0 ?
+                       mlx4_log_num_mgm_entry_size :
+                       MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;
+               dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
+       }
+       mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, "
+                "modparam log_num_mgm_entry_size = %d\n",
+                mlx4_steering_mode_str(dev->caps.steering_mode),
+                dev->oper_log_mgm_entry_size,
+                mlx4_log_num_mgm_entry_size);
+}
+
 static int mlx4_init_hca(struct mlx4_dev *dev)
 {
        struct mlx4_priv          *priv = mlx4_priv(dev);
@@ -1360,6 +1410,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                        goto err_stop_fw;
                }
 
+               choose_steering_mode(dev, &dev_cap);
+
                if (mlx4_is_master(dev))
                        mlx4_parav_master_pf_caps(dev);
 
@@ -1738,15 +1790,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
        int i;
 
        if (msi_x) {
-               /* In multifunction mode each function gets 2 msi-X vectors
-                * one for data path completions anf the other for asynch events
-                * or command completions */
-               if (mlx4_is_mfunc(dev)) {
-                       nreq = 2;
-               } else {
-                       nreq = min_t(int, dev->caps.num_eqs -
-                                    dev->caps.reserved_eqs, nreq);
-               }
+               nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
+                            nreq);
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
@@ -2452,6 +2497,17 @@ static int __init mlx4_verify_params(void)
                port_type_array[0] = true;
        }
 
+       if (mlx4_log_num_mgm_entry_size != -1 &&
+           (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE ||
+            mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) {
+               pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not "
+                          "in legal range (-1 or %d..%d)\n",
+                          mlx4_log_num_mgm_entry_size,
+                          MLX4_MIN_MGM_LOG_ENTRY_SIZE,
+                          MLX4_MAX_MGM_LOG_ENTRY_SIZE);
+               return -1;
+       }
+
        return 0;
 }
 
index e151c21baf2baf5970c9c232c79d0c8650c0eb4e..1ee4db3c6400398c3f4a71ebff04d2199699602c 100644 (file)
@@ -54,12 +54,7 @@ struct mlx4_mgm {
 
 int mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
 {
-       if (dev->caps.steering_mode ==
-           MLX4_STEERING_MODE_DEVICE_MANAGED)
-               return 1 << MLX4_FS_MGM_LOG_ENTRY_SIZE;
-       else
-               return min((1 << mlx4_log_num_mgm_entry_size),
-                          MLX4_MAX_MGM_ENTRY_SIZE);
+       return 1 << dev->oper_log_mgm_entry_size;
 }
 
 int mlx4_get_qp_per_mgm(struct mlx4_dev *dev)
index 1cf42036d7bbe5fec8831497032dbb245e9fd605..116c5c29d2d18488eb60b78b83e889cb119ddeae 100644 (file)
@@ -94,8 +94,10 @@ enum {
 };
 
 enum {
-       MLX4_MAX_MGM_ENTRY_SIZE = 0x1000,
-       MLX4_MAX_QP_PER_MGM     = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2),
+       MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE = 10,
+       MLX4_MIN_MGM_LOG_ENTRY_SIZE = 7,
+       MLX4_MAX_MGM_LOG_ENTRY_SIZE = 12,
+       MLX4_MAX_QP_PER_MGM = 4 * ((1 << MLX4_MAX_MGM_LOG_ENTRY_SIZE) / 16 - 2),
        MLX4_MTT_ENTRY_PER_SEG  = 8,
 };
 
index b05705f50f0fae529e3f728471280ea4a1a1d753..561ed2a22a1708448a40accc54ef72bcbff036c3 100644 (file)
@@ -3071,6 +3071,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
        struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
        int err;
+       int qpn;
        struct mlx4_net_trans_rule_hw_ctrl *ctrl;
        struct _rule_hw  *rule_header;
        int header_id;
@@ -3080,13 +3081,21 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                return -EOPNOTSUPP;
 
        ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+       qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
+       err = get_res(dev, slave, qpn, RES_QP, NULL);
+       if (err) {
+               pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
+               return err;
+       }
        rule_header = (struct _rule_hw *)(ctrl + 1);
        header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
 
        switch (header_id) {
        case MLX4_NET_TRANS_RULE_ID_ETH:
-               if (validate_eth_header_mac(slave, rule_header, rlist))
-                       return -EINVAL;
+               if (validate_eth_header_mac(slave, rule_header, rlist)) {
+                       err = -EINVAL;
+                       goto err_put;
+               }
                break;
        case MLX4_NET_TRANS_RULE_ID_IB:
                break;
@@ -3094,14 +3103,17 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        case MLX4_NET_TRANS_RULE_ID_TCP:
        case MLX4_NET_TRANS_RULE_ID_UDP:
                pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
-               if (add_eth_header(dev, slave, inbox, rlist, header_id))
-                       return -EINVAL;
+               if (add_eth_header(dev, slave, inbox, rlist, header_id)) {
+                       err = -EINVAL;
+                       goto err_put;
+               }
                vhcr->in_modifier +=
                        sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
                break;
        default:
                pr_err("Corrupted mailbox.\n");
-               return -EINVAL;
+               err = -EINVAL;
+               goto err_put;
        }
 
        err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
@@ -3109,16 +3121,18 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                           MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
                           MLX4_CMD_NATIVE);
        if (err)
-               return err;
+               goto err_put;
 
        err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0);
        if (err) {
                mlx4_err(dev, "Fail to add flow steering resources.\n ");
                /* detach rule*/
                mlx4_cmd(dev, vhcr->out_param, 0, 0,
-                        MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
+                        MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
                         MLX4_CMD_NATIVE);
        }
+err_put:
+       put_res(dev, slave, qpn, RES_QP);
        return err;
 }
 
index 653487dc7b52c58d69f42723cd5e572dfddc90a0..87fa5919c455224f8ee6ab47a4bae742e7fc801f 100644 (file)
@@ -1821,6 +1821,11 @@ static int nv_alloc_rx(struct net_device *dev)
                                                             skb->data,
                                                             skb_tailroom(skb),
                                                             PCI_DMA_FROMDEVICE);
+                       if (pci_dma_mapping_error(np->pci_dev,
+                                                 np->put_rx_ctx->dma)) {
+                               kfree_skb(skb);
+                               goto packet_dropped;
+                       }
                        np->put_rx_ctx->dma_len = skb_tailroom(skb);
                        np->put_rx.orig->buf = cpu_to_le32(np->put_rx_ctx->dma);
                        wmb();
@@ -1830,6 +1835,7 @@ static int nv_alloc_rx(struct net_device *dev)
                        if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx))
                                np->put_rx_ctx = np->first_rx_ctx;
                } else {
+packet_dropped:
                        u64_stats_update_begin(&np->swstats_rx_syncp);
                        np->stat_rx_dropped++;
                        u64_stats_update_end(&np->swstats_rx_syncp);
@@ -1856,6 +1862,11 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
                                                             skb->data,
                                                             skb_tailroom(skb),
                                                             PCI_DMA_FROMDEVICE);
+                       if (pci_dma_mapping_error(np->pci_dev,
+                                                 np->put_rx_ctx->dma)) {
+                               kfree_skb(skb);
+                               goto packet_dropped;
+                       }
                        np->put_rx_ctx->dma_len = skb_tailroom(skb);
                        np->put_rx.ex->bufhigh = cpu_to_le32(dma_high(np->put_rx_ctx->dma));
                        np->put_rx.ex->buflow = cpu_to_le32(dma_low(np->put_rx_ctx->dma));
@@ -1866,6 +1877,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
                        if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx))
                                np->put_rx_ctx = np->first_rx_ctx;
                } else {
+packet_dropped:
                        u64_stats_update_begin(&np->swstats_rx_syncp);
                        np->stat_rx_dropped++;
                        u64_stats_update_end(&np->swstats_rx_syncp);
@@ -2217,6 +2229,15 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
                np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
                                                PCI_DMA_TODEVICE);
+               if (pci_dma_mapping_error(np->pci_dev,
+                                         np->put_tx_ctx->dma)) {
+                       /* on DMA mapping error - drop the packet */
+                       kfree_skb(skb);
+                       u64_stats_update_begin(&np->swstats_tx_syncp);
+                       np->stat_tx_dropped++;
+                       u64_stats_update_end(&np->swstats_tx_syncp);
+                       return NETDEV_TX_OK;
+               }
                np->put_tx_ctx->dma_len = bcnt;
                np->put_tx_ctx->dma_single = 1;
                put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma);
@@ -2337,6 +2358,15 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
                bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
                np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
                                                PCI_DMA_TODEVICE);
+               if (pci_dma_mapping_error(np->pci_dev,
+                                         np->put_tx_ctx->dma)) {
+                       /* on DMA mapping error - drop the packet */
+                       kfree_skb(skb);
+                       u64_stats_update_begin(&np->swstats_tx_syncp);
+                       np->stat_tx_dropped++;
+                       u64_stats_update_end(&np->swstats_tx_syncp);
+                       return NETDEV_TX_OK;
+               }
                np->put_tx_ctx->dma_len = bcnt;
                np->put_tx_ctx->dma_single = 1;
                put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
@@ -5003,6 +5033,11 @@ static int nv_loopback_test(struct net_device *dev)
        test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data,
                                       skb_tailroom(tx_skb),
                                       PCI_DMA_FROMDEVICE);
+       if (pci_dma_mapping_error(np->pci_dev,
+                                 test_dma_addr)) {
+               dev_kfree_skb_any(tx_skb);
+               goto out;
+       }
        pkt_data = skb_put(tx_skb, pkt_len);
        for (i = 0; i < pkt_len; i++)
                pkt_data[i] = (u8)(i & 0xff);
index bc165f4d0f65cebb6cc82e3aa99590863963f767..695667d471a1bef8dc81dd8034a593a118993e07 100644 (file)
@@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
                                         buffrag->length, PCI_DMA_TODEVICE);
                        buffrag->dma = 0ULL;
                }
-               for (j = 0; j < cmd_buf->frag_count; j++) {
+               for (j = 1; j < cmd_buf->frag_count; j++) {
                        buffrag++;
                        if (buffrag->dma) {
                                pci_unmap_page(adapter->pdev, buffrag->dma,
index 6098fd4adfeb89ef5ed9c15407799ddbdcf02e7a..69e321a650779c9d3bae975a273035b922fca08f 100644 (file)
@@ -1963,10 +1963,12 @@ unwind:
        while (--i >= 0) {
                nf = &pbuf->frag_array[i+1];
                pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+               nf->dma = 0ULL;
        }
 
        nf = &pbuf->frag_array[0];
        pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+       nf->dma = 0ULL;
 
 out_err:
        return -ENOMEM;
index 6f82812d0fab9e2e5697b3770d2c3c524b5daeab..09aa310b619475a82c6dffc81752f8584ff9ddee 100644 (file)
@@ -986,8 +986,13 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
        th->seq = htonl(seq_number);
        length = skb->len;
 
-       if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+       if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) {
                skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
+               if (skb->protocol == htons(ETH_P_IPV6))
+                       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+               else
+                       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+       }
 
        if (vid != 0xffff)
                __vlan_hwaccel_put_tag(skb, vid);
index f80cd975daed2b84a31af47db58b828d28139638..3e73742024b0cb5af229df1336a9a3aeab653b1f 100644 (file)
@@ -4678,7 +4678,7 @@ static int qlge_probe(struct pci_dev *pdev,
        qdev = netdev_priv(ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);
        ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-               NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN |
+               NETIF_F_TSO | NETIF_F_TSO_ECN |
                NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM;
        ndev->features = ndev->hw_features |
                NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
index ed96f309bca8e030a0c098df8b8e728314f04bb0..998974f7874253f67880009d96f1e80f4788a408 100644 (file)
@@ -450,7 +450,6 @@ enum rtl8168_registers {
 #define PWM_EN                         (1 << 22)
 #define RXDV_GATED_EN                  (1 << 19)
 #define EARLY_TALLY_EN                 (1 << 16)
-#define FORCE_CLK                      (1 << 15) /* force clock request */
 };
 
 enum rtl_register_content {
@@ -514,7 +513,6 @@ enum rtl_register_content {
        PMEnable        = (1 << 0),     /* Power Management Enable */
 
        /* Config2 register p. 25 */
-       ClkReqEn        = (1 << 7),     /* Clock Request Enable */
        MSIEnable       = (1 << 5),     /* 8169 only. Reserved in the 8168. */
        PCI_Clock_66MHz = 0x01,
        PCI_Clock_33MHz = 0x00,
@@ -535,7 +533,6 @@ enum rtl_register_content {
        Spi_en          = (1 << 3),
        LanWake         = (1 << 1),     /* LanWake enable/disable */
        PMEStatus       = (1 << 0),     /* PME status can be reset by PCI RST# */
-       ASPM_en         = (1 << 0),     /* ASPM enable */
 
        /* TBICSR p.28 */
        TBIReset        = 0x80000000,
@@ -684,7 +681,6 @@ enum features {
        RTL_FEATURE_WOL         = (1 << 0),
        RTL_FEATURE_MSI         = (1 << 1),
        RTL_FEATURE_GMII        = (1 << 2),
-       RTL_FEATURE_FW_LOADED   = (1 << 3),
 };
 
 struct rtl8169_counters {
@@ -1826,8 +1822,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
 
        if (opts2 & RxVlanTag)
                __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
-
-       desc->opts2 = 0;
 }
 
 static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -2391,10 +2385,8 @@ static void rtl_apply_firmware(struct rtl8169_private *tp)
        struct rtl_fw *rtl_fw = tp->rtl_fw;
 
        /* TODO: release firmware once rtl_phy_write_fw signals failures. */
-       if (!IS_ERR_OR_NULL(rtl_fw)) {
+       if (!IS_ERR_OR_NULL(rtl_fw))
                rtl_phy_write_fw(tp, rtl_fw);
-               tp->features |= RTL_FEATURE_FW_LOADED;
-       }
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -2405,31 +2397,6 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
                rtl_apply_firmware(tp);
 }
 
-static void r810x_aldps_disable(struct rtl8169_private *tp)
-{
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(100);
-}
-
-static void r810x_aldps_enable(struct rtl8169_private *tp)
-{
-       if (!(tp->features & RTL_FEATURE_FW_LOADED))
-               return;
-
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x8310);
-}
-
-static void r8168_aldps_enable_1(struct rtl8169_private *tp)
-{
-       if (!(tp->features & RTL_FEATURE_FW_LOADED))
-               return;
-
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
-}
-
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
        static const struct phy_reg phy_reg_init[] = {
@@ -3220,8 +3187,6 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
        rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
        rtl_writephy(tp, 0x1f, 0x0000);
 
-       r8168_aldps_enable_1(tp);
-
        /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
        rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
 }
@@ -3296,8 +3261,6 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x05, 0x8b85);
        rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
        rtl_writephy(tp, 0x1f, 0x0000);
-
-       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3305,8 +3268,6 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
        rtl_apply_firmware(tp);
 
        rtl8168f_hw_phy_config(tp);
-
-       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
@@ -3404,8 +3365,6 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
        rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
        rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
        rtl_writephy(tp, 0x1f, 0x0000);
-
-       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3491,19 +3450,21 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
        };
 
        /* Disable ALDPS before ram code */
-       r810x_aldps_disable(tp);
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x0310);
+       msleep(100);
 
        rtl_apply_firmware(tp);
 
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
-
-       r810x_aldps_enable(tp);
 }
 
 static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
 {
        /* Disable ALDPS before setting firmware */
-       r810x_aldps_disable(tp);
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x0310);
+       msleep(20);
 
        rtl_apply_firmware(tp);
 
@@ -3513,8 +3474,6 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x10, 0x401f);
        rtl_writephy(tp, 0x19, 0x7030);
        rtl_writephy(tp, 0x1f, 0x0000);
-
-       r810x_aldps_enable(tp);
 }
 
 static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -3527,7 +3486,9 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
        };
 
        /* Disable ALDPS before ram code */
-       r810x_aldps_disable(tp);
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x0310);
+       msleep(100);
 
        rtl_apply_firmware(tp);
 
@@ -3535,8 +3496,6 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
        rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
-
-       r810x_aldps_enable(tp);
 }
 
 static void rtl_hw_phy_config(struct net_device *dev)
@@ -5053,6 +5012,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, EarlySize);
 
+       rtl_disable_clock_request(pdev);
+
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
 
@@ -5061,8 +5022,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
        RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
-       RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+       RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
 }
 
 static void rtl_hw_start_8168f(struct rtl8169_private *tp)
@@ -5087,12 +5047,13 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, EarlySize);
 
+       rtl_disable_clock_request(pdev);
+
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
-       RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
-       RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+       RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+       RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
 }
 
 static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
@@ -5149,10 +5110,8 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
        rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
 
        RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-       RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
+       RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
        RTL_W8(MaxTxPacketSize, EarlySize);
-       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 
        rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
        rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
@@ -5368,9 +5327,6 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
 
        RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
-       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
-       RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
        rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
 }
@@ -5396,9 +5352,6 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
 
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
-       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
-       RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
        rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
 
@@ -5420,10 +5373,7 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
        /* Force LAN exit from ASPM if Rx/Tx are not idle */
        RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
 
-       RTL_W32(MISC,
-               (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
-       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
-       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+       RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
        RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
 }
@@ -6064,8 +6014,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
                            !(status & (RxRWT | RxFOVF)) &&
                            (dev->features & NETIF_F_RXALL))
                                goto process_pkt;
-
-                       rtl8169_mark_to_asic(desc, rx_buf_sz);
                } else {
                        struct sk_buff *skb;
                        dma_addr_t addr;
@@ -6086,16 +6034,14 @@ process_pkt:
                        if (unlikely(rtl8169_fragmented_frame(status))) {
                                dev->stats.rx_dropped++;
                                dev->stats.rx_length_errors++;
-                               rtl8169_mark_to_asic(desc, rx_buf_sz);
-                               continue;
+                               goto release_descriptor;
                        }
 
                        skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
                                                  tp, pkt_size, addr);
-                       rtl8169_mark_to_asic(desc, rx_buf_sz);
                        if (!skb) {
                                dev->stats.rx_dropped++;
-                               continue;
+                               goto release_descriptor;
                        }
 
                        rtl8169_rx_csum(skb, status);
@@ -6111,13 +6057,10 @@ process_pkt:
                        tp->rx_stats.bytes += pkt_size;
                        u64_stats_update_end(&tp->rx_stats.syncp);
                }
-
-               /* Work around for AMD plateform. */
-               if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
-                   (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
-                       desc->opts2 = 0;
-                       cur_rx++;
-               }
+release_descriptor:
+               desc->opts2 = 0;
+               wmb();
+               rtl8169_mark_to_asic(desc, rx_buf_sz);
        }
 
        count = cur_rx - tp->cur_rx;
index f07c0612abf6843ffe7b41a8ecc2623aff42298f..b75f4b286895021fd587b880a66c17aa4251780b 100644 (file)
@@ -69,7 +69,7 @@
 
 #undef STMMAC_XMIT_DEBUG
 /*#define STMMAC_XMIT_DEBUG*/
-#ifdef STMMAC_TX_DEBUG
+#ifdef STMMAC_XMIT_DEBUG
 #define TX_DBG(fmt, args...)  printk(fmt, ## args)
 #else
 #define TX_DBG(fmt, args...)  do { } while (0)
index 0376a5e6b2bf9c0584e45bf2e34c6f5ee8608033..0b9829fe3eea7344886060d826730aa13e6eba3e 100644 (file)
@@ -188,8 +188,6 @@ int stmmac_mdio_register(struct net_device *ndev)
                goto bus_register_fail;
        }
 
-       priv->mii = new_bus;
-
        found = 0;
        for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
                struct phy_device *phydev = new_bus->phy_map[addr];
@@ -237,8 +235,14 @@ int stmmac_mdio_register(struct net_device *ndev)
                }
        }
 
-       if (!found)
+       if (!found) {
                pr_warning("%s: No PHY found\n", ndev->name);
+               mdiobus_unregister(new_bus);
+               mdiobus_free(new_bus);
+               return -ENODEV;
+       }
+
+       priv->mii = new_bus;
 
        return 0;
 
index 5e62c1aeeffb2325fd392820c9aa1110f4b19a19..463597f919f132b48a238672001e60c36d830459 100644 (file)
@@ -247,8 +247,7 @@ static void cpts_clk_init(struct cpts *cpts)
                cpts->refclk = NULL;
                return;
        }
-       clk_enable(cpts->refclk);
-       cpts->freq = cpts->refclk->recalc(cpts->refclk);
+       clk_prepare_enable(cpts->refclk);
 }
 
 static void cpts_clk_release(struct cpts *cpts)
index e1bba3a496b2bdb32f0fc08557a61361e59802b1..fe993cdd7e23b76ad13f09585c215d87c83a0e46 100644 (file)
@@ -120,7 +120,6 @@ struct cpts {
        struct delayed_work overflow_work;
        int phc_index;
        struct clk *refclk;
-       unsigned long freq;
        struct list_head events;
        struct list_head pool;
        struct cpts_event pool_data[CPTS_MAX_EVENTS];
index 7992b3e05d3dd5a48f7701114a2264d23f3ce4e8..78ace59efd297531001c171d47351c2fe9bb8ef9 100644 (file)
@@ -1801,7 +1801,7 @@ static void rhine_tx(struct net_device *dev)
                                         rp->tx_skbuff[entry]->len,
                                         PCI_DMA_TODEVICE);
                }
-               dev_kfree_skb_irq(rp->tx_skbuff[entry]);
+               dev_kfree_skb(rp->tx_skbuff[entry]);
                rp->tx_skbuff[entry] = NULL;
                entry = (++rp->dirty_tx) % TX_RING_SIZE;
        }
@@ -2010,11 +2010,7 @@ static void rhine_slow_event_task(struct work_struct *work)
        if (intr_status & IntrPCIErr)
                netif_warn(rp, hw, dev, "PCI error\n");
 
-       napi_disable(&rp->napi);
-       rhine_irq_disable(rp);
-       /* Slow and safe. Consider __napi_schedule as a replacement ? */
-       napi_enable(&rp->napi);
-       napi_schedule(&rp->napi);
+       iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable);
 
 out_unlock:
        mutex_unlock(&rp->task_lock);
index 5778a4ae116466d637288fe668fb990ac623fb6e..122d60c0481b0d8eab2a95b56bc495665390a0ec 100644 (file)
@@ -27,7 +27,7 @@ config XILINX_EMACLITE
 
 config XILINX_AXI_EMAC
        tristate "Xilinx 10/100/1000 AXI Ethernet support"
-       depends on (PPC32 || MICROBLAZE)
+       depends on MICROBLAZE
        select PHYLIB
        ---help---
          This driver supports the 10/100/1000 Ethernet from Xilinx for the
index d9f69b82cc4ff638981798e23bbe3c0e9e6329f1..6f47100e58d71584ea13bb0c83c1607ca967a58a 100644 (file)
@@ -1590,7 +1590,7 @@ static int axienet_of_probe(struct platform_device *op)
        lp->rx_irq = irq_of_parse_and_map(np, 1);
        lp->tx_irq = irq_of_parse_and_map(np, 0);
        of_node_put(np);
-       if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
+       if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
                dev_err(&op->dev, "could not determine irqs\n");
                ret = -ENOMEM;
                goto err_iounmap_2;
index 5fd6f4674326f0d3236ae8a97127b842ffffa008..e6fe0d80d6122fcd8dfcf7bb65fa71dac68c1e73 100644 (file)
@@ -84,7 +84,7 @@ struct hv_netvsc_packet {
 };
 
 struct netvsc_device_info {
-       unsigned char mac_adr[6];
+       unsigned char mac_adr[ETH_ALEN];
        bool link_state;        /* 0 - link up, 1 - link down */
        int  ring_size;
 };
index f825a629a699cfe5fac73803353da4b47ca18974..8264f0ef7692f5c832a12336a1188f9c7620190f 100644 (file)
@@ -349,7 +349,7 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
        struct net_device_context *ndevctx = netdev_priv(ndev);
        struct hv_device *hdev =  ndevctx->device_ctx;
        struct sockaddr *addr = p;
-       char save_adr[14];
+       char save_adr[ETH_ALEN];
        unsigned char save_aatype;
        int err;
 
index 81f8f9e31db510892acae3cdb39a799de7e21be9..fcbf680c3e62f73af4933896641045de34f1f68c 100644 (file)
@@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
 
        skb_orphan(skb);
 
+       /* Before queueing this packet to netif_rx(),
+        * make sure dst is refcounted.
+        */
+       skb_dst_force(skb);
+
        skb->protocol = eth_type_trans(skb, dev);
 
        /* it's OK to use per_cpu_ptr() because BHs are off */
index 68a43fe602e7a89ccffa54d1a5b82e2da4e5330c..d3fb97d97cbcb61f68deda7c3009a83393515656 100644 (file)
@@ -822,7 +822,10 @@ static int macvlan_changelink(struct net_device *dev,
 
 static size_t macvlan_get_size(const struct net_device *dev)
 {
-       return nla_total_size(4);
+       return (0
+               + nla_total_size(4) /* IFLA_MACVLAN_MODE */
+               + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */
+               );
 }
 
 static int macvlan_fill_info(struct sk_buff *skb,
index d5199cb4caecd06c1774295765476d3a508e4a10..b5ddd5077a80dd9c6324c92e68a1ecd8a03314e7 100644 (file)
@@ -36,8 +36,9 @@ MODULE_LICENSE("GPL");
 
 /* IP101A/G - IP1001 */
 #define IP10XX_SPEC_CTRL_STATUS                16      /* Spec. Control Register */
+#define IP1001_RXPHASE_SEL             (1<<0)  /* Add delay on RX_CLK */
+#define IP1001_TXPHASE_SEL             (1<<1)  /* Add delay on TX_CLK */
 #define IP1001_SPEC_CTRL_STATUS_2      20      /* IP1001 Spec. Control Reg 2 */
-#define IP1001_PHASE_SEL_MASK          3       /* IP1001 RX/TXPHASE_SEL */
 #define IP1001_APS_ON                  11      /* IP1001 APS Mode  bit */
 #define IP101A_G_APS_ON                        2       /* IP101A/G APS Mode bit */
 #define IP101A_G_IRQ_CONF_STATUS       0x11    /* Conf Info IRQ & Status Reg */
@@ -138,19 +139,24 @@ static int ip1001_config_init(struct phy_device *phydev)
        if (c < 0)
                return c;
 
-       /* INTR pin used: speed/link/duplex will cause an interrupt */
-       c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
-       if (c < 0)
-               return c;
+       if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 
-       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
-               /* Additional delay (2ns) used to adjust RX clock phase
-                * at RGMII interface */
                c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
                if (c < 0)
                        return c;
 
-               c |= IP1001_PHASE_SEL_MASK;
+               c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
+
+               if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+                       c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
+               else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+                       c |= IP1001_RXPHASE_SEL;
+               else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+                       c |= IP1001_TXPHASE_SEL;
+
                c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
                if (c < 0)
                        return c;
@@ -167,6 +173,11 @@ static int ip101a_g_config_init(struct phy_device *phydev)
        if (c < 0)
                return c;
 
+       /* INTR pin used: speed/link/duplex will cause an interrupt */
+       c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
+       if (c < 0)
+               return c;
+
        /* Enable Auto Power Saving mode */
        c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
        c |= IP101A_G_APS_ON;
index 5d2a3f2158876bb39ffc02f2647a57676b1bb718..22dec9c7ef05d7480e87b575605e2240f4476a20 100644 (file)
@@ -353,15 +353,6 @@ static int m88e1111_config_init(struct phy_device *phydev)
        int err;
        int temp;
 
-       /* Enable Fiber/Copper auto selection */
-       temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
-       temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
-       phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
-
-       temp = phy_read(phydev, MII_BMCR);
-       temp |= BMCR_RESET;
-       phy_write(phydev, MII_BMCR, temp);
-
        if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
index 504f7f1cad94655a52526b4fe136fb1468942f1d..2917a86f4c43ec44a3e18566acd7dd00d071660a 100644 (file)
@@ -109,11 +109,11 @@ struct tap_filter {
        unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
-/* 1024 is probably a high enough limit: modern hypervisors seem to support on
- * the order of 100-200 CPUs so this leaves us some breathing space if we want
- * to match a queue per guest CPU.
- */
-#define MAX_TAP_QUEUES 1024
+/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for
+ * the netdevice to be fit in one page. So we can make sure the success of
+ * memory allocation. TODO: increase the limit. */
+#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
+#define MAX_TAP_FLOWS  4096
 
 #define TUN_FLOW_EXPIRE (3 * HZ)
 
@@ -180,12 +180,13 @@ struct tun_struct {
        int debug;
 #endif
        spinlock_t lock;
-       struct kmem_cache *flow_cache;
        struct hlist_head flows[TUN_NUM_FLOW_ENTRIES];
        struct timer_list flow_gc_timer;
        unsigned long ageing_time;
        unsigned int numdisabled;
        struct list_head disabled;
+       void *security;
+       u32 flow_count;
 };
 
 static inline u32 tun_hashfn(u32 rxhash)
@@ -209,8 +210,8 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
                                              struct hlist_head *head,
                                              u32 rxhash, u16 queue_index)
 {
-       struct tun_flow_entry *e = kmem_cache_alloc(tun->flow_cache,
-                                                   GFP_ATOMIC);
+       struct tun_flow_entry *e = kmalloc(sizeof(*e), GFP_ATOMIC);
+
        if (e) {
                tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n",
                          rxhash, queue_index);
@@ -219,23 +220,18 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
                e->queue_index = queue_index;
                e->tun = tun;
                hlist_add_head_rcu(&e->hash_link, head);
+               ++tun->flow_count;
        }
        return e;
 }
 
-static void tun_flow_free(struct rcu_head *head)
-{
-       struct tun_flow_entry *e
-               = container_of(head, struct tun_flow_entry, rcu);
-       kmem_cache_free(e->tun->flow_cache, e);
-}
-
 static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
 {
        tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n",
                  e->rxhash, e->queue_index);
        hlist_del_rcu(&e->hash_link);
-       call_rcu(&e->rcu, tun_flow_free);
+       kfree_rcu(e, rcu);
+       --tun->flow_count;
 }
 
 static void tun_flow_flush(struct tun_struct *tun)
@@ -302,11 +298,12 @@ static void tun_flow_cleanup(unsigned long data)
 }
 
 static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
-                           u16 queue_index)
+                           struct tun_file *tfile)
 {
        struct hlist_head *head;
        struct tun_flow_entry *e;
        unsigned long delay = tun->ageing_time;
+       u16 queue_index = tfile->queue_index;
 
        if (!rxhash)
                return;
@@ -315,7 +312,9 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
 
        rcu_read_lock();
 
-       if (tun->numqueues == 1)
+       /* We may get a very small possibility of OOO during switching, not
+        * worth to optimize.*/
+       if (tun->numqueues == 1 || tfile->detached)
                goto unlock;
 
        e = tun_flow_find(head, rxhash);
@@ -325,7 +324,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
                e->updated = jiffies;
        } else {
                spin_lock_bh(&tun->lock);
-               if (!tun_flow_find(head, rxhash))
+               if (!tun_flow_find(head, rxhash) &&
+                   tun->flow_count < MAX_TAP_FLOWS)
                        tun_flow_create(tun, head, rxhash, queue_index);
 
                if (!timer_pending(&tun->flow_gc_timer))
@@ -412,24 +412,23 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
        struct tun_struct *tun;
        struct net_device *dev;
 
-       tun = rcu_dereference_protected(tfile->tun,
-                                       lockdep_rtnl_is_held());
-       if (tun) {
+       tun = rtnl_dereference(tfile->tun);
+
+       if (tun && !tfile->detached) {
                u16 index = tfile->queue_index;
                BUG_ON(index >= tun->numqueues);
                dev = tun->dev;
 
                rcu_assign_pointer(tun->tfiles[index],
                                   tun->tfiles[tun->numqueues - 1]);
-               rcu_assign_pointer(tfile->tun, NULL);
-               ntfile = rcu_dereference_protected(tun->tfiles[index],
-                                                  lockdep_rtnl_is_held());
+               ntfile = rtnl_dereference(tun->tfiles[index]);
                ntfile->queue_index = index;
 
                --tun->numqueues;
-               if (clean)
+               if (clean) {
+                       rcu_assign_pointer(tfile->tun, NULL);
                        sock_put(&tfile->sk);
-               else
+               else
                        tun_disable_queue(tun, tfile);
 
                synchronize_net();
@@ -437,14 +436,19 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                /* Drop read queue */
                skb_queue_purge(&tfile->sk.sk_receive_queue);
                tun_set_real_num_queues(tun);
-       } else if (tfile->detached && clean)
+       } else if (tfile->detached && clean) {
                tun = tun_enable_queue(tfile);
+               sock_put(&tfile->sk);
+       }
 
        if (clean) {
-               if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
-                   !(tun->flags & TUN_PERSIST))
-                       if (tun->dev->reg_state == NETREG_REGISTERED)
+               if (tun && tun->numqueues == 0 && tun->numdisabled == 0) {
+                       netif_carrier_off(tun->dev);
+
+                       if (!(tun->flags & TUN_PERSIST) &&
+                           tun->dev->reg_state == NETREG_REGISTERED)
                                unregister_netdevice(tun->dev);
+               }
 
                BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
                                 &tfile->socket.flags));
@@ -466,19 +470,21 @@ static void tun_detach_all(struct net_device *dev)
        int i, n = tun->numqueues;
 
        for (i = 0; i < n; i++) {
-               tfile = rcu_dereference_protected(tun->tfiles[i],
-                                                 lockdep_rtnl_is_held());
+               tfile = rtnl_dereference(tun->tfiles[i]);
                BUG_ON(!tfile);
                wake_up_all(&tfile->wq.wait);
                rcu_assign_pointer(tfile->tun, NULL);
                --tun->numqueues;
        }
+       list_for_each_entry(tfile, &tun->disabled, next) {
+               wake_up_all(&tfile->wq.wait);
+               rcu_assign_pointer(tfile->tun, NULL);
+       }
        BUG_ON(tun->numqueues != 0);
 
        synchronize_net();
        for (i = 0; i < n; i++) {
-               tfile = rcu_dereference_protected(tun->tfiles[i],
-                                                 lockdep_rtnl_is_held());
+               tfile = rtnl_dereference(tun->tfiles[i]);
                /* Drop read queue */
                skb_queue_purge(&tfile->sk.sk_receive_queue);
                sock_put(&tfile->sk);
@@ -489,6 +495,9 @@ static void tun_detach_all(struct net_device *dev)
                sock_put(&tfile->sk);
        }
        BUG_ON(tun->numdisabled != 0);
+
+       if (tun->flags & TUN_PERSIST)
+               module_put(THIS_MODULE);
 }
 
 static int tun_attach(struct tun_struct *tun, struct file *file)
@@ -496,8 +505,12 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
        struct tun_file *tfile = file->private_data;
        int err;
 
+       err = security_tun_dev_attach(tfile->socket.sk, tun->security);
+       if (err < 0)
+               goto out;
+
        err = -EINVAL;
-       if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+       if (rtnl_dereference(tfile->tun) && !tfile->detached)
                goto out;
 
        err = -EBUSY;
@@ -833,12 +846,6 @@ static int tun_flow_init(struct tun_struct *tun)
 {
        int i;
 
-       tun->flow_cache = kmem_cache_create("tun_flow_cache",
-                                           sizeof(struct tun_flow_entry), 0, 0,
-                                           NULL);
-       if (!tun->flow_cache)
-               return -ENOMEM;
-
        for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++)
                INIT_HLIST_HEAD(&tun->flows[i]);
 
@@ -854,10 +861,6 @@ static void tun_flow_uninit(struct tun_struct *tun)
 {
        del_timer_sync(&tun->flow_gc_timer);
        tun_flow_flush(tun);
-
-       /* Wait for completion of call_rcu()'s */
-       rcu_barrier();
-       kmem_cache_destroy(tun->flow_cache);
 }
 
 /* Initialize net device. */
@@ -1206,7 +1209,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        tun->dev->stats.rx_packets++;
        tun->dev->stats.rx_bytes += len;
 
-       tun_flow_update(tun, rxhash, tfile->queue_index);
+       tun_flow_update(tun, rxhash, tfile);
        return total_len;
 }
 
@@ -1389,6 +1392,7 @@ static void tun_free_netdev(struct net_device *dev)
 
        BUG_ON(!(list_empty(&tun->disabled)));
        tun_flow_uninit(tun);
+       security_tun_dev_free_security(tun->security);
        free_netdev(dev);
 }
 
@@ -1562,6 +1566,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        struct net_device *dev;
        int err;
 
+       if (tfile->detached)
+               return -EINVAL;
+
        dev = __dev_get_by_name(net, ifr->ifr_name);
        if (dev) {
                if (ifr->ifr_flags & IFF_TUN_EXCL)
@@ -1575,7 +1582,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                if (tun_not_capable(tun))
                        return -EPERM;
-               err = security_tun_dev_attach(tfile->socket.sk);
+               err = security_tun_dev_open(tun->security);
                if (err < 0)
                        return err;
 
@@ -1590,6 +1597,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        else {
                char *name;
                unsigned long flags = 0;
+               int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ?
+                            MAX_TAP_QUEUES : 1;
 
                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
@@ -1613,8 +1622,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                        name = ifr->ifr_name;
 
                dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
-                                      tun_setup,
-                                      MAX_TAP_QUEUES, MAX_TAP_QUEUES);
+                                      tun_setup, queues, queues);
+
                if (!dev)
                        return -ENOMEM;
 
@@ -1632,7 +1641,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                spin_lock_init(&tun->lock);
 
-               security_tun_dev_post_create(&tfile->sk);
+               err = security_tun_dev_alloc_security(&tun->security);
+               if (err < 0)
+                       goto err_free_dev;
 
                tun_net_init(dev);
 
@@ -1657,10 +1668,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
                    device_create_file(&tun->dev->dev, &dev_attr_group))
                        pr_err("Failed to create tun sysfs files\n");
-
-               netif_carrier_on(tun->dev);
        }
 
+       netif_carrier_on(tun->dev);
+
        tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
        if (ifr->ifr_flags & IFF_NO_PI)
@@ -1756,8 +1767,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n)
        struct tun_file *tfile;
 
        for (i = 0; i < n; i++) {
-               tfile = rcu_dereference_protected(tun->tfiles[i],
-                                                 lockdep_rtnl_is_held());
+               tfile = rtnl_dereference(tun->tfiles[i]);
                sk_detach_filter(tfile->socket.sk);
        }
 
@@ -1770,8 +1780,7 @@ static int tun_attach_filter(struct tun_struct *tun)
        struct tun_file *tfile;
 
        for (i = 0; i < tun->numqueues; i++) {
-               tfile = rcu_dereference_protected(tun->tfiles[i],
-                                                 lockdep_rtnl_is_held());
+               tfile = rtnl_dereference(tun->tfiles[i]);
                ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
                if (ret) {
                        tun_detach_filter(tun, i);
@@ -1789,8 +1798,7 @@ static void tun_set_sndbuf(struct tun_struct *tun)
        int i;
 
        for (i = 0; i < tun->numqueues; i++) {
-               tfile = rcu_dereference_protected(tun->tfiles[i],
-                                               lockdep_rtnl_is_held());
+               tfile = rtnl_dereference(tun->tfiles[i]);
                tfile->socket.sk->sk_sndbuf = tun->sndbuf;
        }
 }
@@ -1805,22 +1813,24 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
 
        if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
                tun = tfile->detached;
-               if (!tun)
+               if (!tun) {
                        ret = -EINVAL;
-               else if (tun_not_capable(tun))
-                       ret = -EPERM;
-               else
-                       ret = tun_attach(tun, file);
+                       goto unlock;
+               }
+               ret = security_tun_dev_attach_queue(tun->security);
+               if (ret < 0)
+                       goto unlock;
+               ret = tun_attach(tun, file);
        } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
-               tun = rcu_dereference_protected(tfile->tun,
-                                               lockdep_rtnl_is_held());
-               if (!tun || !(tun->flags & TUN_TAP_MQ))
+               tun = rtnl_dereference(tfile->tun);
+               if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached)
                        ret = -EINVAL;
                else
                        __tun_detach(tfile, false);
        } else
                ret = -EINVAL;
 
+unlock:
        rtnl_unlock();
        return ret;
 }
@@ -1898,10 +1908,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                /* Disable/Enable persist mode. Keep an extra reference to the
                 * module to prevent the module being unprobed.
                 */
-               if (arg) {
+               if (arg && !(tun->flags & TUN_PERSIST)) {
                        tun->flags |= TUN_PERSIST;
                        __module_get(THIS_MODULE);
-               } else {
+               }
+               if (!arg && (tun->flags & TUN_PERSIST)) {
                        tun->flags &= ~TUN_PERSIST;
                        module_put(THIS_MODULE);
                }
index 42f51c71ec1fc7444c668153bdaa200a2b0f4315..248d2dc765a5c06c64ab3c27c47f38d36bf14c20 100644 (file)
@@ -374,6 +374,21 @@ static const struct driver_info cdc_mbim_info = {
        .tx_fixup = cdc_mbim_tx_fixup,
 };
 
+/* MBIM and NCM devices should not need a ZLP after NTBs with
+ * dwNtbOutMaxSize length. This driver_info is for the exceptional
+ * devices requiring it anyway, allowing them to be supported without
+ * forcing the performance penalty on all the sane devices.
+ */
+static const struct driver_info cdc_mbim_info_zlp = {
+       .description = "CDC MBIM",
+       .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP,
+       .bind = cdc_mbim_bind,
+       .unbind = cdc_mbim_unbind,
+       .manage_power = cdc_mbim_manage_power,
+       .rx_fixup = cdc_mbim_rx_fixup,
+       .tx_fixup = cdc_mbim_tx_fixup,
+};
+
 static const struct usb_device_id mbim_devs[] = {
        /* This duplicate NCM entry is intentional. MBIM devices can
         * be disguised as NCM by default, and this is necessary to
@@ -385,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = {
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info,
        },
+       /* Sierra Wireless MC7710 need ZLPs */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info_zlp,
+       },
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info,
        },
index 71b6e92b8e9b687c70d0eda9416f1e235a788747..00d3b2d37828f3f81afb6705965e80e128e7bb3d 100644 (file)
@@ -435,6 +435,13 @@ advance:
                len -= temp;
        }
 
+       /* some buggy devices have an IAD but no CDC Union */
+       if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
+               ctx->control = intf;
+               ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1);
+               dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n");
+       }
+
        /* check if we got everything */
        if ((ctx->control == NULL) || (ctx->data == NULL) ||
            ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
@@ -497,7 +504,8 @@ advance:
 error2:
        usb_set_intfdata(ctx->control, NULL);
        usb_set_intfdata(ctx->data, NULL);
-       usb_driver_release_interface(driver, ctx->data);
+       if (ctx->data != ctx->control)
+               usb_driver_release_interface(driver, ctx->data);
 error:
        cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
        dev->data[0] = 0;
@@ -1155,6 +1163,20 @@ static const struct driver_info wwan_info = {
        .tx_fixup = cdc_ncm_tx_fixup,
 };
 
+/* Same as wwan_info, but with FLAG_NOARP  */
+static const struct driver_info wwan_noarp_info = {
+       .description = "Mobile Broadband Network Device (NO ARP)",
+       .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+                       | FLAG_WWAN | FLAG_NOARP,
+       .bind = cdc_ncm_bind,
+       .unbind = cdc_ncm_unbind,
+       .check_connect = cdc_ncm_check_connect,
+       .manage_power = usbnet_manage_power,
+       .status = cdc_ncm_status,
+       .rx_fixup = cdc_ncm_rx_fixup,
+       .tx_fixup = cdc_ncm_tx_fixup,
+};
+
 static const struct usb_device_id cdc_devs[] = {
        /* Ericsson MBM devices like F5521gw */
        { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
@@ -1193,6 +1215,16 @@ static const struct usb_device_id cdc_devs[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
          .driver_info = (unsigned long)&wwan_info,
        },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
+       /* Infineon(now Intel) HSPA Modem platform */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
+               USB_CLASS_COMM,
+               USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&wwan_noarp_info,
+       },
 
        /* Generic CDC-NCM devices */
        { USB_INTERFACE_INFO(USB_CLASS_COMM,
index 3f554c1149f36d2cf3221ee38e4f02507d566ba7..d7e99445518eb5981d064a7378d7fcf02e4bf5cd 100644 (file)
 #define DM_MCAST_ADDR  0x16    /* 8 bytes */
 #define DM_GPR_CTRL    0x1e
 #define DM_GPR_DATA    0x1f
+#define DM_CHIP_ID     0x2c
+#define DM_MODE_CTRL   0x91    /* only on dm9620 */
+
+/* chip id values */
+#define ID_DM9601      0
+#define ID_DM9620      1
 
 #define DM_MAX_MCAST   64
 #define DM_MCAST_SIZE  8
@@ -53,7 +59,6 @@
 #define DM_RX_OVERHEAD 7       /* 3 byte header + 4 byte crc tail */
 #define DM_TIMEOUT     1000
 
-
 static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
        int err;
@@ -84,32 +89,23 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
 
 static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
 {
-       return usbnet_write_cmd(dev, DM_WRITE_REGS,
+       return usbnet_write_cmd(dev, DM_WRITE_REG,
                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                                value, reg, NULL, 0);
 }
 
-static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value,
-                                 u16 length, void *data)
+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
        usbnet_write_cmd_async(dev, DM_WRITE_REGS,
                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                              value, reg, data, length);
-}
-
-static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
-{
-       netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length);
-
-       dm_write_async_helper(dev, reg, 0, length, data);
+                              0, reg, data, length);
 }
 
 static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
 {
-       netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n",
-                  reg, value);
-
-       dm_write_async_helper(dev, reg, value, 0, NULL);
+       usbnet_write_cmd_async(dev, DM_WRITE_REG,
+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              value, reg, NULL, 0);
 }
 
 static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
@@ -358,7 +354,7 @@ static const struct net_device_ops dm9601_netdev_ops = {
 static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
-       u8 mac[ETH_ALEN];
+       u8 mac[ETH_ALEN], id;
 
        ret = usbnet_get_endpoints(dev, intf);
        if (ret)
@@ -399,6 +395,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
                __dm9601_set_mac_address(dev);
        }
 
+       if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) {
+               netdev_err(dev->net, "Error reading chip ID\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* put dm9620 devices in dm9601 mode */
+       if (id == ID_DM9620) {
+               u8 mode;
+
+               if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) {
+                       netdev_err(dev->net, "Error reading MODE_CTRL\n");
+                       ret = -ENODEV;
+                       goto out;
+               }
+               dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f);
+       }
+
        /* power up phy */
        dm_write_reg(dev, DM_GPR_CTRL, 1);
        dm_write_reg(dev, DM_GPR_DATA, 0);
@@ -581,6 +595,10 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9000),    /* DM9000E */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+        },
        {},                     // END
 };
 
index 91d7cb9728eb5998afc44c0bbaec395243524d01..19d903598b0dcf9d85097ed5a15d742bf0873566 100644 (file)
@@ -351,6 +351,10 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* HUAWEI_INTERFACE_NDIS_CONTROL_QUALCOMM */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 2. Combined interface devices matching on class+protocol */
        {       /* Huawei E367 and possibly others in "Windows mode" */
@@ -361,6 +365,14 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* HUAWEI_NDIS_SINGLE_INTERFACE_VDF */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x37),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* HUAWEI_INTERFACE_NDIS_HW_QUALCOMM */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x67),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
        {       /* Pantech UML290, P4200 and more */
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
@@ -399,6 +411,7 @@ static const struct usb_device_id products[] = {
        },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x0408, 0xea42, 4)},    /* Yota / Megafon M100-1 */
        {QMI_FIXED_INTF(0x12d1, 0x140c, 1)},    /* Huawei E173 */
        {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
        {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
@@ -433,6 +446,7 @@ static const struct usb_device_id products[] = {
        {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, 0x0265, 4)},    /* ONDA MT8205 4G LTE */
        {QMI_FIXED_INTF(0x19d2, 0x0284, 4)},    /* ZTE MF880 */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
@@ -458,6 +472,9 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 19)},   /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
+       {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
+       {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
+       {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index 3d4bf01641b49f0f7c5d820a547885806378c4e2..5e33606c136639f9b9ad7cf38e7ed8c48c7a51eb 100644 (file)
@@ -380,6 +380,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
        unsigned long           lockflags;
        size_t                  size = dev->rx_urb_size;
 
+       /* prevent rx skb allocation when error ratio is high */
+       if (test_bit(EVENT_RX_KILL, &dev->flags)) {
+               usb_free_urb(urb);
+               return -ENOLINK;
+       }
+
        skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
        if (!skb) {
                netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
@@ -539,6 +545,17 @@ block:
                break;
        }
 
+       /* stop rx if packet error rate is high */
+       if (++dev->pkt_cnt > 30) {
+               dev->pkt_cnt = 0;
+               dev->pkt_err = 0;
+       } else {
+               if (state == rx_cleanup)
+                       dev->pkt_err++;
+               if (dev->pkt_err > 20)
+                       set_bit(EVENT_RX_KILL, &dev->flags);
+       }
+
        state = defer_bh(dev, skb, &dev->rxq, state);
 
        if (urb) {
@@ -791,6 +808,11 @@ int usbnet_open (struct net_device *net)
                   (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" :
                   "simple");
 
+       /* reset rx error state */
+       dev->pkt_cnt = 0;
+       dev->pkt_err = 0;
+       clear_bit(EVENT_RX_KILL, &dev->flags);
+
        // delay posting reads until we're fully open
        tasklet_schedule (&dev->bh);
        if (info->manage_power) {
@@ -1103,13 +1125,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
        if (info->tx_fixup) {
                skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
                if (!skb) {
-                       if (netif_msg_tx_err(dev)) {
-                               netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
-                               goto drop;
-                       } else {
-                               /* cdc_ncm collected packet; waits for more */
+                       /* packet collected; minidriver waiting for more */
+                       if (info->flags & FLAG_MULTI_PACKET)
                                goto not_drop;
-                       }
+                       netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
+                       goto drop;
                }
        }
        length = skb->len;
@@ -1254,6 +1274,9 @@ static void usbnet_bh (unsigned long param)
                }
        }
 
+       /* restart RX again after disabling due to high error rate */
+       clear_bit(EVENT_RX_KILL, &dev->flags);
+
        // waiting for all pending urbs to complete?
        if (dev->wait) {
                if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
@@ -1448,6 +1471,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
                if ((dev->driver_info->flags & FLAG_WWAN) != 0)
                        strcpy(net->name, "wwan%d");
 
+               /* devices that cannot do ARP */
+               if ((dev->driver_info->flags & FLAG_NOARP) != 0)
+                       net->flags |= IFF_NOARP;
+
                /* maybe the remote can't receive an Ethernet MTU */
                if (net->mtu > (dev->hard_mtu - net->hard_header_len))
                        net->mtu = dev->hard_mtu - net->hard_header_len;
index a6fcf15adc4ff3d36d928f44cc0ac1f49d249820..35c00c5ea02adcbdf6f2855b7ee506544944843a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/scatterlist.h>
 #include <linux/if_vlan.h>
 #include <linux/slab.h>
+#include <linux/cpu.h>
 
 static int napi_weight = 128;
 module_param(napi_weight, int, 0444);
@@ -123,6 +124,12 @@ struct virtnet_info {
 
        /* Does the affinity hint is set for virtqueues? */
        bool affinity_hint_set;
+
+       /* Per-cpu variable to show the mapping from CPU to virtqueue */
+       int __percpu *vq_index;
+
+       /* CPU hot plug notifier */
+       struct notifier_block nb;
 };
 
 struct skb_vnet_hdr {
@@ -1013,32 +1020,75 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
        return 0;
 }
 
-static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
+static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu)
 {
        int i;
+       int cpu;
+
+       if (vi->affinity_hint_set) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       virtqueue_set_affinity(vi->rq[i].vq, -1);
+                       virtqueue_set_affinity(vi->sq[i].vq, -1);
+               }
+
+               vi->affinity_hint_set = false;
+       }
+
+       i = 0;
+       for_each_online_cpu(cpu) {
+               if (cpu == hcpu) {
+                       *per_cpu_ptr(vi->vq_index, cpu) = -1;
+               } else {
+                       *per_cpu_ptr(vi->vq_index, cpu) =
+                               ++i % vi->curr_queue_pairs;
+               }
+       }
+}
+
+static void virtnet_set_affinity(struct virtnet_info *vi)
+{
+       int i;
+       int cpu;
 
        /* In multiqueue mode, when the number of cpu is equal to the number of
         * queue pairs, we let the queue pairs to be private to one cpu by
         * setting the affinity hint to eliminate the contention.
         */
-       if ((vi->curr_queue_pairs == 1 ||
-            vi->max_queue_pairs != num_online_cpus()) && set) {
-               if (vi->affinity_hint_set)
-                       set = false;
-               else
-                       return;
+       if (vi->curr_queue_pairs == 1 ||
+           vi->max_queue_pairs != num_online_cpus()) {
+               virtnet_clean_affinity(vi, -1);
+               return;
        }
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               int cpu = set ? i : -1;
+       i = 0;
+       for_each_online_cpu(cpu) {
                virtqueue_set_affinity(vi->rq[i].vq, cpu);
                virtqueue_set_affinity(vi->sq[i].vq, cpu);
+               *per_cpu_ptr(vi->vq_index, cpu) = i;
+               i++;
        }
 
-       if (set)
-               vi->affinity_hint_set = true;
-       else
-               vi->affinity_hint_set = false;
+       vi->affinity_hint_set = true;
+}
+
+static int virtnet_cpu_callback(struct notifier_block *nfb,
+                               unsigned long action, void *hcpu)
+{
+       struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb);
+
+       switch(action & ~CPU_TASKS_FROZEN) {
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+       case CPU_DEAD:
+               virtnet_set_affinity(vi);
+               break;
+       case CPU_DOWN_PREPARE:
+               virtnet_clean_affinity(vi, (long)hcpu);
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
 }
 
 static void virtnet_get_ringparam(struct net_device *dev,
@@ -1082,13 +1132,15 @@ static int virtnet_set_channels(struct net_device *dev,
        if (queue_pairs > vi->max_queue_pairs)
                return -EINVAL;
 
+       get_online_cpus();
        err = virtnet_set_queues(vi, queue_pairs);
        if (!err) {
                netif_set_real_num_tx_queues(dev, queue_pairs);
                netif_set_real_num_rx_queues(dev, queue_pairs);
 
-               virtnet_set_affinity(vi, true);
+               virtnet_set_affinity(vi);
        }
+       put_online_cpus();
 
        return err;
 }
@@ -1127,12 +1179,19 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
 
 /* To avoid contending a lock hold by a vcpu who would exit to host, select the
  * txq based on the processor id.
- * TODO: handle cpu hotplug.
  */
 static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
-       int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
-                 smp_processor_id();
+       int txq;
+       struct virtnet_info *vi = netdev_priv(dev);
+
+       if (skb_rx_queue_recorded(skb)) {
+               txq = skb_get_rx_queue(skb);
+       } else {
+               txq = *__this_cpu_ptr(vi->vq_index);
+               if (txq == -1)
+                       txq = 0;
+       }
 
        while (unlikely(txq >= dev->real_num_tx_queues))
                txq -= dev->real_num_tx_queues;
@@ -1248,7 +1307,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi)
 {
        struct virtio_device *vdev = vi->vdev;
 
-       virtnet_set_affinity(vi, false);
+       virtnet_clean_affinity(vi, -1);
 
        vdev->config->del_vqs(vdev);
 
@@ -1371,7 +1430,10 @@ static int init_vqs(struct virtnet_info *vi)
        if (ret)
                goto err_free;
 
-       virtnet_set_affinity(vi, true);
+       get_online_cpus();
+       virtnet_set_affinity(vi);
+       put_online_cpus();
+
        return 0;
 
 err_free:
@@ -1453,6 +1515,10 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->stats == NULL)
                goto free;
 
+       vi->vq_index = alloc_percpu(int);
+       if (vi->vq_index == NULL)
+               goto free_stats;
+
        mutex_init(&vi->config_lock);
        vi->config_enable = true;
        INIT_WORK(&vi->config_work, virtnet_config_changed_work);
@@ -1476,7 +1542,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* Allocate/initialize the rx/tx queues, and invoke find_vqs */
        err = init_vqs(vi);
        if (err)
-               goto free_stats;
+               goto free_index;
 
        netif_set_real_num_tx_queues(dev, 1);
        netif_set_real_num_rx_queues(dev, 1);
@@ -1499,6 +1565,13 @@ static int virtnet_probe(struct virtio_device *vdev)
                }
        }
 
+       vi->nb.notifier_call = &virtnet_cpu_callback;
+       err = register_hotcpu_notifier(&vi->nb);
+       if (err) {
+               pr_debug("virtio_net: registering cpu notifier failed\n");
+               goto free_recv_bufs;
+       }
+
        /* Assume link up if device can't report link status,
           otherwise get link status from config. */
        if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
@@ -1520,6 +1593,8 @@ free_recv_bufs:
 free_vqs:
        cancel_delayed_work_sync(&vi->refill);
        virtnet_del_vqs(vi);
+free_index:
+       free_percpu(vi->vq_index);
 free_stats:
        free_percpu(vi->stats);
 free:
@@ -1543,6 +1618,8 @@ static void virtnet_remove(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
 
+       unregister_hotcpu_notifier(&vi->nb);
+
        /* Prevent config work handler from accessing the device. */
        mutex_lock(&vi->config_lock);
        vi->config_enable = false;
@@ -1554,6 +1631,7 @@ static void virtnet_remove(struct virtio_device *vdev)
 
        flush_work(&vi->config_work);
 
+       free_percpu(vi->vq_index);
        free_percpu(vi->stats);
        free_netdev(vi->dev);
 }
index dc8913c6238c965b0905ef7ad6784bf669f06388..12c6440d16499ebd4a1faaa4e07edc8658b5f198 100644 (file)
@@ -154,8 +154,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
        if (ret & 1) { /* Link is up. */
                printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",
                       adapter->netdev->name, adapter->link_speed);
-               if (!netif_carrier_ok(adapter->netdev))
-                       netif_carrier_on(adapter->netdev);
+               netif_carrier_on(adapter->netdev);
 
                if (affectTxQueue) {
                        for (i = 0; i < adapter->num_tx_queues; i++)
@@ -165,8 +164,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
        } else {
                printk(KERN_INFO "%s: NIC Link is Down\n",
                       adapter->netdev->name);
-               if (netif_carrier_ok(adapter->netdev))
-                       netif_carrier_off(adapter->netdev);
+               netif_carrier_off(adapter->netdev);
 
                if (affectTxQueue) {
                        for (i = 0; i < adapter->num_tx_queues; i++)
@@ -3061,6 +3059,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
        netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
        netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
 
+       netif_carrier_off(netdev);
        err = register_netdev(netdev);
 
        if (err) {
index 3b3fdf648ea741267800a2b49eee87d835d2370a..656230e0d18c7bb1f79892910c56a341f856d862 100644 (file)
@@ -505,7 +505,8 @@ static int vxlan_join_group(struct net_device *dev)
        struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct sock *sk = vn->sock->sk;
        struct ip_mreqn mreq = {
-               .imr_multiaddr.s_addr = vxlan->gaddr,
+               .imr_multiaddr.s_addr   = vxlan->gaddr,
+               .imr_ifindex            = vxlan->link,
        };
        int err;
 
@@ -532,7 +533,8 @@ static int vxlan_leave_group(struct net_device *dev)
        int err = 0;
        struct sock *sk = vn->sock->sk;
        struct ip_mreqn mreq = {
-               .imr_multiaddr.s_addr = vxlan->gaddr,
+               .imr_multiaddr.s_addr   = vxlan->gaddr,
+               .imr_ifindex            = vxlan->link,
        };
 
        /* Only leave group when last vxlan is done. */
@@ -1189,6 +1191,7 @@ static void vxlan_setup(struct net_device *dev)
 
        dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
        spin_lock_init(&vxlan->hash_lock);
 
index 1a67a4f829fe9f3fca15a6ad3533e335bec70a25..2c02b4e84094d32fc5605deaebb0ed148087fbf5 100644 (file)
@@ -30,5 +30,6 @@ source "drivers/net/wireless/ath/ath9k/Kconfig"
 source "drivers/net/wireless/ath/carl9170/Kconfig"
 source "drivers/net/wireless/ath/ath6kl/Kconfig"
 source "drivers/net/wireless/ath/ar5523/Kconfig"
+source "drivers/net/wireless/ath/wil6210/Kconfig"
 
 endif
index 1e18621326dc2fc5c70335e43e4e781436820a84..97b964ded2bef25e4218cc3843377ada32732077 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATH9K_HW)          += ath9k/
 obj-$(CONFIG_CARL9170)         += carl9170/
 obj-$(CONFIG_ATH6KL)           += ath6kl/
 obj-$(CONFIG_AR5523)           += ar5523/
+obj-$(CONFIG_WIL6210)          += wil6210/
 
 obj-$(CONFIG_ATH_COMMON)       += ath.o
 
index 5fc15bf8be09449cffe2a7b19a47843ad615af7b..7647ed6b73d770278ca63875c314bcce9f98ddf2 100644 (file)
@@ -2,6 +2,7 @@ config ATH9K_HW
        tristate
 config ATH9K_COMMON
        tristate
+       select ATH_COMMON
 config ATH9K_DFS_DEBUGFS
        def_bool y
        depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED
@@ -17,7 +18,6 @@ config ATH9K_BTCOEX_SUPPORT
 config ATH9K
        tristate "Atheros 802.11n wireless cards support"
        depends on MAC80211
-       select ATH_COMMON
        select ATH9K_HW
        select MAC80211_LEDS
        select LEDS_CLASS
@@ -56,7 +56,8 @@ config ATH9K_AHB
 
 config ATH9K_DEBUGFS
        bool "Atheros ath9k debugging"
-       depends on ATH9K && DEBUG_FS
+       depends on ATH9K
+       select MAC80211_DEBUGFS
        ---help---
          Say Y, if you need access to ath9k's statistics for
          interrupts, rate control, etc.
index 8b0d8dcd76255239e7451b4a1258adca79ef8342..56317b0fb6b692f3f9ae20b8ba681ec18371788f 100644 (file)
@@ -976,6 +976,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
                                          AR_PHY_CL_TAB_1,
                                          AR_PHY_CL_TAB_2 };
 
+       ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+
        if (rtt) {
                if (!ar9003_hw_rtt_restore(ah, chan))
                        run_rtt_cal = true;
index 74fd3977feeb845adf93f6ed0fd650d506ca2ee1..59bf5f31e212c07bfef14251384aa3f5d2de0c8b 100644 (file)
@@ -544,7 +544,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
                                ar9340Common_rx_gain_table_1p0);
        else if (AR_SREV_9485_11(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                               ar9485Common_wo_xlna_rx_gain_1_1);
+                              ar9485_common_rx_gain_1_1);
        else if (AR_SREV_9550(ah)) {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                                ar955x_1p0_common_rx_gain_table);
index ce19c09fa8e84aec2877e2f14861b0284f4d958e..3afc24bde6d65d88a0d469abb0ef73d93856edcb 100644 (file)
@@ -586,32 +586,19 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
        ath9k_hw_synth_delay(ah, chan, synthDelay);
 }
 
-static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 {
-       switch (rx) {
-       case 0x5:
+       if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5)
                REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
                            AR_PHY_SWAP_ALT_CHAIN);
-       case 0x3:
-       case 0x1:
-       case 0x2:
-       case 0x7:
-               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
-               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
-               break;
-       default:
-               break;
-       }
+
+       REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+       REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
 
        if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
-               REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
-       else
-               REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+               tx = 3;
 
-       if (tx == 0x5) {
-               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-                           AR_PHY_SWAP_ALT_CHAIN);
-       }
+       REG_WRITE(ah, AR_SELFGEN_MASK, tx);
 }
 
 /*
index 86e26a19efdac1923395543c1a50fb53a6cb8958..42794c546a4068ac91b47c1252153b9040362555 100644 (file)
@@ -317,7 +317,6 @@ struct ath_rx {
        u32 *rxlink;
        u32 num_pkts;
        unsigned int rxfilter;
-       spinlock_t rxbuflock;
        struct list_head rxbuf;
        struct ath_descdma rxdma;
        struct ath_buf *rx_bufptr;
@@ -328,7 +327,6 @@ struct ath_rx {
 
 int ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
-void ath_flushrecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
 int ath_rx_init(struct ath_softc *sc, int nbufs);
 void ath_rx_cleanup(struct ath_softc *sc);
@@ -646,7 +644,6 @@ void ath_ant_comb_update(struct ath_softc *sc);
 enum sc_op_flags {
        SC_OP_INVALID,
        SC_OP_BEACONS,
-       SC_OP_RXFLUSH,
        SC_OP_ANI_RUN,
        SC_OP_PRIM_STA_VIF,
        SC_OP_HW_RESET,
index 531fffd801a34eaa11b8d483aca51ac07e7a7fab..2ca355e94da65467e36595990423c80be1b897b6 100644 (file)
@@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
                                 skb->len, DMA_TO_DEVICE);
                dev_kfree_skb_any(skb);
                bf->bf_buf_addr = 0;
+               bf->bf_mpdu = NULL;
        }
 
        skb = ieee80211_beacon_get(hw, vif);
@@ -359,7 +360,6 @@ void ath9k_beacon_tasklet(unsigned long data)
                return;
 
        bf = ath9k_beacon_generate(sc->hw, vif);
-       WARN_ON(!bf);
 
        if (sc->beacon.bmisscnt != 0) {
                ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
index 13ff9edc24015e5e2126fc4f6c7fde8dcb003c90..e585fc827c50b2e9d5ff2fe08afb15cd49cedba6 100644 (file)
@@ -861,7 +861,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
        RXS_ERR("RX-LENGTH-ERR", rx_len_err);
        RXS_ERR("RX-OOM-ERR", rx_oom_err);
        RXS_ERR("RX-RATE-ERR", rx_rate_err);
-       RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush);
        RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err);
 
        PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
index 375c3b46411eee6cd140dbc22e6e435fe0e32ad9..6df2ab62dcb706df5bef4a8afdf04593651f111a 100644 (file)
@@ -216,7 +216,6 @@ struct ath_tx_stats {
  * @rx_oom_err:  No. of frames dropped due to OOM issues.
  * @rx_rate_err:  No. of frames dropped due to rate errors.
  * @rx_too_many_frags_err:  Frames dropped due to too-many-frags received.
- * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH.
  * @rx_beacons:  No. of beacons received.
  * @rx_frags:  No. of rx-fragements received.
  */
@@ -235,7 +234,6 @@ struct ath_rx_stats {
        u32 rx_oom_err;
        u32 rx_rate_err;
        u32 rx_too_many_frags_err;
-       u32 rx_drop_rxflush;
        u32 rx_beacons;
        u32 rx_frags;
 };
index 4a9570dfba72605d2f492ddf51cde8e8e7db835b..aac4a406a5134727e49fef2999e563e39169d83f 100644 (file)
@@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
                        endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
                                                  skb, htc_hdr->endpoint_id,
                                                  txok);
+               } else {
+                       kfree_skb(skb);
                }
        }
 
index 7f1a8e91c908c2dea314a7171e1d1d59139e6c6a..9d26fc56ca56a6bf7d4e8ac0ed91366df0de50cd 100644 (file)
@@ -1066,6 +1066,7 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
 int ar9003_paprd_init_table(struct ath_hw *ah);
 bool ar9003_paprd_is_done(struct ath_hw *ah);
 bool ar9003_is_paprd_enabled(struct ath_hw *ah);
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 
 /* Hardware family op attach helpers */
 void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
index be30a9af152884d8e073b7a3be5b79e6b3d5a8ee..dd91f8fdc01c3ea44c922bbbbd14bee2df4fd6db 100644 (file)
@@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc)
        ath_start_ani(sc);
 }
 
-static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hw *ah = sc->sc_ah;
        bool ret = true;
@@ -202,14 +202,6 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
        if (!ath_drain_all_txq(sc, retry_tx))
                ret = false;
 
-       if (!flush) {
-               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-                       ath_rx_tasklet(sc, 1, true);
-               ath_rx_tasklet(sc, 1, false);
-       } else {
-               ath_flushrecv(sc);
-       }
-
        return ret;
 }
 
@@ -262,11 +254,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_hw_cal_data *caldata = NULL;
        bool fastcc = true;
-       bool flush = false;
        int r;
 
        __ath_cancel_work(sc);
 
+       tasklet_disable(&sc->intr_tq);
        spin_lock_bh(&sc->sc_pcu_lock);
 
        if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
@@ -276,11 +268,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
 
        if (!hchan) {
                fastcc = false;
-               flush = true;
                hchan = ah->curchan;
        }
 
-       if (!ath_prepare_reset(sc, retry_tx, flush))
+       if (!ath_prepare_reset(sc, retry_tx))
                fastcc = false;
 
        ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
@@ -302,6 +293,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
 
 out:
        spin_unlock_bh(&sc->sc_pcu_lock);
+       tasklet_enable(&sc->intr_tq);
+
        return r;
 }
 
@@ -804,7 +797,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
                ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
        }
 
-       ath_prepare_reset(sc, false, true);
+       ath_prepare_reset(sc, false);
 
        if (sc->rx.frag) {
                dev_kfree_skb_any(sc->rx.frag);
@@ -1833,6 +1826,9 @@ static u32 fill_chainmask(u32 cap, u32 new)
 
 static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
 {
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               return true;
+
        switch (val & 0x7) {
        case 0x1:
        case 0x3:
index d4df98a938bf4755d1af6238d41e5df0753970c6..90752f2469704bbbb2bf7cae86a1c2cb4029435a 100644 (file)
@@ -254,8 +254,6 @@ rx_init_fail:
 
 static void ath_edma_start_recv(struct ath_softc *sc)
 {
-       spin_lock_bh(&sc->rx.rxbuflock);
-
        ath9k_hw_rxena(sc->sc_ah);
 
        ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
@@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc)
        ath_opmode_init(sc);
 
        ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
-
-       spin_unlock_bh(&sc->rx.rxbuflock);
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -285,8 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
        int error = 0;
 
        spin_lock_init(&sc->sc_pcu_lock);
-       spin_lock_init(&sc->rx.rxbuflock);
-       clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
 
        common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
                             sc->sc_ah->caps.rx_status_len;
@@ -447,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc)
                return 0;
        }
 
-       spin_lock_bh(&sc->rx.rxbuflock);
        if (list_empty(&sc->rx.rxbuf))
                goto start_recv;
 
@@ -468,26 +461,31 @@ start_recv:
        ath_opmode_init(sc);
        ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
 
-       spin_unlock_bh(&sc->rx.rxbuflock);
-
        return 0;
 }
 
+static void ath_flushrecv(struct ath_softc *sc)
+{
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+               ath_rx_tasklet(sc, 1, true);
+       ath_rx_tasklet(sc, 1, false);
+}
+
 bool ath_stoprecv(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
        bool stopped, reset = false;
 
-       spin_lock_bh(&sc->rx.rxbuflock);
        ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
        stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
+       ath_flushrecv(sc);
+
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
                ath_edma_stop_recv(sc);
        else
                sc->rx.rxlink = NULL;
-       spin_unlock_bh(&sc->rx.rxbuflock);
 
        if (!(ah->ah_flags & AH_UNPLUGGED) &&
            unlikely(!stopped)) {
@@ -499,15 +497,6 @@ bool ath_stoprecv(struct ath_softc *sc)
        return stopped && !reset;
 }
 
-void ath_flushrecv(struct ath_softc *sc)
-{
-       set_bit(SC_OP_RXFLUSH, &sc->sc_flags);
-       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-               ath_rx_tasklet(sc, 1, true);
-       ath_rx_tasklet(sc, 1, false);
-       clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
-}
-
 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
 {
        /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
@@ -744,6 +733,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
                        return NULL;
        }
 
+       list_del(&bf->list);
        if (!bf->bf_mpdu)
                return bf;
 
@@ -1059,16 +1049,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                dma_type = DMA_FROM_DEVICE;
 
        qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
-       spin_lock_bh(&sc->rx.rxbuflock);
 
        tsf = ath9k_hw_gettsf64(ah);
        tsf_lower = tsf & 0xffffffff;
 
        do {
                bool decrypt_error = false;
-               /* If handling rx interrupt and flush is in progress => exit */
-               if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))
-                       break;
 
                memset(&rs, 0, sizeof(rs));
                if (edma)
@@ -1111,15 +1097,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 
                ath_debug_stat_rx(sc, &rs);
 
-               /*
-                * If we're asked to flush receive queue, directly
-                * chain it back at the queue without processing it.
-                */
-               if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) {
-                       RX_STAT_INC(rx_drop_rxflush);
-                       goto requeue_drop_frag;
-               }
-
                memset(rxs, 0, sizeof(struct ieee80211_rx_status));
 
                rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
@@ -1254,19 +1231,18 @@ requeue_drop_frag:
                        sc->rx.frag = NULL;
                }
 requeue:
+               list_add_tail(&bf->list, &sc->rx.rxbuf);
+               if (flush)
+                       continue;
+
                if (edma) {
-                       list_add_tail(&bf->list, &sc->rx.rxbuf);
                        ath_rx_edma_buf_link(sc, qtype);
                } else {
-                       list_move_tail(&bf->list, &sc->rx.rxbuf);
                        ath_rx_buf_link(sc, bf);
-                       if (!flush)
-                               ath9k_hw_rxena(ah);
+                       ath9k_hw_rxena(ah);
                }
        } while (1);
 
-       spin_unlock_bh(&sc->rx.rxbuflock);
-
        if (!(ah->imask & ATH9K_INT_RXEOL)) {
                ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
                ath9k_hw_set_interrupts(ah);
index aaebecd19e5975f449bdd73bcc9c73411b6f37af..63fd9af3fd39dd2c1d7ddb183902ae5e587b1ada 100644 (file)
@@ -336,8 +336,12 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
                if (SUPP(CARL9170FW_WLANTX_CAB)) {
                        if_comb_types |=
                                BIT(NL80211_IFTYPE_AP) |
-                               BIT(NL80211_IFTYPE_MESH_POINT) |
                                BIT(NL80211_IFTYPE_P2P_GO);
+
+#ifdef CONFIG_MAC80211_MESH
+                       if_comb_types |=
+                               BIT(NL80211_IFTYPE_MESH_POINT);
+#endif /* CONFIG_MAC80211_MESH */
                }
        }
 
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig
new file mode 100644 (file)
index 0000000..bac3d98
--- /dev/null
@@ -0,0 +1,29 @@
+config WIL6210
+       tristate "Wilocity 60g WiFi card wil6210 support"
+       depends on CFG80211
+       depends on PCI
+       default n
+       ---help---
+         This module adds support for wireless adapter based on
+         wil6210 chip by Wilocity. It supports operation on the
+         60 GHz band, covered by the IEEE802.11ad standard.
+
+         http://wireless.kernel.org/en/users/Drivers/wil6210
+
+         If you choose to build it as a module, it will be called
+         wil6210
+
+config WIL6210_ISR_COR
+       bool "Use Clear-On-Read mode for ISR registers for wil6210"
+       depends on WIL6210
+       default y
+       ---help---
+         ISR registers on wil6210 chip may operate in either
+         COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode.
+         For production code, use COR (say y); is default since
+         it saves extra target transaction;
+         For ISR debug, use W1C (say n); is allows to monitor ISR
+         registers with debugfs. If COR were used, ISR would
+         self-clear when accessed for debug purposes, it makes
+         such monitoring impossible.
+         Say y unless you debug interrupts
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
new file mode 100644 (file)
index 0000000..9396dc9
--- /dev/null
@@ -0,0 +1,13 @@
+obj-$(CONFIG_WIL6210) += wil6210.o
+
+wil6210-objs := main.o
+wil6210-objs += netdev.o
+wil6210-objs += cfg80211.o
+wil6210-objs += pcie_bus.o
+wil6210-objs += debugfs.o
+wil6210-objs += wmi.o
+wil6210-objs += interrupt.o
+wil6210-objs += txrx.o
+
+subdir-ccflags-y += -Werror
+subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
new file mode 100644 (file)
index 0000000..116f4e8
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <net/cfg80211.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+
+#define CHAN60G(_channel, _flags) {                            \
+       .band                   = IEEE80211_BAND_60GHZ,         \
+       .center_freq            = 56160 + (2160 * (_channel)),  \
+       .hw_value               = (_channel),                   \
+       .flags                  = (_flags),                     \
+       .max_antenna_gain       = 0,                            \
+       .max_power              = 40,                           \
+}
+
+static struct ieee80211_channel wil_60ghz_channels[] = {
+       CHAN60G(1, 0),
+       CHAN60G(2, 0),
+       CHAN60G(3, 0),
+/* channel 4 not supported yet */
+};
+
+static struct ieee80211_supported_band wil_band_60ghz = {
+       .channels = wil_60ghz_channels,
+       .n_channels = ARRAY_SIZE(wil_60ghz_channels),
+       .ht_cap = {
+               .ht_supported = true,
+               .cap = 0, /* TODO */
+               .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */
+               .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */
+               .mcs = {
+                               /* MCS 1..12 - SC PHY */
+                       .rx_mask = {0xfe, 0x1f}, /* 1..12 */
+                       .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */
+               },
+       },
+};
+
+static const struct ieee80211_txrx_stypes
+wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+       [NL80211_IFTYPE_STATION] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+       },
+       [NL80211_IFTYPE_AP] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+       },
+       [NL80211_IFTYPE_P2P_CLIENT] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+       },
+       [NL80211_IFTYPE_P2P_GO] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+       },
+};
+
+static const u32 wil_cipher_suites[] = {
+       WLAN_CIPHER_SUITE_GCMP,
+};
+
+int wil_iftype_nl2wmi(enum nl80211_iftype type)
+{
+       static const struct {
+               enum nl80211_iftype nl;
+               enum wmi_network_type wmi;
+       } __nl2wmi[] = {
+               {NL80211_IFTYPE_ADHOC,          WMI_NETTYPE_ADHOC},
+               {NL80211_IFTYPE_STATION,        WMI_NETTYPE_INFRA},
+               {NL80211_IFTYPE_AP,             WMI_NETTYPE_AP},
+               {NL80211_IFTYPE_P2P_CLIENT,     WMI_NETTYPE_P2P},
+               {NL80211_IFTYPE_P2P_GO,         WMI_NETTYPE_P2P},
+               {NL80211_IFTYPE_MONITOR,        WMI_NETTYPE_ADHOC}, /* FIXME */
+       };
+       uint i;
+
+       for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) {
+               if (__nl2wmi[i].nl == type)
+                       return __nl2wmi[i].wmi;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static int wil_cfg80211_get_station(struct wiphy *wiphy,
+                                   struct net_device *ndev,
+                                   u8 *mac, struct station_info *sinfo)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       int rc;
+       struct wmi_notify_req_cmd cmd = {
+               .cid = 0,
+               .interval_usec = 0,
+       };
+
+       if (memcmp(mac, wil->dst_addr[0], ETH_ALEN))
+               return -ENOENT;
+
+       /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */
+       rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
+                     WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20);
+       if (rc)
+               return rc;
+
+       sinfo->generation = wil->sinfo_gen;
+
+       sinfo->filled |= STATION_INFO_TX_BITRATE;
+       sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
+       sinfo->txrate.mcs = wil->stats.bf_mcs;
+       sinfo->filled |= STATION_INFO_RX_BITRATE;
+       sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
+       sinfo->rxrate.mcs = wil->stats.last_mcs_rx;
+
+       if (test_bit(wil_status_fwconnected, &wil->status)) {
+               sinfo->filled |= STATION_INFO_SIGNAL;
+               sinfo->signal = 12; /* TODO: provide real value */
+       }
+
+       return 0;
+}
+
+static int wil_cfg80211_change_iface(struct wiphy *wiphy,
+                                    struct net_device *ndev,
+                                    enum nl80211_iftype type, u32 *flags,
+                                    struct vif_params *params)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct wireless_dev *wdev = wil->wdev;
+
+       switch (type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_GO:
+               break;
+       case NL80211_IFTYPE_MONITOR:
+               if (flags)
+                       wil->monitor_flags = *flags;
+               else
+                       wil->monitor_flags = 0;
+
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       wdev->iftype = type;
+
+       return 0;
+}
+
+static int wil_cfg80211_scan(struct wiphy *wiphy,
+                            struct cfg80211_scan_request *request)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct wireless_dev *wdev = wil->wdev;
+       struct {
+               struct wmi_start_scan_cmd cmd;
+               u16 chnl[4];
+       } __packed cmd;
+       uint i, n;
+
+       if (wil->scan_request) {
+               wil_err(wil, "Already scanning\n");
+               return -EAGAIN;
+       }
+
+       /* check we are client side */
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_P2P_CLIENT:
+               break;
+       default:
+               return -EOPNOTSUPP;
+
+       }
+
+       /* FW don't support scan after connection attempt */
+       if (test_bit(wil_status_dontscan, &wil->status)) {
+               wil_err(wil, "Scan after connect attempt not supported\n");
+               return -EBUSY;
+       }
+
+       wil->scan_request = request;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.cmd.num_channels = 0;
+       n = min(request->n_channels, 4U);
+       for (i = 0; i < n; i++) {
+               int ch = request->channels[i]->hw_value;
+               if (ch == 0) {
+                       wil_err(wil,
+                               "Scan requested for unknown frequency %dMhz\n",
+                               request->channels[i]->center_freq);
+                       continue;
+               }
+               /* 0-based channel indexes */
+               cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
+               wil_dbg(wil, "Scan for ch %d  : %d MHz\n", ch,
+                       request->channels[i]->center_freq);
+       }
+
+       return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
+                       cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
+}
+
+static int wil_cfg80211_connect(struct wiphy *wiphy,
+                               struct net_device *ndev,
+                               struct cfg80211_connect_params *sme)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct cfg80211_bss *bss;
+       struct wmi_connect_cmd conn;
+       const u8 *ssid_eid;
+       const u8 *rsn_eid;
+       int ch;
+       int rc = 0;
+
+       bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
+                              sme->ssid, sme->ssid_len,
+                              WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+       if (!bss) {
+               wil_err(wil, "Unable to find BSS\n");
+               return -ENOENT;
+       }
+
+       ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
+       if (!ssid_eid) {
+               wil_err(wil, "No SSID\n");
+               rc = -ENOENT;
+               goto out;
+       }
+
+       rsn_eid = sme->ie ?
+                       cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
+                       NULL;
+       if (rsn_eid) {
+               if (sme->ie_len > WMI_MAX_IE_LEN) {
+                       rc = -ERANGE;
+                       wil_err(wil, "IE too large (%td bytes)\n",
+                               sme->ie_len);
+                       goto out;
+               }
+               /*
+                * For secure assoc, send:
+                * (1) WMI_DELETE_CIPHER_KEY_CMD
+                * (2) WMI_SET_APPIE_CMD
+                */
+               rc = wmi_del_cipher_key(wil, 0, bss->bssid);
+               if (rc) {
+                       wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n");
+                       goto out;
+               }
+               /* WMI_SET_APPIE_CMD */
+               rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
+               if (rc) {
+                       wil_err(wil, "WMI_SET_APPIE_CMD failed\n");
+                       goto out;
+               }
+       }
+
+       /* WMI_CONNECT_CMD */
+       memset(&conn, 0, sizeof(conn));
+       switch (bss->capability & 0x03) {
+       case WLAN_CAPABILITY_DMG_TYPE_AP:
+               conn.network_type = WMI_NETTYPE_INFRA;
+               break;
+       case WLAN_CAPABILITY_DMG_TYPE_PBSS:
+               conn.network_type = WMI_NETTYPE_P2P;
+               break;
+       default:
+               wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
+                       bss->capability);
+               goto out;
+       }
+       if (rsn_eid) {
+               conn.dot11_auth_mode = WMI_AUTH11_SHARED;
+               conn.auth_mode = WMI_AUTH_WPA2_PSK;
+               conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
+               conn.pairwise_crypto_len = 16;
+       } else {
+               conn.dot11_auth_mode = WMI_AUTH11_OPEN;
+               conn.auth_mode = WMI_AUTH_NONE;
+       }
+
+       conn.ssid_len = min_t(u8, ssid_eid[1], 32);
+       memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
+
+       ch = bss->channel->hw_value;
+       if (ch == 0) {
+               wil_err(wil, "BSS at unknown frequency %dMhz\n",
+                       bss->channel->center_freq);
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+       conn.channel = ch - 1;
+
+       memcpy(conn.bssid, bss->bssid, 6);
+       memcpy(conn.dst_mac, bss->bssid, 6);
+       /*
+        * FW don't support scan after connection attempt
+        */
+       set_bit(wil_status_dontscan, &wil->status);
+
+       rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
+       if (rc == 0) {
+               /* Connect can take lots of time */
+               mod_timer(&wil->connect_timer,
+                         jiffies + msecs_to_jiffies(2000));
+       }
+
+ out:
+       cfg80211_put_bss(bss);
+
+       return rc;
+}
+
+static int wil_cfg80211_disconnect(struct wiphy *wiphy,
+                                  struct net_device *ndev,
+                                  u16 reason_code)
+{
+       int rc;
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
+
+       return rc;
+}
+
+static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+                                   struct cfg80211_chan_def *chandef)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct wireless_dev *wdev = wil->wdev;
+
+       wdev->preset_chandef = *chandef;
+
+       return 0;
+}
+
+static int wil_cfg80211_add_key(struct wiphy *wiphy,
+                               struct net_device *ndev,
+                               u8 key_index, bool pairwise,
+                               const u8 *mac_addr,
+                               struct key_params *params)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       /* group key is not used */
+       if (!pairwise)
+               return 0;
+
+       return wmi_add_cipher_key(wil, key_index, mac_addr,
+                                 params->key_len, params->key);
+}
+
+static int wil_cfg80211_del_key(struct wiphy *wiphy,
+                               struct net_device *ndev,
+                               u8 key_index, bool pairwise,
+                               const u8 *mac_addr)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       /* group key is not used */
+       if (!pairwise)
+               return 0;
+
+       return wmi_del_cipher_key(wil, key_index, mac_addr);
+}
+
+/* Need to be present or wiphy_new() will WARN */
+static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
+                                       struct net_device *ndev,
+                                       u8 key_index, bool unicast,
+                                       bool multicast)
+{
+       return 0;
+}
+
+static int wil_cfg80211_start_ap(struct wiphy *wiphy,
+                                struct net_device *ndev,
+                                struct cfg80211_ap_settings *info)
+{
+       int rc = 0;
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct wireless_dev *wdev = ndev->ieee80211_ptr;
+       struct ieee80211_channel *channel = info->chandef.chan;
+       struct cfg80211_beacon_data *bcon = &info->beacon;
+       u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+       if (!channel) {
+               wil_err(wil, "AP: No channel???\n");
+               return -EINVAL;
+       }
+
+       wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
+               channel->center_freq, info->privacy ? "secure" : "open");
+       print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
+                            info->ssid, info->ssid_len);
+
+       rc = wil_reset(wil);
+       if (rc)
+               return rc;
+
+       rc = wmi_set_ssid(wil, info->ssid_len, info->ssid);
+       if (rc)
+               return rc;
+
+       rc = wmi_set_channel(wil, channel->hw_value);
+       if (rc)
+               return rc;
+
+       /* MAC address - pre-requisite for other commands */
+       wmi_set_mac_address(wil, ndev->dev_addr);
+
+       /* IE's */
+       /* bcon 'head IE's are not relevant for 60g band */
+       wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
+                  bcon->beacon_ies);
+       wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len,
+                  bcon->proberesp_ies);
+       wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
+                  bcon->assocresp_ies);
+
+       wil->secure_pcp = info->privacy;
+
+       rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype);
+       if (rc)
+               return rc;
+
+       /* Rx VRING. After MAC and beacon */
+       rc = wil_rx_init(wil);
+
+       netif_carrier_on(ndev);
+
+       return rc;
+}
+
+static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
+                               struct net_device *ndev)
+{
+       int rc = 0;
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct wireless_dev *wdev = ndev->ieee80211_ptr;
+       u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+       /* To stop beaconing, set BI to 0 */
+       rc = wmi_set_bcon(wil, 0, wmi_nettype);
+
+       return rc;
+}
+
+static struct cfg80211_ops wil_cfg80211_ops = {
+       .scan = wil_cfg80211_scan,
+       .connect = wil_cfg80211_connect,
+       .disconnect = wil_cfg80211_disconnect,
+       .change_virtual_intf = wil_cfg80211_change_iface,
+       .get_station = wil_cfg80211_get_station,
+       .set_monitor_channel = wil_cfg80211_set_channel,
+       .add_key = wil_cfg80211_add_key,
+       .del_key = wil_cfg80211_del_key,
+       .set_default_key = wil_cfg80211_set_default_key,
+       /* AP mode */
+       .start_ap = wil_cfg80211_start_ap,
+       .stop_ap = wil_cfg80211_stop_ap,
+};
+
+static void wil_wiphy_init(struct wiphy *wiphy)
+{
+       /* TODO: set real value */
+       wiphy->max_scan_ssids = 10;
+       wiphy->max_num_pmkids = 0 /* TODO: */;
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                BIT(NL80211_IFTYPE_AP) |
+                                BIT(NL80211_IFTYPE_MONITOR);
+       /* TODO: enable P2P when integrated with supplicant:
+        * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)
+        */
+       wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+                       WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+       dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
+                __func__, wiphy->flags);
+       wiphy->probe_resp_offload =
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+
+       wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz;
+
+       /* TODO: figure this out */
+       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+       wiphy->cipher_suites = wil_cipher_suites;
+       wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
+       wiphy->mgmt_stypes = wil_mgmt_stypes;
+}
+
+struct wireless_dev *wil_cfg80211_init(struct device *dev)
+{
+       int rc = 0;
+       struct wireless_dev *wdev;
+
+       wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+       if (!wdev)
+               return ERR_PTR(-ENOMEM);
+
+       wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
+                               sizeof(struct wil6210_priv));
+       if (!wdev->wiphy) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       set_wiphy_dev(wdev->wiphy, dev);
+       wil_wiphy_init(wdev->wiphy);
+
+       rc = wiphy_register(wdev->wiphy);
+       if (rc < 0)
+               goto out_failed_reg;
+
+       return wdev;
+
+out_failed_reg:
+       wiphy_free(wdev->wiphy);
+out:
+       kfree(wdev);
+
+       return ERR_PTR(rc);
+}
+
+void wil_wdev_free(struct wil6210_priv *wil)
+{
+       struct wireless_dev *wdev = wil_to_wdev(wil);
+
+       if (!wdev)
+               return;
+
+       wiphy_unregister(wdev->wiphy);
+       wiphy_free(wdev->wiphy);
+       kfree(wdev);
+}
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h
new file mode 100644 (file)
index 0000000..6a315ba
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef WIL_DBG_HEXDUMP_H_
+#define WIL_DBG_HEXDUMP_H_
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+#define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \
+                            groupsize, buf, len, ascii)        \
+do {                                                           \
+       DEFINE_DYNAMIC_DEBUG_METADATA(descriptor,               \
+               __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
+       if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))  \
+               print_hex_dump(KERN_DEBUG, prefix_str,          \
+                              prefix_type, rowsize, groupsize, \
+                              buf, len, ascii);                \
+} while (0)
+
+#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,     \
+                                groupsize, buf, len, ascii)            \
+       wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize,          \
+                            groupsize, buf, len, ascii)
+
+#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)        \
+       wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true)
+#else /* defined(CONFIG_DYNAMIC_DEBUG) */
+#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,     \
+                                groupsize, buf, len, ascii)            \
+       print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize,    \
+                      groupsize, buf, len, ascii)
+#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
+
+#endif /* WIL_DBG_HEXDUMP_H_ */
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
new file mode 100644 (file)
index 0000000..65fc968
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pci.h>
+#include <linux/rtnetlink.h>
+
+#include "wil6210.h"
+#include "txrx.h"
+
+/* Nasty hack. Better have per device instances */
+static u32 mem_addr;
+static u32 dbg_txdesc_index;
+
+static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
+                           const char *name, struct vring *vring)
+{
+       void __iomem *x = wmi_addr(wil, vring->hwtail);
+
+       seq_printf(s, "VRING %s = {\n", name);
+       seq_printf(s, "  pa     = 0x%016llx\n", (unsigned long long)vring->pa);
+       seq_printf(s, "  va     = 0x%p\n", vring->va);
+       seq_printf(s, "  size   = %d\n", vring->size);
+       seq_printf(s, "  swtail = %d\n", vring->swtail);
+       seq_printf(s, "  swhead = %d\n", vring->swhead);
+       seq_printf(s, "  hwtail = [0x%08x] -> ", vring->hwtail);
+       if (x)
+               seq_printf(s, "0x%08x\n", ioread32(x));
+       else
+               seq_printf(s, "???\n");
+
+       if (vring->va && (vring->size < 1025)) {
+               uint i;
+               for (i = 0; i < vring->size; i++) {
+                       volatile struct vring_tx_desc *d = &vring->va[i].tx;
+                       if ((i % 64) == 0 && (i != 0))
+                               seq_printf(s, "\n");
+                       seq_printf(s, "%s", (d->dma.status & BIT(0)) ?
+                                       "S" : (vring->ctx[i] ? "H" : "h"));
+               }
+               seq_printf(s, "\n");
+       }
+       seq_printf(s, "}\n");
+}
+
+static int wil_vring_debugfs_show(struct seq_file *s, void *data)
+{
+       uint i;
+       struct wil6210_priv *wil = s->private;
+
+       wil_print_vring(s, wil, "rx", &wil->vring_rx);
+
+       for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
+               struct vring *vring = &(wil->vring_tx[i]);
+               if (vring->va) {
+                       char name[10];
+                       snprintf(name, sizeof(name), "tx_%2d", i);
+                       wil_print_vring(s, wil, name, vring);
+               }
+       }
+
+       return 0;
+}
+
+static int wil_vring_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wil_vring_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_vring = {
+       .open           = wil_vring_seq_open,
+       .release        = single_release,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+
+static void wil_print_ring(struct seq_file *s, const char *prefix,
+                          void __iomem *off)
+{
+       struct wil6210_priv *wil = s->private;
+       struct wil6210_mbox_ring r;
+       int rsize;
+       uint i;
+
+       wil_memcpy_fromio_32(&r, off, sizeof(r));
+       wil_mbox_ring_le2cpus(&r);
+       /*
+        * we just read memory block from NIC. This memory may be
+        * garbage. Check validity before using it.
+        */
+       rsize = r.size / sizeof(struct wil6210_mbox_ring_desc);
+
+       seq_printf(s, "ring %s = {\n", prefix);
+       seq_printf(s, "  base = 0x%08x\n", r.base);
+       seq_printf(s, "  size = 0x%04x bytes -> %d entries\n", r.size, rsize);
+       seq_printf(s, "  tail = 0x%08x\n", r.tail);
+       seq_printf(s, "  head = 0x%08x\n", r.head);
+       seq_printf(s, "  entry size = %d\n", r.entry_size);
+
+       if (r.size % sizeof(struct wil6210_mbox_ring_desc)) {
+               seq_printf(s, "  ??? size is not multiple of %zd, garbage?\n",
+                          sizeof(struct wil6210_mbox_ring_desc));
+               goto out;
+       }
+
+       if (!wmi_addr(wil, r.base) ||
+           !wmi_addr(wil, r.tail) ||
+           !wmi_addr(wil, r.head)) {
+               seq_printf(s, "  ??? pointers are garbage?\n");
+               goto out;
+       }
+
+       for (i = 0; i < rsize; i++) {
+               struct wil6210_mbox_ring_desc d;
+               struct wil6210_mbox_hdr hdr;
+               size_t delta = i * sizeof(d);
+               void __iomem *x = wil->csr + HOSTADDR(r.base) + delta;
+
+               wil_memcpy_fromio_32(&d, x, sizeof(d));
+
+               seq_printf(s, "  [%2x] %s %s%s 0x%08x", i,
+                          d.sync ? "F" : "E",
+                          (r.tail - r.base == delta) ? "t" : " ",
+                          (r.head - r.base == delta) ? "h" : " ",
+                          le32_to_cpu(d.addr));
+               if (0 == wmi_read_hdr(wil, d.addr, &hdr)) {
+                       u16 len = le16_to_cpu(hdr.len);
+                       seq_printf(s, " -> %04x %04x %04x %02x\n",
+                                  le16_to_cpu(hdr.seq), len,
+                                  le16_to_cpu(hdr.type), hdr.flags);
+                       if (len <= MAX_MBOXITEM_SIZE) {
+                               int n = 0;
+                               unsigned char printbuf[16 * 3 + 2];
+                               unsigned char databuf[MAX_MBOXITEM_SIZE];
+                               void __iomem *src = wmi_buffer(wil, d.addr) +
+                                       sizeof(struct wil6210_mbox_hdr);
+                               /*
+                                * No need to check @src for validity -
+                                * we already validated @d.addr while
+                                * reading header
+                                */
+                               wil_memcpy_fromio_32(databuf, src, len);
+                               while (n < len) {
+                                       int l = min(len - n, 16);
+                                       hex_dump_to_buffer(databuf + n, l,
+                                                          16, 1, printbuf,
+                                                          sizeof(printbuf),
+                                                          false);
+                                       seq_printf(s, "      : %s\n", printbuf);
+                                       n += l;
+                               }
+                       }
+               } else {
+                       seq_printf(s, "\n");
+               }
+       }
+ out:
+       seq_printf(s, "}\n");
+}
+
+static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
+{
+       struct wil6210_priv *wil = s->private;
+
+       wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
+                      offsetof(struct wil6210_mbox_ctl, tx));
+       wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
+                      offsetof(struct wil6210_mbox_ctl, rx));
+
+       return 0;
+}
+
+static int wil_mbox_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wil_mbox_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_mbox = {
+       .open           = wil_mbox_seq_open,
+       .release        = single_release,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+
+static int wil_debugfs_iomem_x32_set(void *data, u64 val)
+{
+       iowrite32(val, (void __iomem *)data);
+       wmb(); /* make sure write propagated to HW */
+
+       return 0;
+}
+
+static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
+{
+       *val = ioread32((void __iomem *)data);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
+                       wil_debugfs_iomem_x32_set, "0x%08llx\n");
+
+static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
+                                                  mode_t mode,
+                                                  struct dentry *parent,
+                                                  void __iomem *value)
+{
+       return debugfs_create_file(name, mode, parent, (void * __force)value,
+                                  &fops_iomem_x32);
+}
+
+static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
+                                     const char *name,
+                                     struct dentry *parent, u32 off)
+{
+       struct dentry *d = debugfs_create_dir(name, parent);
+
+       if (IS_ERR_OR_NULL(d))
+               return -ENODEV;
+
+       wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d,
+                                    wil->csr + off);
+       wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d,
+                                    wil->csr + off + 4);
+       wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d,
+                                    wil->csr + off + 8);
+       wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d,
+                                    wil->csr + off + 12);
+       wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d,
+                                    wil->csr + off + 16);
+       wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d,
+                                    wil->csr + off + 20);
+       wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d,
+                                    wil->csr + off + 24);
+
+       return 0;
+}
+
+static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
+                                            struct dentry *parent)
+{
+       struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent);
+
+       if (IS_ERR_OR_NULL(d))
+               return -ENODEV;
+
+       wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
+       wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+       wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW));
+
+       return 0;
+}
+
+static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
+                                         struct dentry *parent)
+{
+       struct dentry *d = debugfs_create_dir("ITR_CNT", parent);
+
+       if (IS_ERR_OR_NULL(d))
+               return -ENODEV;
+
+       wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
+       wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_ITR_CNT_DATA));
+       wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr +
+                                    HOSTADDR(RGF_DMA_ITR_CNT_CRL));
+
+       return 0;
+}
+
+static int wil_memread_debugfs_show(struct seq_file *s, void *data)
+{
+       struct wil6210_priv *wil = s->private;
+       void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr));
+
+       if (a)
+               seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a));
+       else
+               seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);
+
+       return 0;
+}
+
+static int wil_memread_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wil_memread_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_memread = {
+       .open           = wil_memread_seq_open,
+       .release        = single_release,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+
+static int wil_default_open(struct inode *inode, struct file *file)
+{
+       if (inode->i_private)
+               file->private_data = inode->i_private;
+
+       return 0;
+}
+
+static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       enum { max_count = 4096 };
+       struct debugfs_blob_wrapper *blob = file->private_data;
+       loff_t pos = *ppos;
+       size_t available = blob->size;
+       void *buf;
+       size_t ret;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       if (pos >= available || !count)
+               return 0;
+
+       if (count > available - pos)
+               count = available - pos;
+       if (count > max_count)
+               count = max_count;
+
+       buf = kmalloc(count, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data +
+                            pos, count);
+
+       ret = copy_to_user(user_buf, buf, count);
+       kfree(buf);
+       if (ret == count)
+               return -EFAULT;
+
+       count -= ret;
+       *ppos = pos + count;
+
+       return count;
+}
+
+static const struct file_operations fops_ioblob = {
+       .read =         wil_read_file_ioblob,
+       .open =         wil_default_open,
+       .llseek =       default_llseek,
+};
+
+static
+struct dentry *wil_debugfs_create_ioblob(const char *name,
+                                        mode_t mode,
+                                        struct dentry *parent,
+                                        struct debugfs_blob_wrapper *blob)
+{
+       return debugfs_create_file(name, mode, parent, blob, &fops_ioblob);
+}
+/*---reset---*/
+static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
+                                   size_t len, loff_t *ppos)
+{
+       struct wil6210_priv *wil = file->private_data;
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       /**
+        * BUG:
+        * this code does NOT sync device state with the rest of system
+        * use with care, debug only!!!
+        */
+       rtnl_lock();
+       dev_close(ndev);
+       ndev->flags &= ~IFF_UP;
+       rtnl_unlock();
+       wil_reset(wil);
+
+       return len;
+}
+
+static const struct file_operations fops_reset = {
+       .write = wil_write_file_reset,
+       .open  = wil_default_open,
+};
+/*---------Tx descriptor------------*/
+
+static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
+{
+       struct wil6210_priv *wil = s->private;
+       struct vring *vring = &(wil->vring_tx[0]);
+
+       if (!vring->va) {
+               seq_printf(s, "No Tx VRING\n");
+               return 0;
+       }
+
+       if (dbg_txdesc_index < vring->size) {
+               volatile struct vring_tx_desc *d =
+                               &(vring->va[dbg_txdesc_index].tx);
+               volatile u32 *u = (volatile u32 *)d;
+               struct sk_buff *skb = vring->ctx[dbg_txdesc_index];
+
+               seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index);
+               seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                          u[0], u[1], u[2], u[3]);
+               seq_printf(s, "  DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                          u[4], u[5], u[6], u[7]);
+               seq_printf(s, "  SKB = %p\n", skb);
+
+               if (skb) {
+                       unsigned char printbuf[16 * 3 + 2];
+                       int i = 0;
+                       int len = skb_headlen(skb);
+                       void *p = skb->data;
+
+                       seq_printf(s, "    len = %d\n", len);
+
+                       while (i < len) {
+                               int l = min(len - i, 16);
+                               hex_dump_to_buffer(p + i, l, 16, 1, printbuf,
+                                                  sizeof(printbuf), false);
+                               seq_printf(s, "      : %s\n", printbuf);
+                               i += l;
+                       }
+               }
+               seq_printf(s, "}\n");
+       } else {
+               seq_printf(s, "TxDesc index (%d) >= size (%d)\n",
+                          dbg_txdesc_index, vring->size);
+       }
+
+       return 0;
+}
+
+static int wil_txdesc_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wil_txdesc_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_txdesc = {
+       .open           = wil_txdesc_seq_open,
+       .release        = single_release,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+
+/*---------beamforming------------*/
+static int wil_bf_debugfs_show(struct seq_file *s, void *data)
+{
+       struct wil6210_priv *wil = s->private;
+       seq_printf(s,
+                  "TSF : 0x%016llx\n"
+                  "TxMCS : %d\n"
+                  "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n",
+                  wil->stats.tsf, wil->stats.bf_mcs,
+                  wil->stats.my_rx_sector, wil->stats.my_tx_sector,
+                  wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
+       return 0;
+}
+
+static int wil_bf_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wil_bf_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_bf = {
+       .open           = wil_bf_seq_open,
+       .release        = single_release,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+/*---------SSID------------*/
+static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct wil6210_priv *wil = file->private_data;
+       struct wireless_dev *wdev = wil_to_wdev(wil);
+
+       return simple_read_from_buffer(user_buf, count, ppos,
+                                      wdev->ssid, wdev->ssid_len);
+}
+
+static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       struct wil6210_priv *wil = file->private_data;
+       struct wireless_dev *wdev = wil_to_wdev(wil);
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       if (*ppos != 0) {
+               wil_err(wil, "Unable to set SSID substring from [%d]\n",
+                       (int)*ppos);
+               return -EINVAL;
+       }
+
+       if (count > sizeof(wdev->ssid)) {
+               wil_err(wil, "SSID too long, len = %d\n", (int)count);
+               return -EINVAL;
+       }
+       if (netif_running(ndev)) {
+               wil_err(wil, "Unable to change SSID on running interface\n");
+               return -EINVAL;
+       }
+
+       wdev->ssid_len = count;
+       return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos,
+                                     buf, count);
+}
+
+static const struct file_operations fops_ssid = {
+       .read = wil_read_file_ssid,
+       .write = wil_write_file_ssid,
+       .open  = wil_default_open,
+};
+
+/*----------------*/
+int wil6210_debugfs_init(struct wil6210_priv *wil)
+{
+       struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
+                       wil_to_wiphy(wil)->debugfsdir);
+
+       if (IS_ERR_OR_NULL(dbg))
+               return -ENODEV;
+
+       debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox);
+       debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring);
+       debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc);
+       debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg,
+                          &dbg_txdesc_index);
+       debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf);
+       debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
+       debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
+                          &wil->secure_pcp);
+
+       wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
+                                  HOSTADDR(RGF_USER_USER_ICR));
+       wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg,
+                                  HOSTADDR(RGF_DMA_EP_TX_ICR));
+       wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg,
+                                  HOSTADDR(RGF_DMA_EP_RX_ICR));
+       wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg,
+                                  HOSTADDR(RGF_DMA_EP_MISC_ICR));
+       wil6210_debugfs_create_pseudo_ISR(wil, dbg);
+       wil6210_debugfs_create_ITR_CNT(wil, dbg);
+
+       debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
+       debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
+
+       debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+
+       wil->rgf_blob.data = (void * __force)wil->csr + 0;
+       wil->rgf_blob.size = 0xa000;
+       wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
+
+       wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
+       wil->fw_code_blob.size = 0x40000;
+       wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
+                                 &wil->fw_code_blob);
+
+       wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
+       wil->fw_data_blob.size = 0x8000;
+       wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
+                                 &wil->fw_data_blob);
+
+       wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
+       wil->fw_peri_blob.size = 0x18000;
+       wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
+                                 &wil->fw_peri_blob);
+
+       wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
+       wil->uc_code_blob.size = 0x10000;
+       wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
+                                 &wil->uc_code_blob);
+
+       wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
+       wil->uc_data_blob.size = 0x4000;
+       wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
+                                 &wil->uc_data_blob);
+
+       return 0;
+}
+
+void wil6210_debugfs_remove(struct wil6210_priv *wil)
+{
+       debugfs_remove_recursive(wil->debug);
+       wil->debug = NULL;
+}
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
new file mode 100644 (file)
index 0000000..38049da
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+
+#include "wil6210.h"
+
+/**
+ * Theory of operation:
+ *
+ * There is ISR pseudo-cause register,
+ * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE
+ * Its bits represents OR'ed bits from 3 real ISR registers:
+ * TX, RX, and MISC.
+ *
+ * Registers may be configured to either "write 1 to clear" or
+ * "clear on read" mode
+ *
+ * When handling interrupt, one have to mask/unmask interrupts for the
+ * real ISR registers, or hardware may malfunction.
+ *
+ */
+
+#define WIL6210_IRQ_DISABLE    (0xFFFFFFFFUL)
+#define WIL6210_IMC_RX         BIT_DMA_EP_RX_ICR_RX_DONE
+#define WIL6210_IMC_TX         (BIT_DMA_EP_TX_ICR_TX_DONE | \
+                               BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
+#define WIL6210_IMC_MISC       (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT)
+
+#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
+                                       BIT_DMA_PSEUDO_CAUSE_TX | \
+                                       BIT_DMA_PSEUDO_CAUSE_MISC))
+
+#if defined(CONFIG_WIL6210_ISR_COR)
+/* configure to Clear-On-Read mode */
+#define WIL_ICR_ICC_VALUE      (0xFFFFFFFFUL)
+
+static inline void wil_icr_clear(u32 x, void __iomem *addr)
+{
+
+}
+#else /* defined(CONFIG_WIL6210_ISR_COR) */
+/* configure to Write-1-to-Clear mode */
+#define WIL_ICR_ICC_VALUE      (0UL)
+
+static inline void wil_icr_clear(u32 x, void __iomem *addr)
+{
+       iowrite32(x, addr);
+}
+#endif /* defined(CONFIG_WIL6210_ISR_COR) */
+
+static inline u32 wil_ioread32_and_clear(void __iomem *addr)
+{
+       u32 x = ioread32(addr);
+
+       wil_icr_clear(x, addr);
+
+       return x;
+}
+
+static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                 offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                 offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                 offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
+{
+       wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+                 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+
+       clear_bit(wil_status_irqen, &wil->status);
+}
+
+static void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IMC_TX, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                 offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IMC_RX, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                 offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
+{
+       iowrite32(WIL6210_IMC_MISC, wil->csr +
+                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                 offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
+{
+       wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+       set_bit(wil_status_irqen, &wil->status);
+
+       iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr +
+                 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+}
+
+void wil6210_disable_irq(struct wil6210_priv *wil)
+{
+       wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+       wil6210_mask_irq_tx(wil);
+       wil6210_mask_irq_rx(wil);
+       wil6210_mask_irq_misc(wil);
+       wil6210_mask_irq_pseudo(wil);
+}
+
+void wil6210_enable_irq(struct wil6210_priv *wil)
+{
+       wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                 offsetof(struct RGF_ICR, ICC));
+       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                 offsetof(struct RGF_ICR, ICC));
+       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                 offsetof(struct RGF_ICR, ICC));
+
+       wil6210_unmask_irq_pseudo(wil);
+       wil6210_unmask_irq_tx(wil);
+       wil6210_unmask_irq_rx(wil);
+       wil6210_unmask_irq_misc(wil);
+}
+
+static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
+{
+       struct wil6210_priv *wil = cookie;
+       u32 isr = wil_ioread32_and_clear(wil->csr +
+                                        HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                                        offsetof(struct RGF_ICR, ICR));
+
+       wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr);
+
+       if (!isr) {
+               wil_err(wil, "spurious IRQ: RX\n");
+               return IRQ_NONE;
+       }
+
+       wil6210_mask_irq_rx(wil);
+
+       if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
+               wil_dbg_IRQ(wil, "RX done\n");
+               isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
+               wil_rx_handle(wil);
+       }
+
+       if (isr)
+               wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
+
+       wil6210_unmask_irq_rx(wil);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
+{
+       struct wil6210_priv *wil = cookie;
+       u32 isr = wil_ioread32_and_clear(wil->csr +
+                                        HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                                        offsetof(struct RGF_ICR, ICR));
+
+       wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr);
+
+       if (!isr) {
+               wil_err(wil, "spurious IRQ: TX\n");
+               return IRQ_NONE;
+       }
+
+       wil6210_mask_irq_tx(wil);
+
+       if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
+               uint i;
+               wil_dbg_IRQ(wil, "TX done\n");
+               isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
+               for (i = 0; i < 24; i++) {
+                       u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i);
+                       if (isr & mask) {
+                               isr &= ~mask;
+                               wil_dbg_IRQ(wil, "TX done(%i)\n", i);
+                               wil_tx_complete(wil, i);
+                       }
+               }
+       }
+
+       if (isr)
+               wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
+
+       wil6210_unmask_irq_tx(wil);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
+{
+       struct wil6210_priv *wil = cookie;
+       u32 isr = wil_ioread32_and_clear(wil->csr +
+                                        HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                                        offsetof(struct RGF_ICR, ICR));
+
+       wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr);
+
+       if (!isr) {
+               wil_err(wil, "spurious IRQ: MISC\n");
+               return IRQ_NONE;
+       }
+
+       wil6210_mask_irq_misc(wil);
+
+       if (isr & ISR_MISC_FW_READY) {
+               wil_dbg_IRQ(wil, "IRQ: FW ready\n");
+               /**
+                * Actual FW ready indicated by the
+                * WMI_FW_READY_EVENTID
+                */
+               isr &= ~ISR_MISC_FW_READY;
+       }
+
+       wil->isr_misc = isr;
+
+       if (isr) {
+               return IRQ_WAKE_THREAD;
+       } else {
+               wil6210_unmask_irq_misc(wil);
+               return IRQ_HANDLED;
+       }
+}
+
+static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
+{
+       struct wil6210_priv *wil = cookie;
+       u32 isr = wil->isr_misc;
+
+       wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr);
+
+       if (isr & ISR_MISC_MBOX_EVT) {
+               wil_dbg_IRQ(wil, "MBOX event\n");
+               wmi_recv_cmd(wil);
+               isr &= ~ISR_MISC_MBOX_EVT;
+       }
+
+       if (isr)
+               wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr);
+
+       wil->isr_misc = 0;
+
+       wil6210_unmask_irq_misc(wil);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * thread IRQ handler
+ */
+static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
+{
+       struct wil6210_priv *wil = cookie;
+
+       wil_dbg_IRQ(wil, "Thread IRQ\n");
+       /* Discover real IRQ cause */
+       if (wil->isr_misc)
+               wil6210_irq_misc_thread(irq, cookie);
+
+       wil6210_unmask_irq_pseudo(wil);
+
+       return IRQ_HANDLED;
+}
+
+/* DEBUG
+ * There is subtle bug in hardware that causes IRQ to raise when it should be
+ * masked. It is quite rare and hard to debug.
+ *
+ * Catch irq issue if it happens and print all I can.
+ */
+static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
+{
+       if (!test_bit(wil_status_irqen, &wil->status)) {
+               u32 icm_rx = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                               offsetof(struct RGF_ICR, ICM));
+               u32 icr_rx = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                               offsetof(struct RGF_ICR, ICR));
+               u32 imv_rx = ioread32(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_RX_ICR) +
+                               offsetof(struct RGF_ICR, IMV));
+               u32 icm_tx = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                               offsetof(struct RGF_ICR, ICM));
+               u32 icr_tx = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                               offsetof(struct RGF_ICR, ICR));
+               u32 imv_tx = ioread32(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_TX_ICR) +
+                               offsetof(struct RGF_ICR, IMV));
+               u32 icm_misc = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                               offsetof(struct RGF_ICR, ICM));
+               u32 icr_misc = wil_ioread32_and_clear(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                               offsetof(struct RGF_ICR, ICR));
+               u32 imv_misc = ioread32(wil->csr +
+                               HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+                               offsetof(struct RGF_ICR, IMV));
+               wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n"
+                               "Rx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
+                               "Tx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
+                               "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n",
+                               pseudo_cause,
+                               icm_rx, icr_rx, imv_rx,
+                               icm_tx, icr_tx, imv_tx,
+                               icm_misc, icr_misc, imv_misc);
+
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static irqreturn_t wil6210_hardirq(int irq, void *cookie)
+{
+       irqreturn_t rc = IRQ_HANDLED;
+       struct wil6210_priv *wil = cookie;
+       u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
+
+       /**
+        * pseudo_cause is Clear-On-Read, no need to ACK
+        */
+       if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff))
+               return IRQ_NONE;
+
+       /* FIXME: IRQ mask debug */
+       if (wil6210_debug_irq_mask(wil, pseudo_cause))
+               return IRQ_NONE;
+
+       wil6210_mask_irq_pseudo(wil);
+
+       /* Discover real IRQ cause
+        * There are 2 possible phases for every IRQ:
+        * - hard IRQ handler called right here
+        * - threaded handler called later
+        *
+        * Hard IRQ handler reads and clears ISR.
+        *
+        * If threaded handler requested, hard IRQ handler
+        * returns IRQ_WAKE_THREAD and saves ISR register value
+        * for the threaded handler use.
+        *
+        * voting for wake thread - need at least 1 vote
+        */
+       if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
+           (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
+               rc = IRQ_WAKE_THREAD;
+
+       if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
+           (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
+               rc = IRQ_WAKE_THREAD;
+
+       if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
+           (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD))
+               rc = IRQ_WAKE_THREAD;
+
+       /* if thread is requested, it will unmask IRQ */
+       if (rc != IRQ_WAKE_THREAD)
+               wil6210_unmask_irq_pseudo(wil);
+
+       wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause);
+
+       return rc;
+}
+
+static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
+{
+       int rc;
+       /*
+        * IRQ's are in the following order:
+        * - Tx
+        * - Rx
+        * - Misc
+        */
+
+       rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED,
+                        WIL_NAME"_tx", wil);
+       if (rc)
+               return rc;
+
+       rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED,
+                        WIL_NAME"_rx", wil);
+       if (rc)
+               goto free0;
+
+       rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
+                                 wil6210_irq_misc_thread,
+                                 IRQF_SHARED, WIL_NAME"_misc", wil);
+       if (rc)
+               goto free1;
+
+       return 0;
+       /* error branch */
+free1:
+       free_irq(irq + 1, wil);
+free0:
+       free_irq(irq, wil);
+
+       return rc;
+}
+
+int wil6210_init_irq(struct wil6210_priv *wil, int irq)
+{
+       int rc;
+       if (wil->n_msi == 3)
+               rc = wil6210_request_3msi(wil, irq);
+       else
+               rc = request_threaded_irq(irq, wil6210_hardirq,
+                                         wil6210_thread_irq,
+                                         wil->n_msi ? 0 : IRQF_SHARED,
+                                         WIL_NAME, wil);
+       if (rc)
+               return rc;
+
+       wil6210_enable_irq(wil);
+
+       return 0;
+}
+
+void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
+{
+       wil6210_disable_irq(wil);
+       free_irq(irq, wil);
+       if (wil->n_msi == 3) {
+               free_irq(irq + 1, wil);
+               free_irq(irq + 2, wil);
+       }
+}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
new file mode 100644 (file)
index 0000000..95fcd36
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/ieee80211.h>
+#include <linux/wireless.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/if_arp.h>
+
+#include "wil6210.h"
+
+/*
+ * Due to a hardware issue,
+ * one has to read/write to/from NIC in 32-bit chunks;
+ * regular memcpy_fromio and siblings will
+ * not work on 64-bit platform - it uses 64-bit transactions
+ *
+ * Force 32-bit transactions to enable NIC on 64-bit platforms
+ *
+ * To avoid byte swap on big endian host, __raw_{read|write}l
+ * should be used - {read|write}l would swap bytes to provide
+ * little endian on PCI value in host endianness.
+ */
+void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
+                         size_t count)
+{
+       u32 *d = dst;
+       const volatile u32 __iomem *s = src;
+
+       /* size_t is unsigned, if (count%4 != 0) it will wrap */
+       for (count += 4; count > 4; count -= 4)
+               *d++ = __raw_readl(s++);
+}
+
+void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
+                       size_t count)
+{
+       volatile u32 __iomem *d = dst;
+       const u32 *s = src;
+
+       for (count += 4; count > 4; count -= 4)
+               __raw_writel(*s++, d++);
+}
+
+static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+{
+       uint i;
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *wdev = wil->wdev;
+
+       wil_dbg(wil, "%s()\n", __func__);
+
+       wil_link_off(wil);
+       clear_bit(wil_status_fwconnected, &wil->status);
+
+       switch (wdev->sme_state) {
+       case CFG80211_SME_CONNECTED:
+               cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                     NULL, 0, GFP_KERNEL);
+               break;
+       case CFG80211_SME_CONNECTING:
+               cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
+                                       WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                       GFP_KERNEL);
+               break;
+       default:
+               ;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++)
+               wil_vring_fini_tx(wil, i);
+}
+
+static void wil_disconnect_worker(struct work_struct *work)
+{
+       struct wil6210_priv *wil = container_of(work,
+                       struct wil6210_priv, disconnect_worker);
+
+       _wil6210_disconnect(wil, NULL);
+}
+
+static void wil_connect_timer_fn(ulong x)
+{
+       struct wil6210_priv *wil = (void *)x;
+
+       wil_dbg(wil, "Connect timeout\n");
+
+       /* reschedule to thread context - disconnect won't
+        * run from atomic context
+        */
+       schedule_work(&wil->disconnect_worker);
+}
+
+int wil_priv_init(struct wil6210_priv *wil)
+{
+       wil_dbg(wil, "%s()\n", __func__);
+
+       mutex_init(&wil->mutex);
+       mutex_init(&wil->wmi_mutex);
+
+       init_completion(&wil->wmi_ready);
+
+       wil->pending_connect_cid = -1;
+       setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
+
+       INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker);
+       INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
+       INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
+
+       INIT_LIST_HEAD(&wil->pending_wmi_ev);
+       spin_lock_init(&wil->wmi_ev_lock);
+
+       wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi");
+       if (!wil->wmi_wq)
+               return -EAGAIN;
+
+       wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect");
+       if (!wil->wmi_wq_conn) {
+               destroy_workqueue(wil->wmi_wq);
+               return -EAGAIN;
+       }
+
+       /* make shadow copy of registers that should not change on run time */
+       wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+                            sizeof(struct wil6210_mbox_ctl));
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+
+       return 0;
+}
+
+void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+{
+       del_timer_sync(&wil->connect_timer);
+       _wil6210_disconnect(wil, bssid);
+}
+
+void wil_priv_deinit(struct wil6210_priv *wil)
+{
+       cancel_work_sync(&wil->disconnect_worker);
+       wil6210_disconnect(wil, NULL);
+       wmi_event_flush(wil);
+       destroy_workqueue(wil->wmi_wq_conn);
+       destroy_workqueue(wil->wmi_wq);
+}
+
+static void wil_target_reset(struct wil6210_priv *wil)
+{
+       wil_dbg(wil, "Resetting...\n");
+
+       /* register write */
+#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a))
+       /* register set = read, OR, write */
+#define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \
+               wil->csr + HOSTADDR(a))
+
+       /* hpal_perst_from_pad_src_n_mask */
+       S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
+       /* car_perst_rst_src_n_mask */
+       S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
+
+       W(RGF_USER_MAC_CPU_0,  BIT(1)); /* mac_cpu_man_rst */
+       W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
+
+       msleep(100);
+
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
+
+       msleep(100);
+
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
+
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
+       W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
+
+       msleep(2000);
+
+       W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */
+
+       msleep(2000);
+
+       wil_dbg(wil, "Reset completed\n");
+
+#undef W
+#undef S
+}
+
+void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
+{
+       le32_to_cpus(&r->base);
+       le16_to_cpus(&r->entry_size);
+       le16_to_cpus(&r->size);
+       le32_to_cpus(&r->tail);
+       le32_to_cpus(&r->head);
+}
+
+static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
+{
+       ulong to = msecs_to_jiffies(1000);
+       ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
+       if (0 == left) {
+               wil_err(wil, "Firmware not ready\n");
+               return -ETIME;
+       } else {
+               wil_dbg(wil, "FW ready after %d ms\n",
+                       jiffies_to_msecs(to-left));
+       }
+       return 0;
+}
+
+/*
+ * We reset all the structures, and we reset the UMAC.
+ * After calling this routine, you're expected to reload
+ * the firmware.
+ */
+int wil_reset(struct wil6210_priv *wil)
+{
+       int rc;
+
+       cancel_work_sync(&wil->disconnect_worker);
+       wil6210_disconnect(wil, NULL);
+
+       wmi_event_flush(wil);
+
+       flush_workqueue(wil->wmi_wq);
+       flush_workqueue(wil->wmi_wq_conn);
+
+       wil6210_disable_irq(wil);
+       wil->status = 0;
+
+       /* TODO: put MAC in reset */
+       wil_target_reset(wil);
+
+       /* init after reset */
+       wil->pending_connect_cid = -1;
+       INIT_COMPLETION(wil->wmi_ready);
+
+       /* make shadow copy of registers that should not change on run time */
+       wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+                            sizeof(struct wil6210_mbox_ctl));
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+       wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+
+       /* TODO: release MAC reset */
+       wil6210_enable_irq(wil);
+
+       /* we just started MAC, wait for FW ready */
+       rc = wil_wait_for_fw_ready(wil);
+
+       return rc;
+}
+
+
+void wil_link_on(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       wil_dbg(wil, "%s()\n", __func__);
+
+       netif_carrier_on(ndev);
+       netif_tx_wake_all_queues(ndev);
+}
+
+void wil_link_off(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       wil_dbg(wil, "%s()\n", __func__);
+
+       netif_tx_stop_all_queues(ndev);
+       netif_carrier_off(ndev);
+}
+
+static int __wil_up(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *wdev = wil->wdev;
+       struct ieee80211_channel *channel = wdev->preset_chandef.chan;
+       int rc;
+       int bi;
+       u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+       rc = wil_reset(wil);
+       if (rc)
+               return rc;
+
+       /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */
+       wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC);
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+               wil_dbg(wil, "type: STATION\n");
+               bi = 0;
+               ndev->type = ARPHRD_ETHER;
+               break;
+       case NL80211_IFTYPE_AP:
+               wil_dbg(wil, "type: AP\n");
+               bi = 100;
+               ndev->type = ARPHRD_ETHER;
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               wil_dbg(wil, "type: P2P_CLIENT\n");
+               bi = 0;
+               ndev->type = ARPHRD_ETHER;
+               break;
+       case NL80211_IFTYPE_P2P_GO:
+               wil_dbg(wil, "type: P2P_GO\n");
+               bi = 100;
+               ndev->type = ARPHRD_ETHER;
+               break;
+       case NL80211_IFTYPE_MONITOR:
+               wil_dbg(wil, "type: Monitor\n");
+               bi = 0;
+               ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+               /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       /* Apply profile in the following order: */
+       /* SSID and channel for the AP */
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_GO:
+               if (wdev->ssid_len == 0) {
+                       wil_err(wil, "SSID not set\n");
+                       return -EINVAL;
+               }
+               wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid);
+               if (channel)
+                       wmi_set_channel(wil, channel->hw_value);
+               break;
+       default:
+               ;
+       }
+
+       /* MAC address - pre-requisite for other commands */
+       wmi_set_mac_address(wil, ndev->dev_addr);
+
+       /* Set up beaconing if required. */
+       rc = wmi_set_bcon(wil, bi, wmi_nettype);
+       if (rc)
+               return rc;
+
+       /* Rx VRING. After MAC and beacon */
+       wil_rx_init(wil);
+
+       return 0;
+}
+
+int wil_up(struct wil6210_priv *wil)
+{
+       int rc;
+
+       mutex_lock(&wil->mutex);
+       rc = __wil_up(wil);
+       mutex_unlock(&wil->mutex);
+
+       return rc;
+}
+
+static int __wil_down(struct wil6210_priv *wil)
+{
+       if (wil->scan_request) {
+               cfg80211_scan_done(wil->scan_request, true);
+               wil->scan_request = NULL;
+       }
+
+       wil6210_disconnect(wil, NULL);
+       wil_rx_fini(wil);
+
+       return 0;
+}
+
+int wil_down(struct wil6210_priv *wil)
+{
+       int rc;
+
+       mutex_lock(&wil->mutex);
+       rc = __wil_down(wil);
+       mutex_unlock(&wil->mutex);
+
+       return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
new file mode 100644 (file)
index 0000000..3068b5c
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+
+#include "wil6210.h"
+
+static int wil_open(struct net_device *ndev)
+{
+       struct wil6210_priv *wil = ndev_to_wil(ndev);
+
+       return wil_up(wil);
+}
+
+static int wil_stop(struct net_device *ndev)
+{
+       struct wil6210_priv *wil = ndev_to_wil(ndev);
+
+       return wil_down(wil);
+}
+
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 3
+ * AC_VI -> queue 2
+ * AC_BE -> queue 1
+ * AC_BK -> queue 0
+ */
+static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb)
+{
+       static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+       struct wil6210_priv *wil = ndev_to_wil(ndev);
+       u16 rc;
+
+       skb->priority = cfg80211_classify8021d(skb);
+
+       rc = wil_1d_to_queue[skb->priority];
+
+       wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority,
+                    (int)rc);
+
+       return rc;
+}
+
+static const struct net_device_ops wil_netdev_ops = {
+       .ndo_open               = wil_open,
+       .ndo_stop               = wil_stop,
+       .ndo_start_xmit         = wil_start_xmit,
+       .ndo_select_queue       = wil_select_queue,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+void *wil_if_alloc(struct device *dev, void __iomem *csr)
+{
+       struct net_device *ndev;
+       struct wireless_dev *wdev;
+       struct wil6210_priv *wil;
+       struct ieee80211_channel *ch;
+       int rc = 0;
+
+       wdev = wil_cfg80211_init(dev);
+       if (IS_ERR(wdev)) {
+               dev_err(dev, "wil_cfg80211_init failed\n");
+               return wdev;
+       }
+
+       wil = wdev_to_wil(wdev);
+       wil->csr = csr;
+       wil->wdev = wdev;
+
+       rc = wil_priv_init(wil);
+       if (rc) {
+               dev_err(dev, "wil_priv_init failed\n");
+               goto out_wdev;
+       }
+
+       wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */
+       /* default monitor channel */
+       ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
+       cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
+
+       ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1);
+       if (!ndev) {
+               dev_err(dev, "alloc_netdev_mqs failed\n");
+               rc = -ENOMEM;
+               goto out_priv;
+       }
+
+       ndev->netdev_ops = &wil_netdev_ops;
+       ndev->ieee80211_ptr = wdev;
+       SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+       wdev->netdev = ndev;
+
+       wil_link_off(wil);
+
+       return wil;
+
+ out_priv:
+       wil_priv_deinit(wil);
+
+ out_wdev:
+       wil_wdev_free(wil);
+
+       return ERR_PTR(rc);
+}
+
+void wil_if_free(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       if (!ndev)
+               return;
+
+       free_netdev(ndev);
+       wil_priv_deinit(wil);
+       wil_wdev_free(wil);
+}
+
+int wil_if_add(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       int rc;
+
+       rc = register_netdev(ndev);
+       if (rc < 0) {
+               dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);
+               return rc;
+       }
+
+       wil_link_off(wil);
+
+       return 0;
+}
+
+void wil_if_remove(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       unregister_netdev(ndev);
+}
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
new file mode 100644 (file)
index 0000000..0fc83ed
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+
+#include "wil6210.h"
+
+static int use_msi = 1;
+module_param(use_msi, int, S_IRUGO);
+MODULE_PARM_DESC(use_msi,
+                " Use MSI interrupt: "
+                "0 - don't, 1 - (default) - single, or 3");
+
+/* Bus ops */
+static int wil_if_pcie_enable(struct wil6210_priv *wil)
+{
+       struct pci_dev *pdev = wil->pdev;
+       int rc;
+
+       pci_set_master(pdev);
+
+       /*
+        * how many MSI interrupts to request?
+        */
+       switch (use_msi) {
+       case 3:
+       case 1:
+       case 0:
+               break;
+       default:
+               wil_err(wil, "Invalid use_msi=%d, default to 1\n",
+                       use_msi);
+               use_msi = 1;
+       }
+       wil->n_msi = use_msi;
+       if (wil->n_msi) {
+               wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi);
+               rc = pci_enable_msi_block(pdev, wil->n_msi);
+               if (rc && (wil->n_msi == 3)) {
+                       wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
+                       wil->n_msi = 1;
+                       rc = pci_enable_msi_block(pdev, wil->n_msi);
+               }
+               if (rc) {
+                       wil_err(wil, "pci_enable_msi failed, use INTx\n");
+                       wil->n_msi = 0;
+               }
+       } else {
+               wil_dbg(wil, "MSI interrupts disabled, use INTx\n");
+       }
+
+       rc = wil6210_init_irq(wil, pdev->irq);
+       if (rc)
+               goto stop_master;
+
+       /* need reset here to obtain MAC */
+       rc = wil_reset(wil);
+       if (rc)
+               goto release_irq;
+
+       return 0;
+
+ release_irq:
+       wil6210_fini_irq(wil, pdev->irq);
+       /* safe to call if no MSI */
+       pci_disable_msi(pdev);
+ stop_master:
+       pci_clear_master(pdev);
+       return rc;
+}
+
+static int wil_if_pcie_disable(struct wil6210_priv *wil)
+{
+       struct pci_dev *pdev = wil->pdev;
+
+       pci_clear_master(pdev);
+       /* disable and release IRQ */
+       wil6210_fini_irq(wil, pdev->irq);
+       /* safe to call if no MSI */
+       pci_disable_msi(pdev);
+       /* TODO: disable HW */
+
+       return 0;
+}
+
+static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct wil6210_priv *wil;
+       struct device *dev = &pdev->dev;
+       void __iomem *csr;
+       int rc;
+
+       /* check HW */
+       dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
+                (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
+
+       if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
+               dev_err(&pdev->dev, "Not " WIL_NAME "? "
+                       "BAR0 size is %lu while expecting %lu\n",
+                       (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
+               return -ENODEV;
+       }
+
+       rc = pci_enable_device(pdev);
+       if (rc) {
+               dev_err(&pdev->dev, "pci_enable_device failed\n");
+               return -ENODEV;
+       }
+       /* rollback to err_disable_pdev */
+
+       rc = pci_request_region(pdev, 0, WIL_NAME);
+       if (rc) {
+               dev_err(&pdev->dev, "pci_request_region failed\n");
+               goto err_disable_pdev;
+       }
+       /* rollback to err_release_reg */
+
+       csr = pci_ioremap_bar(pdev, 0);
+       if (!csr) {
+               dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
+               rc = -ENODEV;
+               goto err_release_reg;
+       }
+       /* rollback to err_iounmap */
+       dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr);
+
+       wil = wil_if_alloc(dev, csr);
+       if (IS_ERR(wil)) {
+               rc = (int)PTR_ERR(wil);
+               dev_err(dev, "wil_if_alloc failed: %d\n", rc);
+               goto err_iounmap;
+       }
+       /* rollback to if_free */
+
+       pci_set_drvdata(pdev, wil);
+       wil->pdev = pdev;
+
+       /* FW should raise IRQ when ready */
+       rc = wil_if_pcie_enable(wil);
+       if (rc) {
+               wil_err(wil, "Enable device failed\n");
+               goto if_free;
+       }
+       /* rollback to bus_disable */
+
+       rc = wil_if_add(wil);
+       if (rc) {
+               wil_err(wil, "wil_if_add failed: %d\n", rc);
+               goto bus_disable;
+       }
+
+       wil6210_debugfs_init(wil);
+
+       /* check FW is alive */
+       wmi_echo(wil);
+
+       return 0;
+
+ bus_disable:
+       wil_if_pcie_disable(wil);
+ if_free:
+       wil_if_free(wil);
+ err_iounmap:
+       pci_iounmap(pdev, csr);
+ err_release_reg:
+       pci_release_region(pdev, 0);
+ err_disable_pdev:
+       pci_disable_device(pdev);
+
+       return rc;
+}
+
+static void wil_pcie_remove(struct pci_dev *pdev)
+{
+       struct wil6210_priv *wil = pci_get_drvdata(pdev);
+
+       wil6210_debugfs_remove(wil);
+       wil_if_pcie_disable(wil);
+       wil_if_remove(wil);
+       wil_if_free(wil);
+       pci_iounmap(pdev, wil->csr);
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
+       { PCI_DEVICE(0x1ae9, 0x0301) },
+       { /* end: all zeroes */ },
+};
+MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
+
+static struct pci_driver wil6210_driver = {
+       .probe          = wil_pcie_probe,
+       .remove         = wil_pcie_remove,
+       .id_table       = wil6210_pcie_ids,
+       .name           = WIL_NAME,
+};
+
+module_pci_driver(wil6210_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
+MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card");
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
new file mode 100644 (file)
index 0000000..f29c294
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/if_arp.h>
+#include <linux/moduleparam.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+#include "txrx.h"
+
+static bool rtap_include_phy_info;
+module_param(rtap_include_phy_info, bool, S_IRUGO);
+MODULE_PARM_DESC(rtap_include_phy_info,
+                " Include PHY info in the radiotap header, default - no");
+
+static inline int wil_vring_is_empty(struct vring *vring)
+{
+       return vring->swhead == vring->swtail;
+}
+
+static inline u32 wil_vring_next_tail(struct vring *vring)
+{
+       return (vring->swtail + 1) % vring->size;
+}
+
+static inline void wil_vring_advance_head(struct vring *vring, int n)
+{
+       vring->swhead = (vring->swhead + n) % vring->size;
+}
+
+static inline int wil_vring_is_full(struct vring *vring)
+{
+       return wil_vring_next_tail(vring) == vring->swhead;
+}
+/*
+ * Available space in Tx Vring
+ */
+static inline int wil_vring_avail_tx(struct vring *vring)
+{
+       u32 swhead = vring->swhead;
+       u32 swtail = vring->swtail;
+       int used = (vring->size + swhead - swtail) % vring->size;
+
+       return vring->size - used - 1;
+}
+
+static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
+{
+       struct device *dev = wil_to_dev(wil);
+       size_t sz = vring->size * sizeof(vring->va[0]);
+       uint i;
+
+       BUILD_BUG_ON(sizeof(vring->va[0]) != 32);
+
+       vring->swhead = 0;
+       vring->swtail = 0;
+       vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL);
+       if (!vring->ctx) {
+               wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n",
+                       vring->size);
+               vring->va = NULL;
+               return -ENOMEM;
+       }
+       /*
+        * vring->va should be aligned on its size rounded up to power of 2
+        * This is granted by the dma_alloc_coherent
+        */
+       vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
+       if (!vring->va) {
+               wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n",
+                       vring->size);
+               kfree(vring->ctx);
+               vring->ctx = NULL;
+               return -ENOMEM;
+       }
+       /* initially, all descriptors are SW owned
+        * For Tx and Rx, ownership bit is at the same location, thus
+        * we can use any
+        */
+       for (i = 0; i < vring->size; i++) {
+               volatile struct vring_tx_desc *d = &(vring->va[i].tx);
+               d->dma.status = TX_DMA_STATUS_DU;
+       }
+
+       wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
+               vring->va, (unsigned long long)vring->pa, vring->ctx);
+
+       return 0;
+}
+
+static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
+                          int tx)
+{
+       struct device *dev = wil_to_dev(wil);
+       size_t sz = vring->size * sizeof(vring->va[0]);
+
+       while (!wil_vring_is_empty(vring)) {
+               if (tx) {
+                       volatile struct vring_tx_desc *d =
+                                       &vring->va[vring->swtail].tx;
+                       dma_addr_t pa = d->dma.addr_low |
+                                       ((u64)d->dma.addr_high << 32);
+                       struct sk_buff *skb = vring->ctx[vring->swtail];
+                       if (skb) {
+                               dma_unmap_single(dev, pa, d->dma.length,
+                                                DMA_TO_DEVICE);
+                               dev_kfree_skb_any(skb);
+                               vring->ctx[vring->swtail] = NULL;
+                       } else {
+                               dma_unmap_page(dev, pa, d->dma.length,
+                                              DMA_TO_DEVICE);
+                       }
+                       vring->swtail = wil_vring_next_tail(vring);
+               } else { /* rx */
+                       volatile struct vring_rx_desc *d =
+                                       &vring->va[vring->swtail].rx;
+                       dma_addr_t pa = d->dma.addr_low |
+                                       ((u64)d->dma.addr_high << 32);
+                       struct sk_buff *skb = vring->ctx[vring->swhead];
+                       dma_unmap_single(dev, pa, d->dma.length,
+                                        DMA_FROM_DEVICE);
+                       kfree_skb(skb);
+                       wil_vring_advance_head(vring, 1);
+               }
+       }
+       dma_free_coherent(dev, sz, (void *)vring->va, vring->pa);
+       kfree(vring->ctx);
+       vring->pa = 0;
+       vring->va = NULL;
+       vring->ctx = NULL;
+}
+
+/**
+ * Allocate one skb for Rx VRING
+ *
+ * Safe to call from IRQ
+ */
+static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
+                              u32 i, int headroom)
+{
+       struct device *dev = wil_to_dev(wil);
+       unsigned int sz = RX_BUF_LEN;
+       volatile struct vring_rx_desc *d = &(vring->va[i].rx);
+       dma_addr_t pa;
+
+       /* TODO align */
+       struct sk_buff *skb = dev_alloc_skb(sz + headroom);
+       if (unlikely(!skb))
+               return -ENOMEM;
+
+       skb_reserve(skb, headroom);
+       skb_put(skb, sz);
+
+       pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE);
+       if (unlikely(dma_mapping_error(dev, pa))) {
+               kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
+       d->dma.addr_low = lower_32_bits(pa);
+       d->dma.addr_high = (u16)upper_32_bits(pa);
+       /* ip_length don't care */
+       /* b11 don't care */
+       /* error don't care */
+       d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
+       d->dma.length = sz;
+       vring->ctx[i] = skb;
+
+       return 0;
+}
+
+/**
+ * Adds radiotap header
+ *
+ * Any error indicated as "Bad FCS"
+ *
+ * Vendor data for 04:ce:14-1 (Wilocity-1) consists of:
+ *  - Rx descriptor: 32 bytes
+ *  - Phy info
+ */
+static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
+                                      struct sk_buff *skb,
+                                      volatile struct vring_rx_desc *d)
+{
+       struct wireless_dev *wdev = wil->wdev;
+       struct wil6210_rtap {
+               struct ieee80211_radiotap_header rthdr;
+               /* fields should be in the order of bits in rthdr.it_present */
+               /* flags */
+               u8 flags;
+               /* channel */
+               __le16 chnl_freq __aligned(2);
+               __le16 chnl_flags;
+               /* MCS */
+               u8 mcs_present;
+               u8 mcs_flags;
+               u8 mcs_index;
+       } __packed;
+       struct wil6210_rtap_vendor {
+               struct wil6210_rtap rtap;
+               /* vendor */
+               u8 vendor_oui[3] __aligned(2);
+               u8 vendor_ns;
+               __le16 vendor_skip;
+               u8 vendor_data[0];
+       } __packed;
+       struct wil6210_rtap_vendor *rtap_vendor;
+       int rtap_len = sizeof(struct wil6210_rtap);
+       int phy_length = 0; /* phy info header size, bytes */
+       static char phy_data[128];
+       struct ieee80211_channel *ch = wdev->preset_chandef.chan;
+
+       if (rtap_include_phy_info) {
+               rtap_len = sizeof(*rtap_vendor) + sizeof(*d);
+               /* calculate additional length */
+               if (d->dma.status & RX_DMA_STATUS_PHY_INFO) {
+                       /**
+                        * PHY info starts from 8-byte boundary
+                        * there are 8-byte lines, last line may be partially
+                        * written (HW bug), thus FW configures for last line
+                        * to be excessive. Driver skips this last line.
+                        */
+                       int len = min_t(int, 8 + sizeof(phy_data),
+                                       wil_rxdesc_phy_length(d));
+                       if (len > 8) {
+                               void *p = skb_tail_pointer(skb);
+                               void *pa = PTR_ALIGN(p, 8);
+                               if (skb_tailroom(skb) >= len + (pa - p)) {
+                                       phy_length = len - 8;
+                                       memcpy(phy_data, pa, phy_length);
+                               }
+                       }
+               }
+               rtap_len += phy_length;
+       }
+
+       if (skb_headroom(skb) < rtap_len &&
+           pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) {
+               wil_err(wil, "Unable to expand headrom to %d\n", rtap_len);
+               return;
+       }
+
+       rtap_vendor = (void *)skb_push(skb, rtap_len);
+       memset(rtap_vendor, 0, rtap_len);
+
+       rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
+       rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len);
+       rtap_vendor->rtap.rthdr.it_present = cpu_to_le32(
+                       (1 << IEEE80211_RADIOTAP_FLAGS) |
+                       (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                       (1 << IEEE80211_RADIOTAP_MCS));
+       if (d->dma.status & RX_DMA_STATUS_ERROR)
+               rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+       rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
+       rtap_vendor->rtap.chnl_flags = cpu_to_le16(0);
+
+       rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
+       rtap_vendor->rtap.mcs_flags = 0;
+       rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d);
+
+       if (rtap_include_phy_info) {
+               rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 <<
+                               IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
+               /* OUI for Wilocity 04:ce:14 */
+               rtap_vendor->vendor_oui[0] = 0x04;
+               rtap_vendor->vendor_oui[1] = 0xce;
+               rtap_vendor->vendor_oui[2] = 0x14;
+               rtap_vendor->vendor_ns = 1;
+               /* Rx descriptor + PHY data  */
+               rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) +
+                                                      phy_length);
+               memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d));
+               memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data,
+                      phy_length);
+       }
+}
+
+/*
+ * Fast swap in place between 2 registers
+ */
+static void wil_swap_u16(u16 *a, u16 *b)
+{
+       *a ^= *b;
+       *b ^= *a;
+       *a ^= *b;
+}
+
+static void wil_swap_ethaddr(void *data)
+{
+       struct ethhdr *eth = data;
+       u16 *s = (u16 *)eth->h_source;
+       u16 *d = (u16 *)eth->h_dest;
+
+       wil_swap_u16(s++, d++);
+       wil_swap_u16(s++, d++);
+       wil_swap_u16(s, d);
+}
+
+/**
+ * reap 1 frame from @swhead
+ *
+ * Safe to call from IRQ
+ */
+static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
+                                        struct vring *vring)
+{
+       struct device *dev = wil_to_dev(wil);
+       struct net_device *ndev = wil_to_ndev(wil);
+       volatile struct vring_rx_desc *d;
+       struct sk_buff *skb;
+       dma_addr_t pa;
+       unsigned int sz = RX_BUF_LEN;
+       u8 ftype;
+       u8 ds_bits;
+
+       if (wil_vring_is_empty(vring))
+               return NULL;
+
+       d = &(vring->va[vring->swhead].rx);
+       if (!(d->dma.status & RX_DMA_STATUS_DU)) {
+               /* it is not error, we just reached end of Rx done area */
+               return NULL;
+       }
+
+       pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+       skb = vring->ctx[vring->swhead];
+       dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
+       skb_trim(skb, d->dma.length);
+
+       wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
+
+       /* use radiotap header only if required */
+       if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
+               wil_rx_add_radiotap_header(wil, skb, d);
+
+       wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
+       wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4,
+                         (const void *)d, sizeof(*d), false);
+
+       wil_vring_advance_head(vring, 1);
+
+       /* no extra checks if in sniffer mode */
+       if (ndev->type != ARPHRD_ETHER)
+               return skb;
+       /*
+        * Non-data frames may be delivered through Rx DMA channel (ex: BAR)
+        * Driver should recognize it by frame type, that is found
+        * in Rx descriptor. If type is not data, it is 802.11 frame as is
+        */
+       ftype = wil_rxdesc_ftype(d) << 2;
+       if (ftype != IEEE80211_FTYPE_DATA) {
+               wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype);
+               /* TODO: process it */
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       if (skb->len < ETH_HLEN) {
+               wil_err(wil, "Short frame, len = %d\n", skb->len);
+               /* TODO: process it (i.e. BAR) */
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       ds_bits = wil_rxdesc_ds_bits(d);
+       if (ds_bits == 1) {
+               /*
+                * HW bug - in ToDS mode, i.e. Rx on AP side,
+                * addresses get swapped
+                */
+               wil_swap_ethaddr(skb->data);
+       }
+
+       return skb;
+}
+
+/**
+ * allocate and fill up to @count buffers in rx ring
+ * buffers posted at @swtail
+ */
+static int wil_rx_refill(struct wil6210_priv *wil, int count)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct vring *v = &wil->vring_rx;
+       u32 next_tail;
+       int rc = 0;
+       int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ?
+                       WIL6210_RTAP_SIZE : 0;
+
+       for (; next_tail = wil_vring_next_tail(v),
+                       (next_tail != v->swhead) && (count-- > 0);
+                       v->swtail = next_tail) {
+               rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom);
+               if (rc) {
+                       wil_err(wil, "Error %d in wil_rx_refill[%d]\n",
+                               rc, v->swtail);
+                       break;
+               }
+       }
+       iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail));
+
+       return rc;
+}
+
+/*
+ * Pass Rx packet to the netif. Update statistics.
+ */
+static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
+{
+       int rc;
+       unsigned int len = skb->len;
+
+       if (in_interrupt())
+               rc = netif_rx(skb);
+       else
+               rc = netif_rx_ni(skb);
+
+       if (likely(rc == NET_RX_SUCCESS)) {
+               ndev->stats.rx_packets++;
+               ndev->stats.rx_bytes += len;
+
+       } else {
+               ndev->stats.rx_dropped++;
+       }
+}
+
+/**
+ * Proceed all completed skb's from Rx VRING
+ *
+ * Safe to call from IRQ
+ */
+void wil_rx_handle(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct vring *v = &wil->vring_rx;
+       struct sk_buff *skb;
+
+       if (!v->va) {
+               wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
+               return;
+       }
+       wil_dbg_TXRX(wil, "%s()\n", __func__);
+       while (NULL != (skb = wil_vring_reap_rx(wil, v))) {
+               wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
+                                 skb->data, skb_headlen(skb), false);
+
+               skb_orphan(skb);
+
+               if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+                       skb->dev = ndev;
+                       skb_reset_mac_header(skb);
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       skb->pkt_type = PACKET_OTHERHOST;
+                       skb->protocol = htons(ETH_P_802_2);
+
+               } else {
+                       skb->protocol = eth_type_trans(skb, ndev);
+               }
+
+               wil_netif_rx_any(skb, ndev);
+       }
+       wil_rx_refill(wil, v->size);
+}
+
+int wil_rx_init(struct wil6210_priv *wil)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *wdev = wil->wdev;
+       struct vring *vring = &wil->vring_rx;
+       int rc;
+       struct wmi_cfg_rx_chain_cmd cmd = {
+               .action = WMI_RX_CHAIN_ADD,
+               .rx_sw_ring = {
+                       .max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
+               },
+               .mid = 0, /* TODO - what is it? */
+               .decap_trans_type = WMI_DECAP_TYPE_802_3,
+       };
+       struct {
+               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cfg_rx_chain_done_event evt;
+       } __packed evt;
+
+       vring->size = WIL6210_RX_RING_SIZE;
+       rc = wil_vring_alloc(wil, vring);
+       if (rc)
+               return rc;
+
+       cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
+       cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size);
+       if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
+               struct ieee80211_channel *ch = wdev->preset_chandef.chan;
+
+               cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
+               if (ch)
+                       cmd.sniffer_cfg.channel = ch->hw_value - 1;
+               cmd.sniffer_cfg.phy_info_mode =
+                       cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
+               cmd.sniffer_cfg.phy_support =
+                       cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
+                                   ? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
+       }
+       /* typical time for secure PCP is 840ms */
+       rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
+                     WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
+       if (rc)
+               goto err_free;
+
+       vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
+
+       wil_dbg(wil, "Rx init: status %d tail 0x%08x\n",
+               le32_to_cpu(evt.evt.status), vring->hwtail);
+
+       rc = wil_rx_refill(wil, vring->size);
+       if (rc)
+               goto err_free;
+
+       return 0;
+ err_free:
+       wil_vring_free(wil, vring, 0);
+
+       return rc;
+}
+
+void wil_rx_fini(struct wil6210_priv *wil)
+{
+       struct vring *vring = &wil->vring_rx;
+
+       if (vring->va) {
+               int rc;
+               struct wmi_cfg_rx_chain_cmd cmd = {
+                       .action = cpu_to_le32(WMI_RX_CHAIN_DEL),
+                       .rx_sw_ring = {
+                               .max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
+                       },
+               };
+               struct {
+                       struct wil6210_mbox_hdr_wmi wmi;
+                       struct wmi_cfg_rx_chain_done_event cfg;
+               } __packed wmi_rx_cfg_reply;
+
+               rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
+                             WMI_CFG_RX_CHAIN_DONE_EVENTID,
+                             &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply),
+                             100);
+               wil_vring_free(wil, vring, 0);
+       }
+}
+
+int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+                     int cid, int tid)
+{
+       int rc;
+       struct wmi_vring_cfg_cmd cmd = {
+               .action = cpu_to_le32(WMI_VRING_CMD_ADD),
+               .vring_cfg = {
+                       .tx_sw_ring = {
+                               .max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
+                       },
+                       .ringid = id,
+                       .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4),
+                       .encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
+                       .mac_ctrl = 0,
+                       .to_resolution = 0,
+                       .agg_max_wsize = 16,
+                       .schd_params = {
+                               .priority = cpu_to_le16(0),
+                               .timeslot_us = cpu_to_le16(0xfff),
+                       },
+               },
+       };
+       struct {
+               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_vring_cfg_done_event cmd;
+       } __packed reply;
+       struct vring *vring = &wil->vring_tx[id];
+
+       if (vring->va) {
+               wil_err(wil, "Tx ring [%d] already allocated\n", id);
+               rc = -EINVAL;
+               goto out;
+       }
+
+       vring->size = size;
+       rc = wil_vring_alloc(wil, vring);
+       if (rc)
+               goto out;
+
+       cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
+       cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size);
+
+       rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
+                     WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
+       if (rc)
+               goto out_free;
+
+       if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
+               wil_err(wil, "Tx config failed, status 0x%02x\n",
+                       reply.cmd.status);
+               goto out_free;
+       }
+       vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
+
+       return 0;
+ out_free:
+       wil_vring_free(wil, vring, 1);
+ out:
+
+       return rc;
+}
+
+void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
+{
+       struct vring *vring = &wil->vring_tx[id];
+
+       if (!vring->va)
+               return;
+
+       wil_vring_free(wil, vring, 1);
+}
+
+static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
+                                      struct sk_buff *skb)
+{
+       struct vring *v = &wil->vring_tx[0];
+
+       if (v->va)
+               return v;
+
+       return NULL;
+}
+
+static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
+                          dma_addr_t pa, u32 len)
+{
+       d->dma.addr_low = lower_32_bits(pa);
+       d->dma.addr_high = (u16)upper_32_bits(pa);
+       d->dma.ip_length = 0;
+       /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/
+       d->dma.b11 = 0/*14 | BIT(7)*/;
+       d->dma.error = 0;
+       d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
+       d->dma.length = len;
+       d->dma.d0 = 0;
+       d->mac.d[0] = 0;
+       d->mac.d[1] = 0;
+       d->mac.d[2] = 0;
+       d->mac.ucode_cmd = 0;
+       /* use dst index 0 */
+       d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) |
+                      (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS);
+       /* translation type:  0 - bypass; 1 - 802.3; 2 - native wifi */
+       d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) |
+                     (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS);
+
+       return 0;
+}
+
+static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
+                       struct sk_buff *skb)
+{
+       struct device *dev = wil_to_dev(wil);
+       volatile struct vring_tx_desc *d;
+       u32 swhead = vring->swhead;
+       int avail = wil_vring_avail_tx(vring);
+       int nr_frags = skb_shinfo(skb)->nr_frags;
+       uint f;
+       int vring_index = vring - wil->vring_tx;
+       uint i = swhead;
+       dma_addr_t pa;
+
+       wil_dbg_TXRX(wil, "%s()\n", __func__);
+
+       if (avail < vring->size/8)
+               netif_tx_stop_all_queues(wil_to_ndev(wil));
+       if (avail < 1 + nr_frags) {
+               wil_err(wil, "Tx ring full. No space for %d fragments\n",
+                       1 + nr_frags);
+               return -ENOMEM;
+       }
+       d = &(vring->va[i].tx);
+
+       /* FIXME FW can accept only unicast frames for the peer */
+       memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);
+
+       pa = dma_map_single(dev, skb->data,
+                       skb_headlen(skb), DMA_TO_DEVICE);
+
+       wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
+                    skb->data, (unsigned long long)pa);
+       wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
+                         skb->data, skb_headlen(skb), false);
+
+       if (unlikely(dma_mapping_error(dev, pa)))
+               return -EINVAL;
+       /* 1-st segment */
+       wil_tx_desc_map(d, pa, skb_headlen(skb));
+       d->mac.d[2] |= ((nr_frags + 1) <<
+                      MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
+       /* middle segments */
+       for (f = 0; f < nr_frags; f++) {
+               const struct skb_frag_struct *frag =
+                               &skb_shinfo(skb)->frags[f];
+               int len = skb_frag_size(frag);
+               i = (swhead + f + 1) % vring->size;
+               d = &(vring->va[i].tx);
+               pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
+                               DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(dev, pa)))
+                       goto dma_error;
+               wil_tx_desc_map(d, pa, len);
+               vring->ctx[i] = NULL;
+       }
+       /* for the last seg only */
+       d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
+       d->dma.d0 |= BIT(9); /* BUG: undocumented bit */
+       d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
+       d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
+
+       wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4,
+                         (const void *)d, sizeof(*d), false);
+
+       /* advance swhead */
+       wil_vring_advance_head(vring, nr_frags + 1);
+       wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
+       iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
+       /* hold reference to skb
+        * to prevent skb release before accounting
+        * in case of immediate "tx done"
+        */
+       vring->ctx[i] = skb_get(skb);
+
+       return 0;
+ dma_error:
+       /* unmap what we have mapped */
+       /* Note: increment @f to operate with positive index */
+       for (f++; f > 0; f--) {
+               i = (swhead + f) % vring->size;
+               d = &(vring->va[i].tx);
+               d->dma.status = TX_DMA_STATUS_DU;
+               pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+               if (vring->ctx[i])
+                       dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+               else
+                       dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+       }
+
+       return -EINVAL;
+}
+
+
+netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       struct wil6210_priv *wil = ndev_to_wil(ndev);
+       struct vring *vring;
+       int rc;
+
+       wil_dbg_TXRX(wil, "%s()\n", __func__);
+       if (!test_bit(wil_status_fwready, &wil->status)) {
+               wil_err(wil, "FW not ready\n");
+               goto drop;
+       }
+       if (!test_bit(wil_status_fwconnected, &wil->status)) {
+               wil_err(wil, "FW not connected\n");
+               goto drop;
+       }
+       if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+               wil_err(wil, "Xmit in monitor mode not supported\n");
+               goto drop;
+       }
+       if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+               rc = wmi_tx_eapol(wil, skb);
+       } else {
+               /* find vring */
+               vring = wil_find_tx_vring(wil, skb);
+               if (!vring) {
+                       wil_err(wil, "No Tx VRING available\n");
+                       goto drop;
+               }
+               /* set up vring entry */
+               rc = wil_tx_vring(wil, vring, skb);
+       }
+       switch (rc) {
+       case 0:
+               ndev->stats.tx_packets++;
+               ndev->stats.tx_bytes += skb->len;
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
+       case -ENOMEM:
+               return NETDEV_TX_BUSY;
+       default:
+               ; /* goto drop; */
+               break;
+       }
+ drop:
+       netif_tx_stop_all_queues(ndev);
+       ndev->stats.tx_dropped++;
+       dev_kfree_skb_any(skb);
+
+       return NET_XMIT_DROP;
+}
+
+/**
+ * Clean up transmitted skb's from the Tx VRING
+ *
+ * Safe to call from IRQ
+ */
+void wil_tx_complete(struct wil6210_priv *wil, int ringid)
+{
+       struct device *dev = wil_to_dev(wil);
+       struct vring *vring = &wil->vring_tx[ringid];
+
+       if (!vring->va) {
+               wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid);
+               return;
+       }
+
+       wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid);
+
+       while (!wil_vring_is_empty(vring)) {
+               volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
+               dma_addr_t pa;
+               struct sk_buff *skb;
+               if (!(d->dma.status & TX_DMA_STATUS_DU))
+                       break;
+
+               wil_dbg_TXRX(wil,
+                            "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
+                            vring->swtail, d->dma.length, d->dma.status,
+                            d->dma.error);
+               wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4,
+                                 (const void *)d, sizeof(*d), false);
+
+               pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+               skb = vring->ctx[vring->swtail];
+               if (skb) {
+                       dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+                       dev_kfree_skb_any(skb);
+                       vring->ctx[vring->swtail] = NULL;
+               } else {
+                       dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+               }
+               d->dma.addr_low = 0;
+               d->dma.addr_high = 0;
+               d->dma.length = 0;
+               d->dma.status = TX_DMA_STATUS_DU;
+               vring->swtail = wil_vring_next_tail(vring);
+       }
+       if (wil_vring_avail_tx(vring) > vring->size/4)
+               netif_tx_wake_all_queues(wil_to_ndev(wil));
+}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
new file mode 100644 (file)
index 0000000..45a61f5
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef WIL6210_TXRX_H
+#define WIL6210_TXRX_H
+
+#define BUF_SW_OWNED    (1)
+#define BUF_HW_OWNED    (0)
+
+/* size of max. Rx packet */
+#define RX_BUF_LEN      (2048)
+#define TX_BUF_LEN      (2048)
+/* how many bytes to reserve for rtap header? */
+#define WIL6210_RTAP_SIZE (128)
+
+/* Tx/Rx path */
+/*
+ * Tx descriptor - MAC part
+ * [dword 0]
+ * bit  0.. 9 : lifetime_expiry_value:10
+ * bit     10 : interrup_en:1
+ * bit     11 : status_en:1
+ * bit 12..13 : txss_override:2
+ * bit     14 : timestamp_insertion:1
+ * bit     15 : duration_preserve:1
+ * bit 16..21 : reserved0:6
+ * bit 22..26 : mcs_index:5
+ * bit     27 : mcs_en:1
+ * bit 28..29 : reserved1:2
+ * bit     30 : reserved2:1
+ * bit     31 : sn_preserved:1
+ * [dword 1]
+ * bit  0.. 3 : pkt_mode:4
+ * bit      4 : pkt_mode_en:1
+ * bit  5.. 7 : reserved0:3
+ * bit  8..13 : reserved1:6
+ * bit     14 : reserved2:1
+ * bit     15 : ack_policy_en:1
+ * bit 16..19 : dst_index:4
+ * bit     20 : dst_index_en:1
+ * bit 21..22 : ack_policy:2
+ * bit     23 : lifetime_en:1
+ * bit 24..30 : max_retry:7
+ * bit     31 : max_retry_en:1
+ * [dword 2]
+ * bit  0.. 7 : num_of_descriptors:8
+ * bit  8..17 : reserved:10
+ * bit 18..19 : l2_translation_type:2
+ * bit     20 : snap_hdr_insertion_en:1
+ * bit     21 : vlan_removal_en:1
+ * bit 22..31 : reserved0:10
+ * [dword 3]
+ * bit  0.. 31: ucode_cmd:32
+ */
+struct vring_tx_mac {
+       u32 d[3];
+       u32 ucode_cmd;
+} __packed;
+
+/* TX MAC Dword 0 */
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF
+
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400
+
+#define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11
+#define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800
+
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000
+
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000
+
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000
+
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000
+
+#define MAC_CFG_DESC_TX_0_MCS_EN_POS 27
+#define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000
+
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000
+
+/* TX MAC Dword 1 */
+#define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0
+#define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4
+#define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF
+
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10
+
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000
+
+#define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16
+#define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4
+#define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000
+
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000
+
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000
+
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000
+
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000
+
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000
+
+/* TX MAC Dword 2 */
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF
+
+#define MAC_CFG_DESC_TX_2_RESERVED_POS 8
+#define MAC_CFG_DESC_TX_2_RESERVED_LEN 10
+#define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00
+
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000
+
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000
+
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000
+
+/* TX MAC Dword 3 */
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF
+
+/* TX DMA Dword 0 */
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF
+
+#define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8
+#define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1
+#define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100
+
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400
+
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800
+
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000
+
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000
+
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000
+
+#define DMA_CFG_DESC_TX_0_QID_POS 16
+#define DMA_CFG_DESC_TX_0_QID_LEN 5
+#define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000
+
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000
+
+#define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30
+#define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2
+#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000
+
+
+#define TX_DMA_STATUS_DU         BIT(0)
+
+struct vring_tx_dma {
+       u32 d0;
+       u32 addr_low;
+       u16 addr_high;
+       u8  ip_length;
+       u8  b11;       /* 0..6: mac_length; 7:ip_version */
+       u8  error;     /* 0..2: err; 3..7: reserved; */
+       u8  status;    /* 0: used; 1..7; reserved */
+       u16 length;
+} __packed;
+
+/*
+ * Rx descriptor - MAC part
+ * [dword 0]
+ * bit  0.. 3 : tid:4 The QoS (b3-0) TID Field
+ * bit  4.. 6 : connection_id:3 :The Source index that  was found during
+ *  Parsing the TA.  This field is used to  define the source of the packet
+ * bit      7 : reserved:1
+ * bit  8.. 9 : mac_id:2 : The MAC virtual  Ring number (always zero)
+ * bit 10..11 : frame_type:2 : The FC Control  (b3-2) -  MPDU Type
+ *              (management, data, control  and extension)
+ * bit 12..15 : frame_subtype:4 : The FC Control  (b7-4) -  Frame Subtype
+ * bit 16..27 : seq_number:12 The received Sequence number field
+ * bit 28..31 : extended:4 extended subtype
+ * [dword 1]
+ * bit  0.. 3 : reserved
+ * bit  4.. 5 : key_id:2
+ * bit      6 : decrypt_bypass:1
+ * bit      7 : security:1
+ * bit  8.. 9 : ds_bits:2
+ * bit     10 : a_msdu_present:1  from qos header
+ * bit     11 : a_msdu_type:1  from qos header
+ * bit     12 : a_mpdu:1  part of AMPDU aggregation
+ * bit     13 : broadcast:1
+ * bit     14 : mutlicast:1
+ * bit     15 : reserved:1
+ * bit 16..20 : rx_mac_qid:5   The Queue Identifier that the packet
+ *                             is received from
+ * bit 21..24 : mcs:4
+ * bit 25..28 : mic_icr:4
+ * bit 29..31 : reserved:3
+ * [dword 2]
+ * bit  0.. 2 : time_slot:3 The timeslot that the MPDU is received
+ * bit      3 : fc_protocol_ver:1 The FC Control  (b0) - Protocol  Version
+ * bit      4 : fc_order:1 The FC Control (b15) -Order
+ * bit  5.. 7 : qos_ack_policy:3  The QoS (b6-5) ack policy Field
+ * bit      8 : esop:1 The QoS (b4) ESOP field
+ * bit      9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG  field
+ * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved  field
+ * bit     15 : qos_ac_constraint:1
+ * bit 16..31 : pn_15_0:16 low 2 bytes of PN
+ * [dword 3]
+ * bit  0..31 : pn_47_16:32 high 4 bytes of PN
+ */
+struct vring_rx_mac {
+       u32 d0;
+       u32 d1;
+       u16 w4;
+       u16 pn_15_0;
+       u32 pn_47_16;
+} __packed;
+
+/*
+ * Rx descriptor - DMA part
+ * [dword 0]
+ * bit  0.. 7 : l4_length:8 layer 4 length
+ * bit  8.. 9 : reserved:2
+ * bit     10 : cmd_dma_it:1
+ * bit 11..15 : reserved:5
+ * bit 16..29 : phy_info_length:14
+ * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field
+ * [dword 1]
+ * bit  0..31 : addr_low:32 The payload buffer low address
+ * [dword 2]
+ * bit  0..15 : addr_high:16 The payload buffer high address
+ * bit 16..23 : ip_length:8
+ * bit 24..30 : mac_length:7
+ * bit     31 : ip_version:1
+ * [dword 3]
+ *  [byte 12] error
+ *  [byte 13] status
+ * bit      0 : du:1
+ * bit      1 : eop:1
+ * bit      2 : error:1
+ * bit      3 : mi:1
+ * bit      4 : l3_identified:1
+ * bit      5 : l4_identified:1
+ * bit      6 : phy_info_included:1
+ * bit      7 : reserved:1
+ *  [word 7] length
+ *
+ */
+
+#define RX_DMA_D0_CMD_DMA_IT     BIT(10)
+
+#define RX_DMA_STATUS_DU         BIT(0)
+#define RX_DMA_STATUS_ERROR      BIT(2)
+#define RX_DMA_STATUS_PHY_INFO   BIT(6)
+
+struct vring_rx_dma {
+       u32 d0;
+       u32 addr_low;
+       u16 addr_high;
+       u8  ip_length;
+       u8  b11;
+       u8  error;
+       u8  status;
+       u16 length;
+} __packed;
+
+struct vring_tx_desc {
+       struct vring_tx_mac mac;
+       struct vring_tx_dma dma;
+} __packed;
+
+struct vring_rx_desc {
+       struct vring_rx_mac mac;
+       struct vring_rx_dma dma;
+} __packed;
+
+union vring_desc {
+       struct vring_tx_desc tx;
+       struct vring_rx_desc rx;
+} __packed;
+
+static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->dma.d0, 16, 29);
+}
+
+static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->mac.d1, 21, 24);
+}
+
+static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->mac.d1, 8, 9);
+}
+
+static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->mac.d0, 10, 11);
+}
+
+#endif /* WIL6210_TXRX_H */
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
new file mode 100644 (file)
index 0000000..9bcfffa
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __WIL6210_H__
+#define __WIL6210_H__
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+
+#include "dbg_hexdump.h"
+
+#define WIL_NAME "wil6210"
+
+/**
+ * extract bits [@b0:@b1] (inclusive) from the value @x
+ * it should be @b0 <= @b1, or result is incorrect
+ */
+static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
+{
+       return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1);
+}
+
+#define WIL6210_MEM_SIZE (2*1024*1024UL)
+
+#define WIL6210_TX_QUEUES (4)
+
+#define WIL6210_RX_RING_SIZE (128)
+#define WIL6210_TX_RING_SIZE (128)
+#define WIL6210_MAX_TX_RINGS (24)
+
+/* Hardware definitions begin */
+
+/*
+ * Mapping
+ * RGF File      | Host addr    |  FW addr
+ *               |              |
+ * user_rgf      | 0x000000     | 0x880000
+ *  dma_rgf      | 0x001000     | 0x881000
+ * pcie_rgf      | 0x002000     | 0x882000
+ *               |              |
+ */
+
+/* Where various structures placed in host address space */
+#define WIL6210_FW_HOST_OFF      (0x880000UL)
+
+#define HOSTADDR(fwaddr)        (fwaddr - WIL6210_FW_HOST_OFF)
+
+/*
+ * Interrupt control registers block
+ *
+ * each interrupt controlled by the same bit in all registers
+ */
+struct RGF_ICR {
+       u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */
+       u32 ICR; /* Cause, W1C/COR depending on ICC */
+       u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */
+       u32 ICS; /* Cause Set, WO */
+       u32 IMV; /* Mask, RW+S/C */
+       u32 IMS; /* Mask Set, write 1 to set */
+       u32 IMC; /* Mask Clear, write 1 to clear */
+} __packed;
+
+/* registers - FW addresses */
+#define RGF_USER_USER_SCRATCH_PAD      (0x8802bc)
+#define RGF_USER_USER_ICR              (0x880b4c) /* struct RGF_ICR */
+       #define BIT_USER_USER_ICR_SW_INT_2      BIT(18)
+#define RGF_USER_CLKS_CTL_SW_RST_MASK_0        (0x880b14)
+#define RGF_USER_MAC_CPU_0             (0x8801fc)
+#define RGF_USER_USER_CPU_0            (0x8801e0)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10)
+
+#define RGF_DMA_PSEUDO_CAUSE           (0x881c68)
+#define RGF_DMA_PSEUDO_CAUSE_MASK_SW   (0x881c6c)
+#define RGF_DMA_PSEUDO_CAUSE_MASK_FW   (0x881c70)
+       #define BIT_DMA_PSEUDO_CAUSE_RX         BIT(0)
+       #define BIT_DMA_PSEUDO_CAUSE_TX         BIT(1)
+       #define BIT_DMA_PSEUDO_CAUSE_MISC       BIT(2)
+
+#define RGF_DMA_EP_TX_ICR              (0x881bb4) /* struct RGF_ICR */
+       #define BIT_DMA_EP_TX_ICR_TX_DONE       BIT(0)
+       #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n)  BIT(n+1) /* n = [0..23] */
+#define RGF_DMA_EP_RX_ICR              (0x881bd0) /* struct RGF_ICR */
+       #define BIT_DMA_EP_RX_ICR_RX_DONE       BIT(0)
+#define RGF_DMA_EP_MISC_ICR            (0x881bec) /* struct RGF_ICR */
+       #define BIT_DMA_EP_MISC_ICR_RX_HTRSH    BIT(0)
+       #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT   BIT(1)
+       #define BIT_DMA_EP_MISC_ICR_FW_INT0     BIT(28)
+       #define BIT_DMA_EP_MISC_ICR_FW_INT1     BIT(29)
+
+/* Interrupt moderation control */
+#define RGF_DMA_ITR_CNT_TRSH           (0x881c5c)
+#define RGF_DMA_ITR_CNT_DATA           (0x881c60)
+#define RGF_DMA_ITR_CNT_CRL            (0x881C64)
+       #define BIT_DMA_ITR_CNT_CRL_EN          BIT(0)
+       #define BIT_DMA_ITR_CNT_CRL_EXT_TICK    BIT(1)
+       #define BIT_DMA_ITR_CNT_CRL_FOREVER     BIT(2)
+       #define BIT_DMA_ITR_CNT_CRL_CLR         BIT(3)
+       #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH  BIT(4)
+
+/* popular locations */
+#define HOST_MBOX   HOSTADDR(RGF_USER_USER_SCRATCH_PAD)
+#define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \
+       offsetof(struct RGF_ICR, ICS))
+#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2
+
+/* ISR register bits */
+#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0
+#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1
+
+/* Hardware definitions end */
+
+struct wil6210_mbox_ring {
+       u32 base;
+       u16 entry_size; /* max. size of mbox entry, incl. all headers */
+       u16 size;
+       u32 tail;
+       u32 head;
+} __packed;
+
+struct wil6210_mbox_ring_desc {
+       __le32 sync;
+       __le32 addr;
+} __packed;
+
+/* at HOST_OFF_WIL6210_MBOX_CTL */
+struct wil6210_mbox_ctl {
+       struct wil6210_mbox_ring tx;
+       struct wil6210_mbox_ring rx;
+} __packed;
+
+struct wil6210_mbox_hdr {
+       __le16 seq;
+       __le16 len; /* payload, bytes after this header */
+       __le16 type;
+       u8 flags;
+       u8 reserved;
+} __packed;
+
+#define WIL_MBOX_HDR_TYPE_WMI (0)
+
+/* max. value for wil6210_mbox_hdr.len */
+#define MAX_MBOXITEM_SIZE   (240)
+
+struct wil6210_mbox_hdr_wmi {
+       u8 reserved0[2];
+       __le16 id;
+       __le16 info1; /* bits [0..3] - device_id, rest - unused */
+       u8 reserved1[2];
+} __packed;
+
+struct pending_wmi_event {
+       struct list_head list;
+       struct {
+               struct wil6210_mbox_hdr hdr;
+               struct wil6210_mbox_hdr_wmi wmi;
+               u8 data[0];
+       } __packed event;
+};
+
+union vring_desc;
+
+struct vring {
+       dma_addr_t pa;
+       volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */
+       u16 size; /* number of vring_desc elements */
+       u32 swtail;
+       u32 swhead;
+       u32 hwtail; /* write here to inform hw */
+       void **ctx; /* void *ctx[size] - software context */
+};
+
+enum { /* for wil6210_priv.status */
+       wil_status_fwready = 0,
+       wil_status_fwconnected,
+       wil_status_dontscan,
+       wil_status_irqen, /* FIXME: interrupts enabled - for debug */
+};
+
+struct pci_dev;
+
+struct wil6210_stats {
+       u64 tsf;
+       u32 snr;
+       u16 last_mcs_rx;
+       u16 bf_mcs; /* last BF, used for Tx */
+       u16 my_rx_sector;
+       u16 my_tx_sector;
+       u16 peer_rx_sector;
+       u16 peer_tx_sector;
+};
+
+struct wil6210_priv {
+       struct pci_dev *pdev;
+       int n_msi;
+       struct wireless_dev *wdev;
+       void __iomem *csr;
+       ulong status;
+       /* profile */
+       u32 monitor_flags;
+       u32 secure_pcp; /* create secure PCP? */
+       int sinfo_gen;
+       /* cached ISR registers */
+       u32 isr_misc;
+       /* mailbox related */
+       struct mutex wmi_mutex;
+       struct wil6210_mbox_ctl mbox_ctl;
+       struct completion wmi_ready;
+       u16 wmi_seq;
+       u16 reply_id; /**< wait for this WMI event */
+       void *reply_buf;
+       u16 reply_size;
+       struct workqueue_struct *wmi_wq; /* for deferred calls */
+       struct work_struct wmi_event_worker;
+       struct workqueue_struct *wmi_wq_conn; /* for connect worker */
+       struct work_struct wmi_connect_worker;
+       struct work_struct disconnect_worker;
+       struct timer_list connect_timer;
+       int pending_connect_cid;
+       struct list_head pending_wmi_ev;
+       /*
+        * protect pending_wmi_ev
+        * - fill in IRQ from wil6210_irq_misc,
+        * - consumed in thread by wmi_event_worker
+        */
+       spinlock_t wmi_ev_lock;
+       /* DMA related */
+       struct vring vring_rx;
+       struct vring vring_tx[WIL6210_MAX_TX_RINGS];
+       u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN];
+       /* scan */
+       struct cfg80211_scan_request *scan_request;
+
+       struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
+       /* statistics */
+       struct wil6210_stats stats;
+       /* debugfs */
+       struct dentry *debug;
+       struct debugfs_blob_wrapper fw_code_blob;
+       struct debugfs_blob_wrapper fw_data_blob;
+       struct debugfs_blob_wrapper fw_peri_blob;
+       struct debugfs_blob_wrapper uc_code_blob;
+       struct debugfs_blob_wrapper uc_data_blob;
+       struct debugfs_blob_wrapper rgf_blob;
+};
+
+#define wil_to_wiphy(i) (i->wdev->wiphy)
+#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i)))
+#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w))
+#define wil_to_wdev(i) (i->wdev)
+#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
+#define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
+#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
+
+#define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg)
+#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg)
+#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg)
+
+#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
+#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
+#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
+
+#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize,    \
+                         groupsize, buf, len, ascii)           \
+                         wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
+                                        prefix_type, rowsize,  \
+                                        groupsize, buf, len, ascii)
+
+#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize,     \
+                        groupsize, buf, len, ascii)            \
+                        wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
+                                       prefix_type, rowsize,   \
+                                       groupsize, buf, len, ascii)
+
+void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
+                         size_t count);
+void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
+                       size_t count);
+
+void *wil_if_alloc(struct device *dev, void __iomem *csr);
+void wil_if_free(struct wil6210_priv *wil);
+int wil_if_add(struct wil6210_priv *wil);
+void wil_if_remove(struct wil6210_priv *wil);
+int wil_priv_init(struct wil6210_priv *wil);
+void wil_priv_deinit(struct wil6210_priv *wil);
+int wil_reset(struct wil6210_priv *wil);
+void wil_link_on(struct wil6210_priv *wil);
+void wil_link_off(struct wil6210_priv *wil);
+int wil_up(struct wil6210_priv *wil);
+int wil_down(struct wil6210_priv *wil);
+void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
+
+void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr);
+void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
+int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
+                struct wil6210_mbox_hdr *hdr);
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len);
+void wmi_recv_cmd(struct wil6210_priv *wil);
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+            u16 reply_id, void *reply, u8 reply_size, int to_msec);
+void wmi_connect_worker(struct work_struct *work);
+void wmi_event_worker(struct work_struct *work);
+void wmi_event_flush(struct wil6210_priv *wil);
+int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid);
+int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid);
+int wmi_set_channel(struct wil6210_priv *wil, int channel);
+int wmi_get_channel(struct wil6210_priv *wil, int *channel);
+int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb);
+int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+                      const void *mac_addr);
+int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+                      const void *mac_addr, int key_len, const void *key);
+int wmi_echo(struct wil6210_priv *wil);
+int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
+
+int wil6210_init_irq(struct wil6210_priv *wil, int irq);
+void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
+void wil6210_disable_irq(struct wil6210_priv *wil);
+void wil6210_enable_irq(struct wil6210_priv *wil);
+
+int wil6210_debugfs_init(struct wil6210_priv *wil);
+void wil6210_debugfs_remove(struct wil6210_priv *wil);
+
+struct wireless_dev *wil_cfg80211_init(struct device *dev);
+void wil_wdev_free(struct wil6210_priv *wil);
+
+int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
+int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype);
+void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
+
+int wil_rx_init(struct wil6210_priv *wil);
+void wil_rx_fini(struct wil6210_priv *wil);
+
+/* TX API */
+int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+                     int cid, int tid);
+void wil_vring_fini_tx(struct wil6210_priv *wil, int id);
+
+netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+void wil_tx_complete(struct wil6210_priv *wil, int ringid);
+
+/* RX API */
+void wil_rx_handle(struct wil6210_priv *wil);
+
+int wil_iftype_nl2wmi(enum nl80211_iftype type);
+
+#endif /* __WIL6210_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
new file mode 100644 (file)
index 0000000..12915f6
--- /dev/null
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/etherdevice.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+
+/**
+ * WMI event receiving - theory of operations
+ *
+ * When firmware about to report WMI event, it fills memory area
+ * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
+ * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
+ *
+ * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
+ * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
+ * and handles events within the @wmi_event_worker. Every event get detached
+ * from list, processed and deleted.
+ *
+ * Purpose for this mechanism is to release IRQ thread; otherwise,
+ * if WMI event handling involves another WMI command flow, this 2-nd flow
+ * won't be completed because of blocked IRQ thread.
+ */
+
+/**
+ * Addressing - theory of operations
+ *
+ * There are several buses present on the WIL6210 card.
+ * Same memory areas are visible at different address on
+ * the different busses. There are 3 main bus masters:
+ *  - MAC CPU (ucode)
+ *  - User CPU (firmware)
+ *  - AHB (host)
+ *
+ * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
+ * AHB addresses starting from 0x880000
+ *
+ * Internally, firmware uses addresses that allows faster access but
+ * are invisible from the host. To read from these addresses, alternative
+ * AHB address must be used.
+ *
+ * Memory mapping
+ * Linker address         PCI/Host address
+ *                        0x880000 .. 0xa80000  2Mb BAR0
+ * 0x800000 .. 0x807000   0x900000 .. 0x907000  28k DCCM
+ * 0x840000 .. 0x857000   0x908000 .. 0x91f000  92k PERIPH
+ */
+
+/**
+ * @fw_mapping provides memory remapping table
+ */
+static const struct {
+       u32 from; /* linker address - from, inclusive */
+       u32 to;   /* linker address - to, exclusive */
+       u32 host; /* PCI/Host address - BAR0 + 0x880000 */
+} fw_mapping[] = {
+       {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */
+       {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */
+       {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */
+       {0x880000, 0x88a000, 0x880000}, /* various RGF */
+       {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */
+       /*
+        * 920000..930000 ucode code RAM
+        * 930000..932000 ucode data RAM
+        */
+};
+
+/**
+ * return AHB address for given firmware/ucode internal (linker) address
+ * @x - internal address
+ * If address have no valid AHB mapping, return 0
+ */
+static u32 wmi_addr_remap(u32 x)
+{
+       uint i;
+
+       for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+               if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))
+                       return x + fw_mapping[i].host - fw_mapping[i].from;
+       }
+
+       return 0;
+}
+
+/**
+ * Check address validity for WMI buffer; remap if needed
+ * @ptr - internal (linker) fw/ucode address
+ *
+ * Valid buffer should be DWORD aligned
+ *
+ * return address for accessing buffer from the host;
+ * if buffer is not valid, return NULL.
+ */
+void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
+{
+       u32 off;
+       u32 ptr = le32_to_cpu(ptr_);
+
+       if (ptr % 4)
+               return NULL;
+
+       ptr = wmi_addr_remap(ptr);
+       if (ptr < WIL6210_FW_HOST_OFF)
+               return NULL;
+
+       off = HOSTADDR(ptr);
+       if (off > WIL6210_MEM_SIZE - 4)
+               return NULL;
+
+       return wil->csr + off;
+}
+
+/**
+ * Check address validity
+ */
+void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
+{
+       u32 off;
+
+       if (ptr % 4)
+               return NULL;
+
+       if (ptr < WIL6210_FW_HOST_OFF)
+               return NULL;
+
+       off = HOSTADDR(ptr);
+       if (off > WIL6210_MEM_SIZE - 4)
+               return NULL;
+
+       return wil->csr + off;
+}
+
+int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
+                struct wil6210_mbox_hdr *hdr)
+{
+       void __iomem *src = wmi_buffer(wil, ptr);
+       if (!src)
+               return -EINVAL;
+
+       wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
+
+       return 0;
+}
+
+static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+{
+       struct {
+               struct wil6210_mbox_hdr hdr;
+               struct wil6210_mbox_hdr_wmi wmi;
+       } __packed cmd = {
+               .hdr = {
+                       .type = WIL_MBOX_HDR_TYPE_WMI,
+                       .flags = 0,
+                       .len = cpu_to_le16(sizeof(cmd.wmi) + len),
+               },
+               .wmi = {
+                       .id = cpu_to_le16(cmdid),
+                       .info1 = 0,
+               },
+       };
+       struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
+       struct wil6210_mbox_ring_desc d_head;
+       u32 next_head;
+       void __iomem *dst;
+       void __iomem *head = wmi_addr(wil, r->head);
+       uint retry;
+
+       if (sizeof(cmd) + len > r->entry_size) {
+               wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
+                       (int)(sizeof(cmd) + len), r->entry_size);
+               return -ERANGE;
+
+       }
+
+       might_sleep();
+
+       if (!test_bit(wil_status_fwready, &wil->status)) {
+               wil_err(wil, "FW not ready\n");
+               return -EAGAIN;
+       }
+
+       if (!head) {
+               wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
+               return -EINVAL;
+       }
+       /* read Tx head till it is not busy */
+       for (retry = 5; retry > 0; retry--) {
+               wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
+               if (d_head.sync == 0)
+                       break;
+               msleep(20);
+       }
+       if (d_head.sync != 0) {
+               wil_err(wil, "WMI head busy\n");
+               return -EBUSY;
+       }
+       /* next head */
+       next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
+       wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
+       /* wait till FW finish with previous command */
+       for (retry = 5; retry > 0; retry--) {
+               r->tail = ioread32(wil->csr + HOST_MBOX +
+                                  offsetof(struct wil6210_mbox_ctl, tx.tail));
+               if (next_head != r->tail)
+                       break;
+               msleep(20);
+       }
+       if (next_head == r->tail) {
+               wil_err(wil, "WMI ring full\n");
+               return -EBUSY;
+       }
+       dst = wmi_buffer(wil, d_head.addr);
+       if (!dst) {
+               wil_err(wil, "invalid WMI buffer: 0x%08x\n",
+                       le32_to_cpu(d_head.addr));
+               return -EINVAL;
+       }
+       cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
+       /* set command */
+       wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
+       wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
+                        sizeof(cmd), true);
+       wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
+                        len, true);
+       wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
+       wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
+       /* mark entry as full */
+       iowrite32(1, wil->csr + HOSTADDR(r->head) +
+                 offsetof(struct wil6210_mbox_ring_desc, sync));
+       /* advance next ptr */
+       iowrite32(r->head = next_head, wil->csr + HOST_MBOX +
+                 offsetof(struct wil6210_mbox_ctl, tx.head));
+
+       /* interrupt to FW */
+       iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT);
+
+       return 0;
+}
+
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+{
+       int rc;
+
+       mutex_lock(&wil->wmi_mutex);
+       rc = __wmi_send(wil, cmdid, buf, len);
+       mutex_unlock(&wil->wmi_mutex);
+
+       return rc;
+}
+
+/*=== Event handlers ===*/
+static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *wdev = wil->wdev;
+       struct wmi_ready_event *evt = d;
+       u32 ver = le32_to_cpu(evt->sw_version);
+
+       wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
+
+       if (!is_valid_ether_addr(ndev->dev_addr)) {
+               memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
+               memcpy(ndev->perm_addr, evt->mac, ETH_ALEN);
+       }
+       snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
+                "%d", ver);
+}
+
+static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
+                            int len)
+{
+       wil_dbg_WMI(wil, "WMI: FW ready\n");
+
+       set_bit(wil_status_fwready, &wil->status);
+       /* reuse wmi_ready for the firmware ready indication */
+       complete(&wil->wmi_ready);
+}
+
+static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
+{
+       struct wmi_rx_mgmt_packet_event *data = d;
+       struct wiphy *wiphy = wil_to_wiphy(wil);
+       struct ieee80211_mgmt *rx_mgmt_frame =
+                       (struct ieee80211_mgmt *)data->payload;
+       int ch_no = data->info.channel+1;
+       u32 freq = ieee80211_channel_to_frequency(ch_no,
+                       IEEE80211_BAND_60GHZ);
+       struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq);
+       /* TODO convert LE to CPU */
+       s32 signal = 0; /* TODO */
+       __le16 fc = rx_mgmt_frame->frame_control;
+       u32 d_len = le32_to_cpu(data->info.len);
+       u16 d_status = le16_to_cpu(data->info.status);
+
+       wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n",
+                   data->info.channel, data->info.mcs, data->info.snr);
+       wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
+                   le16_to_cpu(data->info.stype));
+       wil_dbg_WMI(wil, "qid %d mid %d cid %d\n",
+                   data->info.qid, data->info.mid, data->info.cid);
+
+       if (!channel) {
+               wil_err(wil, "Frame on unsupported channel\n");
+               return;
+       }
+
+       if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
+               struct cfg80211_bss *bss;
+               u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
+               u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
+               u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
+               const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
+               size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
+                                                u.beacon.variable);
+               wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap);
+
+               bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
+                                         tsf, cap, bi, ie_buf, ie_len,
+                                         signal, GFP_KERNEL);
+               if (bss) {
+                       wil_dbg_WMI(wil, "Added BSS %pM\n",
+                                   rx_mgmt_frame->bssid);
+                       cfg80211_put_bss(bss);
+               } else {
+                       wil_err(wil, "cfg80211_inform_bss() failed\n");
+               }
+       }
+}
+
+static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
+                                 void *d, int len)
+{
+       if (wil->scan_request) {
+               struct wmi_scan_complete_event *data = d;
+               bool aborted = (data->status != 0);
+
+               wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+               cfg80211_scan_done(wil->scan_request, aborted);
+               wil->scan_request = NULL;
+       } else {
+               wil_err(wil, "SCAN_COMPLETE while not scanning\n");
+       }
+}
+
+static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *wdev = wil->wdev;
+       struct wmi_connect_event *evt = d;
+       int ch; /* channel number */
+       struct station_info sinfo;
+       u8 *assoc_req_ie, *assoc_resp_ie;
+       size_t assoc_req_ielen, assoc_resp_ielen;
+       /* capinfo(u16) + listen_interval(u16) + IEs */
+       const size_t assoc_req_ie_offset = sizeof(u16) * 2;
+       /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
+       const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
+
+       if (len < sizeof(*evt)) {
+               wil_err(wil, "Connect event too short : %d bytes\n", len);
+               return;
+       }
+       if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
+                  evt->assoc_resp_len) {
+               wil_err(wil,
+                       "Connect event corrupted : %d != %d + %d + %d + %d\n",
+                       len, (int)sizeof(*evt), evt->beacon_ie_len,
+                       evt->assoc_req_len, evt->assoc_resp_len);
+               return;
+       }
+       ch = evt->channel + 1;
+       wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n",
+                   evt->bssid, ch, evt->cid);
+       wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
+                        evt->assoc_info, len - sizeof(*evt), true);
+
+       /* figure out IE's */
+       assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
+                                       assoc_req_ie_offset];
+       assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
+       if (evt->assoc_req_len <= assoc_req_ie_offset) {
+               assoc_req_ie = NULL;
+               assoc_req_ielen = 0;
+       }
+
+       assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
+                                        evt->assoc_req_len +
+                                        assoc_resp_ie_offset];
+       assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
+       if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
+               assoc_resp_ie = NULL;
+               assoc_resp_ielen = 0;
+       }
+
+       if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
+           (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+               if (wdev->sme_state != CFG80211_SME_CONNECTING) {
+                       wil_err(wil, "Not in connecting state\n");
+                       return;
+               }
+               del_timer_sync(&wil->connect_timer);
+               cfg80211_connect_result(ndev, evt->bssid,
+                                       assoc_req_ie, assoc_req_ielen,
+                                       assoc_resp_ie, assoc_resp_ielen,
+                                       WLAN_STATUS_SUCCESS, GFP_KERNEL);
+
+       } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
+                  (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
+               memset(&sinfo, 0, sizeof(sinfo));
+
+               sinfo.generation = wil->sinfo_gen++;
+
+               if (assoc_req_ie) {
+                       sinfo.assoc_req_ies = assoc_req_ie;
+                       sinfo.assoc_req_ies_len = assoc_req_ielen;
+                       sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
+               }
+
+               cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
+       }
+       set_bit(wil_status_fwconnected, &wil->status);
+
+       /* FIXME FW can transmit only ucast frames to peer */
+       /* FIXME real ring_id instead of hard coded 0 */
+       memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN);
+
+       wil->pending_connect_cid = evt->cid;
+       queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker);
+}
+
+static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
+                              void *d, int len)
+{
+       struct wmi_disconnect_event *evt = d;
+
+       wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n",
+                   evt->bssid,
+                   evt->protocol_reason_status, evt->disconnect_reason);
+
+       wil->sinfo_gen++;
+
+       wil6210_disconnect(wil, evt->bssid);
+       clear_bit(wil_status_dontscan, &wil->status);
+}
+
+static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
+{
+       struct wmi_notify_req_done_event *evt = d;
+
+       if (len < sizeof(*evt)) {
+               wil_err(wil, "Short NOTIFY event\n");
+               return;
+       }
+
+       wil->stats.tsf = le64_to_cpu(evt->tsf);
+       wil->stats.snr = le32_to_cpu(evt->snr_val);
+       wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs);
+       wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector);
+       wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector);
+       wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector);
+       wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector);
+       wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n"
+                   "BF status 0x%08x SNR 0x%08x\n"
+                   "Tx Tpt %d goodput %d Rx goodput %d\n"
+                   "Sectors(rx:tx) my %d:%d peer %d:%d\n",
+                   wil->stats.bf_mcs, wil->stats.tsf, evt->status,
+                   wil->stats.snr, le32_to_cpu(evt->tx_tpt),
+                   le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput),
+                   wil->stats.my_rx_sector, wil->stats.my_tx_sector,
+                   wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
+}
+
+/*
+ * Firmware reports EAPOL frame using WME event.
+ * Reconstruct Ethernet frame and deliver it via normal Rx
+ */
+static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
+                            void *d, int len)
+{
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wmi_eapol_rx_event *evt = d;
+       u16 eapol_len = le16_to_cpu(evt->eapol_len);
+       int sz = eapol_len + ETH_HLEN;
+       struct sk_buff *skb;
+       struct ethhdr *eth;
+
+       wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len,
+                   evt->src_mac);
+
+       if (eapol_len > 196) { /* TODO: revisit size limit */
+               wil_err(wil, "EAPOL too large\n");
+               return;
+       }
+
+       skb = alloc_skb(sz, GFP_KERNEL);
+       if (!skb) {
+               wil_err(wil, "Failed to allocate skb\n");
+               return;
+       }
+       eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+       memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN);
+       memcpy(eth->h_source, evt->src_mac, ETH_ALEN);
+       eth->h_proto = cpu_to_be16(ETH_P_PAE);
+       memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
+       skb->protocol = eth_type_trans(skb, ndev);
+       if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
+               ndev->stats.rx_packets++;
+               ndev->stats.rx_bytes += skb->len;
+       } else {
+               ndev->stats.rx_dropped++;
+       }
+}
+
+static const struct {
+       int eventid;
+       void (*handler)(struct wil6210_priv *wil, int eventid,
+                       void *data, int data_len);
+} wmi_evt_handlers[] = {
+       {WMI_READY_EVENTID,             wmi_evt_ready},
+       {WMI_FW_READY_EVENTID,          wmi_evt_fw_ready},
+       {WMI_RX_MGMT_PACKET_EVENTID,    wmi_evt_rx_mgmt},
+       {WMI_SCAN_COMPLETE_EVENTID,     wmi_evt_scan_complete},
+       {WMI_CONNECT_EVENTID,           wmi_evt_connect},
+       {WMI_DISCONNECT_EVENTID,        wmi_evt_disconnect},
+       {WMI_NOTIFY_REQ_DONE_EVENTID,   wmi_evt_notify},
+       {WMI_EAPOL_RX_EVENTID,          wmi_evt_eapol_rx},
+};
+
+/*
+ * Run in IRQ context
+ * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
+ * that will be eventually handled by the @wmi_event_worker in the thread
+ * context of thread "wil6210_wmi"
+ */
+void wmi_recv_cmd(struct wil6210_priv *wil)
+{
+       struct wil6210_mbox_ring_desc d_tail;
+       struct wil6210_mbox_hdr hdr;
+       struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
+       struct pending_wmi_event *evt;
+       u8 *cmd;
+       void __iomem *src;
+       ulong flags;
+
+       for (;;) {
+               u16 len;
+
+               r->head = ioread32(wil->csr + HOST_MBOX +
+                                  offsetof(struct wil6210_mbox_ctl, rx.head));
+               if (r->tail == r->head)
+                       return;
+
+               /* read cmd from tail */
+               wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
+                                    sizeof(struct wil6210_mbox_ring_desc));
+               if (d_tail.sync == 0) {
+                       wil_err(wil, "Mbox evt not owned by FW?\n");
+                       return;
+               }
+
+               if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
+                       wil_err(wil, "Mbox evt at 0x%08x?\n",
+                               le32_to_cpu(d_tail.addr));
+                       return;
+               }
+
+               len = le16_to_cpu(hdr.len);
+               src = wmi_buffer(wil, d_tail.addr) +
+                     sizeof(struct wil6210_mbox_hdr);
+               evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
+                                            event.wmi) + len, 4),
+                             GFP_KERNEL);
+               if (!evt) {
+                       wil_err(wil, "kmalloc for WMI event (%d) failed\n",
+                               len);
+                       return;
+               }
+               evt->event.hdr = hdr;
+               cmd = (void *)&evt->event.wmi;
+               wil_memcpy_fromio_32(cmd, src, len);
+               /* mark entry as empty */
+               iowrite32(0, wil->csr + HOSTADDR(r->tail) +
+                         offsetof(struct wil6210_mbox_ring_desc, sync));
+               /* indicate */
+               wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n",
+                           le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
+                           hdr.flags);
+               if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
+                   (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
+                       wil_dbg_WMI(wil, "WMI event 0x%04x\n",
+                                   evt->event.wmi.id);
+               }
+               wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1,
+                                &evt->event.hdr, sizeof(hdr) + len, true);
+
+               /* advance tail */
+               r->tail = r->base + ((r->tail - r->base +
+                         sizeof(struct wil6210_mbox_ring_desc)) % r->size);
+               iowrite32(r->tail, wil->csr + HOST_MBOX +
+                         offsetof(struct wil6210_mbox_ctl, rx.tail));
+
+               /* add to the pending list */
+               spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+               list_add_tail(&evt->list, &wil->pending_wmi_ev);
+               spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+               {
+                       int q = queue_work(wil->wmi_wq,
+                                          &wil->wmi_event_worker);
+                       wil_dbg_WMI(wil, "queue_work -> %d\n", q);
+               }
+       }
+}
+
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+            u16 reply_id, void *reply, u8 reply_size, int to_msec)
+{
+       int rc;
+       int remain;
+
+       mutex_lock(&wil->wmi_mutex);
+
+       rc = __wmi_send(wil, cmdid, buf, len);
+       if (rc)
+               goto out;
+
+       wil->reply_id = reply_id;
+       wil->reply_buf = reply;
+       wil->reply_size = reply_size;
+       remain = wait_for_completion_timeout(&wil->wmi_ready,
+                       msecs_to_jiffies(to_msec));
+       if (0 == remain) {
+               wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
+                       cmdid, reply_id, to_msec);
+               rc = -ETIME;
+       } else {
+               wil_dbg_WMI(wil,
+                           "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
+                           cmdid, reply_id,
+                           to_msec - jiffies_to_msecs(remain));
+       }
+       wil->reply_id = 0;
+       wil->reply_buf = NULL;
+       wil->reply_size = 0;
+ out:
+       mutex_unlock(&wil->wmi_mutex);
+
+       return rc;
+}
+
+int wmi_echo(struct wil6210_priv *wil)
+{
+       struct wmi_echo_cmd cmd = {
+               .value = cpu_to_le32(0x12345678),
+       };
+
+       return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
+                        WMI_ECHO_RSP_EVENTID, NULL, 0, 20);
+}
+
+int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
+{
+       struct wmi_set_mac_address_cmd cmd;
+
+       memcpy(cmd.mac, addr, ETH_ALEN);
+
+       wil_dbg_WMI(wil, "Set MAC %pM\n", addr);
+
+       return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype)
+{
+       struct wmi_bcon_ctrl_cmd cmd = {
+               .bcon_interval = cpu_to_le16(bi),
+               .network_type = wmi_nettype,
+               .disable_sec_offload = 1,
+       };
+
+       if (!wil->secure_pcp)
+               cmd.disable_sec = 1;
+
+       return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
+{
+       struct wmi_set_ssid_cmd cmd = {
+               .ssid_len = cpu_to_le32(ssid_len),
+       };
+
+       if (ssid_len > sizeof(cmd.ssid))
+               return -EINVAL;
+
+       memcpy(cmd.ssid, ssid, ssid_len);
+
+       return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
+{
+       int rc;
+       struct {
+               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_set_ssid_cmd cmd;
+       } __packed reply;
+       int len; /* reply.cmd.ssid_len in CPU order */
+
+       rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
+                     &reply, sizeof(reply), 20);
+       if (rc)
+               return rc;
+
+       len = le32_to_cpu(reply.cmd.ssid_len);
+       if (len > sizeof(reply.cmd.ssid))
+               return -EINVAL;
+
+       *ssid_len = len;
+       memcpy(ssid, reply.cmd.ssid, len);
+
+       return 0;
+}
+
+int wmi_set_channel(struct wil6210_priv *wil, int channel)
+{
+       struct wmi_set_pcp_channel_cmd cmd = {
+               .channel = channel - 1,
+       };
+
+       return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_get_channel(struct wil6210_priv *wil, int *channel)
+{
+       int rc;
+       struct {
+               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_set_pcp_channel_cmd cmd;
+       } __packed reply;
+
+       rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
+                     WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
+       if (rc)
+               return rc;
+
+       if (reply.cmd.channel > 3)
+               return -EINVAL;
+
+       *channel = reply.cmd.channel + 1;
+
+       return 0;
+}
+
+int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
+{
+       struct wmi_eapol_tx_cmd *cmd;
+       struct ethhdr *eth;
+       u16 eapol_len = skb->len - ETH_HLEN;
+       void *eapol = skb->data + ETH_HLEN;
+       uint i;
+       int rc;
+
+       skb_set_mac_header(skb, 0);
+       eth = eth_hdr(skb);
+       wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
+       for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
+               if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0)
+                       goto found_dest;
+       }
+
+       return -EINVAL;
+
+ found_dest:
+       /* find out eapol data & len */
+       cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL);
+       if (!cmd)
+               return -EINVAL;
+
+       memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN);
+       cmd->eapol_len = cpu_to_le16(eapol_len);
+       memcpy(cmd->eapol, eapol, eapol_len);
+       rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len);
+       kfree(cmd);
+
+       return rc;
+}
+
+int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+                      const void *mac_addr)
+{
+       struct wmi_delete_cipher_key_cmd cmd = {
+               .key_index = key_index,
+       };
+
+       if (mac_addr)
+               memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
+
+       return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+                      const void *mac_addr, int key_len, const void *key)
+{
+       struct wmi_add_cipher_key_cmd cmd = {
+               .key_index = key_index,
+               .key_usage = WMI_KEY_USE_PAIRWISE,
+               .key_len = key_len,
+       };
+
+       if (!key || (key_len > sizeof(cmd.key)))
+               return -EINVAL;
+
+       memcpy(cmd.key, key, key_len);
+       if (mac_addr)
+               memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
+
+       return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
+{
+       int rc;
+       u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
+       struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
+       if (!cmd) {
+               wil_err(wil, "kmalloc(%d) failed\n", len);
+               return -ENOMEM;
+       }
+
+       cmd->mgmt_frm_type = type;
+       /* BUG: FW API define ieLen as u8. Will fix FW */
+       cmd->ie_len = cpu_to_le16(ie_len);
+       memcpy(cmd->ie_info, ie, ie_len);
+       rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len);
+       kfree(cmd);
+
+       return rc;
+}
+
+void wmi_event_flush(struct wil6210_priv *wil)
+{
+       struct pending_wmi_event *evt, *t;
+
+       wil_dbg_WMI(wil, "%s()\n", __func__);
+
+       list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+}
+
+static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
+                                void *d, int len)
+{
+       uint i;
+
+       for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
+               if (wmi_evt_handlers[i].eventid == id) {
+                       wmi_evt_handlers[i].handler(wil, id, d, len);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static void wmi_event_handle(struct wil6210_priv *wil,
+                            struct wil6210_mbox_hdr *hdr)
+{
+       u16 len = le16_to_cpu(hdr->len);
+
+       if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
+           (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
+               struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
+               void *evt_data = (void *)(&wmi[1]);
+               u16 id = le16_to_cpu(wmi->id);
+               /* check if someone waits for this event */
+               if (wil->reply_id && wil->reply_id == id) {
+                       if (wil->reply_buf) {
+                               memcpy(wil->reply_buf, wmi,
+                                      min(len, wil->reply_size));
+                       } else {
+                               wmi_evt_call_handler(wil, id, evt_data,
+                                                    len - sizeof(*wmi));
+                       }
+                       wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id);
+                       complete(&wil->wmi_ready);
+                       return;
+               }
+               /* unsolicited event */
+               /* search for handler */
+               if (!wmi_evt_call_handler(wil, id, evt_data,
+                                         len - sizeof(*wmi))) {
+                       wil_err(wil, "Unhandled event 0x%04x\n", id);
+               }
+       } else {
+               wil_err(wil, "Unknown event type\n");
+               print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
+                              hdr, sizeof(*hdr) + len, true);
+       }
+}
+
+/*
+ * Retrieve next WMI event from the pending list
+ */
+static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
+{
+       ulong flags;
+       struct list_head *ret = NULL;
+
+       spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
+       if (!list_empty(&wil->pending_wmi_ev)) {
+               ret = wil->pending_wmi_ev.next;
+               list_del(ret);
+       }
+
+       spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+
+       return ret;
+}
+
+/*
+ * Handler for the WMI events
+ */
+void wmi_event_worker(struct work_struct *work)
+{
+       struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
+                                                wmi_event_worker);
+       struct pending_wmi_event *evt;
+       struct list_head *lh;
+
+       while ((lh = next_wmi_ev(wil)) != NULL) {
+               evt = list_entry(lh, struct pending_wmi_event, list);
+               wmi_event_handle(wil, &evt->event.hdr);
+               kfree(evt);
+       }
+}
+
+void wmi_connect_worker(struct work_struct *work)
+{
+       int rc;
+       struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
+                                               wmi_connect_worker);
+
+       if (wil->pending_connect_cid < 0) {
+               wil_err(wil, "No connection pending\n");
+               return;
+       }
+
+       wil_dbg_WMI(wil, "Configure for connection CID %d\n",
+                   wil->pending_connect_cid);
+
+       rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
+                              wil->pending_connect_cid, 0);
+       wil->pending_connect_cid = -1;
+       if (rc == 0)
+               wil_link_on(wil);
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
new file mode 100644 (file)
index 0000000..3bbf875
--- /dev/null
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2006-2012 Wilocity .
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This file contains the definitions of the WMI protocol specified in the
+ * Wireless Module Interface (WMI) for the Wilocity
+ * MARLON 60 Gigabit wireless solution.
+ * It includes definitions of all the commands and events.
+ * Commands are messages from the host to the WM.
+ * Events are messages from the WM to the host.
+ */
+
+#ifndef __WILOCITY_WMI_H__
+#define __WILOCITY_WMI_H__
+
+/* General */
+
+#define WMI_MAC_LEN            (6)
+#define WMI_PROX_RANGE_NUM     (3)
+
+/* List of Commands */
+enum wmi_command_id {
+       WMI_CONNECT_CMDID               = 0x0001,
+       WMI_DISCONNECT_CMDID            = 0x0003,
+       WMI_START_SCAN_CMDID            = 0x0007,
+       WMI_SET_BSS_FILTER_CMDID        = 0x0009,
+       WMI_SET_PROBED_SSID_CMDID       = 0x000a,
+       WMI_SET_LISTEN_INT_CMDID        = 0x000b,
+       WMI_BCON_CTRL_CMDID             = 0x000f,
+       WMI_ADD_CIPHER_KEY_CMDID        = 0x0016,
+       WMI_DELETE_CIPHER_KEY_CMDID     = 0x0017,
+       WMI_SET_APPIE_CMDID             = 0x003f,
+       WMI_GET_APPIE_CMDID             = 0x0040,
+       WMI_SET_WSC_STATUS_CMDID        = 0x0041,
+       WMI_PXMT_RANGE_CFG_CMDID        = 0x0042,
+       WMI_PXMT_SNR2_RANGE_CFG_CMDID   = 0x0043,
+       WMI_FAST_MEM_ACC_MODE_CMDID     = 0x0300,
+       WMI_MEM_READ_CMDID              = 0x0800,
+       WMI_MEM_WR_CMDID                = 0x0801,
+       WMI_ECHO_CMDID                  = 0x0803,
+       WMI_DEEP_ECHO_CMDID             = 0x0804,
+       WMI_CONFIG_MAC_CMDID            = 0x0805,
+       WMI_CONFIG_PHY_DEBUG_CMDID      = 0x0806,
+       WMI_ADD_STATION_CMDID           = 0x0807,
+       WMI_ADD_DEBUG_TX_PCKT_CMDID     = 0x0808,
+       WMI_PHY_GET_STATISTICS_CMDID    = 0x0809,
+       WMI_FS_TUNE_CMDID               = 0x080a,
+       WMI_CORR_MEASURE_CMDID          = 0x080b,
+       WMI_TEMP_SENSE_CMDID            = 0x080e,
+       WMI_DC_CALIB_CMDID              = 0x080f,
+       WMI_SEND_TONE_CMDID             = 0x0810,
+       WMI_IQ_TX_CALIB_CMDID           = 0x0811,
+       WMI_IQ_RX_CALIB_CMDID           = 0x0812,
+       WMI_SET_UCODE_IDLE_CMDID        = 0x0813,
+       WMI_SET_WORK_MODE_CMDID         = 0x0815,
+       WMI_LO_LEAKAGE_CALIB_CMDID      = 0x0816,
+       WMI_MARLON_R_ACTIVATE_CMDID     = 0x0817,
+       WMI_MARLON_R_READ_CMDID         = 0x0818,
+       WMI_MARLON_R_WRITE_CMDID        = 0x0819,
+       WMI_MARLON_R_TXRX_SEL_CMDID     = 0x081a,
+       MAC_IO_STATIC_PARAMS_CMDID      = 0x081b,
+       MAC_IO_DYNAMIC_PARAMS_CMDID     = 0x081c,
+       WMI_SILENT_RSSI_CALIB_CMDID     = 0x081d,
+       WMI_CFG_RX_CHAIN_CMDID          = 0x0820,
+       WMI_VRING_CFG_CMDID             = 0x0821,
+       WMI_RX_ON_CMDID                 = 0x0822,
+       WMI_VRING_BA_EN_CMDID           = 0x0823,
+       WMI_VRING_BA_DIS_CMDID          = 0x0824,
+       WMI_RCP_ADDBA_RESP_CMDID        = 0x0825,
+       WMI_RCP_DELBA_CMDID             = 0x0826,
+       WMI_SET_SSID_CMDID              = 0x0827,
+       WMI_GET_SSID_CMDID              = 0x0828,
+       WMI_SET_PCP_CHANNEL_CMDID       = 0x0829,
+       WMI_GET_PCP_CHANNEL_CMDID       = 0x082a,
+       WMI_SW_TX_REQ_CMDID             = 0x082b,
+       WMI_RX_OFF_CMDID                = 0x082c,
+       WMI_READ_MAC_RXQ_CMDID          = 0x0830,
+       WMI_READ_MAC_TXQ_CMDID          = 0x0831,
+       WMI_WRITE_MAC_RXQ_CMDID         = 0x0832,
+       WMI_WRITE_MAC_TXQ_CMDID         = 0x0833,
+       WMI_WRITE_MAC_XQ_FIELD_CMDID    = 0x0834,
+       WMI_MLME_PUSH_CMDID             = 0x0835,
+       WMI_BEAMFORMING_MGMT_CMDID      = 0x0836,
+       WMI_BF_TXSS_MGMT_CMDID          = 0x0837,
+       WMI_BF_SM_MGMT_CMDID            = 0x0838,
+       WMI_BF_RXSS_MGMT_CMDID          = 0x0839,
+       WMI_SET_SECTORS_CMDID           = 0x0849,
+       WMI_MAINTAIN_PAUSE_CMDID        = 0x0850,
+       WMI_MAINTAIN_RESUME_CMDID       = 0x0851,
+       WMI_RS_MGMT_CMDID               = 0x0852,
+       WMI_RF_MGMT_CMDID               = 0x0853,
+       /* Performance monitoring commands */
+       WMI_BF_CTRL_CMDID               = 0x0862,
+       WMI_NOTIFY_REQ_CMDID            = 0x0863,
+       WMI_GET_STATUS_CMDID            = 0x0864,
+       WMI_UNIT_TEST_CMDID             = 0x0900,
+       WMI_HICCUP_CMDID                = 0x0901,
+       WMI_FLASH_READ_CMDID            = 0x0902,
+       WMI_FLASH_WRITE_CMDID           = 0x0903,
+       WMI_SECURITY_UNIT_TEST_CMDID    = 0x0904,
+
+       WMI_SET_MAC_ADDRESS_CMDID       = 0xf003,
+       WMI_ABORT_SCAN_CMDID            = 0xf007,
+       WMI_SET_PMK_CMDID               = 0xf028,
+
+       WMI_SET_PROMISCUOUS_MODE_CMDID  = 0xf041,
+       WMI_GET_PMK_CMDID               = 0xf048,
+       WMI_SET_PASSPHRASE_CMDID        = 0xf049,
+       WMI_SEND_ASSOC_RES_CMDID        = 0xf04a,
+       WMI_SET_ASSOC_REQ_RELAY_CMDID   = 0xf04b,
+       WMI_EAPOL_TX_CMDID              = 0xf04c,
+       WMI_MAC_ADDR_REQ_CMDID          = 0xf04d,
+       WMI_FW_VER_CMDID                = 0xf04e,
+};
+
+/*
+ * Commands data structures
+ */
+
+/*
+ * Frame Types
+ */
+enum wmi_mgmt_frame_type {
+       WMI_FRAME_BEACON        = 0,
+       WMI_FRAME_PROBE_REQ     = 1,
+       WMI_FRAME_PROBE_RESP    = 2,
+       WMI_FRAME_ASSOC_REQ     = 3,
+       WMI_FRAME_ASSOC_RESP    = 4,
+       WMI_NUM_MGMT_FRAME,
+};
+
+/*
+ * WMI_CONNECT_CMDID
+ */
+enum wmi_network_type {
+       WMI_NETTYPE_INFRA               = 0x01,
+       WMI_NETTYPE_ADHOC               = 0x02,
+       WMI_NETTYPE_ADHOC_CREATOR       = 0x04,
+       WMI_NETTYPE_AP                  = 0x10,
+       WMI_NETTYPE_P2P                 = 0x20,
+       WMI_NETTYPE_WBE                 = 0x40, /* PCIE over 60g */
+};
+
+enum wmi_dot11_auth_mode {
+       WMI_AUTH11_OPEN                 = 0x01,
+       WMI_AUTH11_SHARED               = 0x02,
+       WMI_AUTH11_LEAP                 = 0x04,
+       WMI_AUTH11_WSC                  = 0x08,
+};
+
+enum wmi_auth_mode {
+       WMI_AUTH_NONE                   = 0x01,
+       WMI_AUTH_WPA                    = 0x02,
+       WMI_AUTH_WPA2                   = 0x04,
+       WMI_AUTH_WPA_PSK                = 0x08,
+       WMI_AUTH_WPA2_PSK               = 0x10,
+       WMI_AUTH_WPA_CCKM               = 0x20,
+       WMI_AUTH_WPA2_CCKM              = 0x40,
+};
+
+enum wmi_crypto_type {
+       WMI_CRYPT_NONE                  = 0x01,
+       WMI_CRYPT_WEP                   = 0x02,
+       WMI_CRYPT_TKIP                  = 0x04,
+       WMI_CRYPT_AES                   = 0x08,
+       WMI_CRYPT_AES_GCMP              = 0x20,
+};
+
+
+enum wmi_connect_ctrl_flag_bits {
+       WMI_CONNECT_ASSOC_POLICY_USER           = 0x0001,
+       WMI_CONNECT_SEND_REASSOC                = 0x0002,
+       WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER    = 0x0004,
+       WMI_CONNECT_PROFILE_MATCH_DONE          = 0x0008,
+       WMI_CONNECT_IGNORE_AAC_BEACON           = 0x0010,
+       WMI_CONNECT_CSA_FOLLOW_BSS              = 0x0020,
+       WMI_CONNECT_DO_WPA_OFFLOAD              = 0x0040,
+       WMI_CONNECT_DO_NOT_DEAUTH               = 0x0080,
+};
+
+#define WMI_MAX_SSID_LEN    (32)
+
+struct wmi_connect_cmd {
+       u8 network_type;
+       u8 dot11_auth_mode;
+       u8 auth_mode;
+       u8 pairwise_crypto_type;
+       u8 pairwise_crypto_len;
+       u8 group_crypto_type;
+       u8 group_crypto_len;
+       u8 ssid_len;
+       u8 ssid[WMI_MAX_SSID_LEN];
+       u8 channel;
+       u8 reserved0;
+       u8 bssid[WMI_MAC_LEN];
+       __le32 ctrl_flags;
+       u8 dst_mac[WMI_MAC_LEN];
+       u8 reserved1[2];
+} __packed;
+
+
+/*
+ * WMI_RECONNECT_CMDID
+ */
+struct wmi_reconnect_cmd {
+       u8 channel;                     /* hint */
+       u8 reserved;
+       u8 bssid[WMI_MAC_LEN];          /* mandatory if set */
+} __packed;
+
+
+/*
+ * WMI_SET_PMK_CMDID
+ */
+
+#define WMI_MIN_KEY_INDEX      (0)
+#define WMI_MAX_KEY_INDEX      (3)
+#define WMI_MAX_KEY_LEN                (32)
+#define WMI_PASSPHRASE_LEN     (64)
+#define WMI_PMK_LEN            (32)
+
+struct  wmi_set_pmk_cmd {
+       u8 pmk[WMI_PMK_LEN];
+} __packed;
+
+
+/*
+ * WMI_SET_PASSPHRASE_CMDID
+ */
+struct wmi_set_passphrase_cmd {
+       u8 ssid[WMI_MAX_SSID_LEN];
+       u8 passphrase[WMI_PASSPHRASE_LEN];
+       u8 ssid_len;
+       u8 passphrase_len;
+} __packed;
+
+/*
+ * WMI_ADD_CIPHER_KEY_CMDID
+ */
+enum wmi_key_usage {
+       WMI_KEY_USE_PAIRWISE    = 0,
+       WMI_KEY_USE_GROUP       = 1,
+       WMI_KEY_USE_TX          = 2,  /* default Tx Key - Static WEP only */
+};
+
+struct wmi_add_cipher_key_cmd {
+       u8 key_index;
+       u8 key_type;
+       u8 key_usage;           /* enum wmi_key_usage */
+       u8 key_len;
+       u8 key_rsc[8];          /* key replay sequence counter */
+       u8 key[WMI_MAX_KEY_LEN];
+       u8 key_op_ctrl;         /* Additional Key Control information */
+       u8 mac[WMI_MAC_LEN];
+} __packed;
+
+/*
+ * WMI_DELETE_CIPHER_KEY_CMDID
+ */
+struct wmi_delete_cipher_key_cmd {
+       u8 key_index;
+       u8 mac[WMI_MAC_LEN];
+} __packed;
+
+
+/*
+ * WMI_START_SCAN_CMDID
+ *
+ * Start L1 scan operation
+ *
+ * Returned events:
+ * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp.
+ * - WMI_SCAN_COMPLETE_EVENTID
+ */
+enum wmi_scan_type {
+       WMI_LONG_SCAN           = 0,
+       WMI_SHORT_SCAN          = 1,
+};
+
+struct wmi_start_scan_cmd {
+       u8 reserved[8];
+       __le32 home_dwell_time; /* Max duration in the home channel(ms) */
+       __le32 force_scan_interval;     /* Time interval between scans (ms)*/
+       u8 scan_type;           /* wmi_scan_type */
+       u8 num_channels;                /* how many channels follow */
+       struct {
+               u8 channel;
+               u8 reserved;
+       } channel_list[0];      /* channels ID's */
+                               /* 0 - 58320 MHz */
+                               /* 1 - 60480 MHz */
+                               /* 2 - 62640 MHz */
+} __packed;
+
+/*
+ * WMI_SET_PROBED_SSID_CMDID
+ */
+#define MAX_PROBED_SSID_INDEX   (15)
+
+enum wmi_ssid_flag {
+       WMI_SSID_FLAG_DISABLE   = 0,    /* disables entry */
+       WMI_SSID_FLAG_SPECIFIC  = 1,    /* probes specified ssid */
+       WMI_SSID_FLAG_ANY       = 2,    /* probes for any ssid */
+};
+
+struct wmi_probed_ssid_cmd {
+       u8 entry_index;                 /* 0 to MAX_PROBED_SSID_INDEX */
+       u8 flag;                        /* enum wmi_ssid_flag */
+       u8 ssid_len;
+       u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_SET_APPIE_CMDID
+ * Add Application specified IE to a management frame
+ */
+struct wmi_set_appie_cmd {
+       u8 mgmt_frm_type;       /* enum wmi_mgmt_frame_type */
+       u8 reserved;
+       __le16 ie_len;  /* Length of the IE to be added to MGMT frame */
+       u8 ie_info[0];
+} __packed;
+
+#define WMI_MAX_IE_LEN (1024)
+
+struct wmi_pxmt_range_cfg_cmd {
+       u8 dst_mac[WMI_MAC_LEN];
+       __le16 range;
+} __packed;
+
+struct wmi_pxmt_snr2_range_cfg_cmd {
+       s8 snr2range_arr[WMI_PROX_RANGE_NUM-1];
+} __packed;
+
+/*
+ * WMI_RF_MGMT_CMDID
+ */
+enum wmi_rf_mgmt_type {
+       WMI_RF_MGMT_W_DISABLE   = 0,
+       WMI_RF_MGMT_W_ENABLE    = 1,
+       WMI_RF_MGMT_GET_STATUS  = 2,
+};
+
+struct wmi_rf_mgmt_cmd {
+       __le32 rf_mgmt_type;
+} __packed;
+
+/*
+ * WMI_SET_SSID_CMDID
+ */
+struct wmi_set_ssid_cmd {
+       __le32 ssid_len;
+       u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_SET_PCP_CHANNEL_CMDID
+ */
+struct wmi_set_pcp_channel_cmd {
+       u8 channel;
+       u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_BCON_CTRL_CMDID
+ */
+struct wmi_bcon_ctrl_cmd {
+       __le16 bcon_interval;
+       __le16 frag_num;
+       __le64 ss_mask;
+       u8 network_type;
+       u8 reserved;
+       u8 disable_sec_offload;
+       u8 disable_sec;
+} __packed;
+
+/*
+ * WMI_SW_TX_REQ_CMDID
+ */
+struct wmi_sw_tx_req_cmd {
+       u8 dst_mac[WMI_MAC_LEN];
+       __le16 len;
+       u8 payload[0];
+} __packed;
+
+/*
+ * WMI_VRING_CFG_CMDID
+ */
+
+struct wmi_sw_ring_cfg {
+       __le64 ring_mem_base;
+       __le16 ring_size;
+       __le16 max_mpdu_size;
+} __packed;
+
+struct wmi_vring_cfg_schd {
+       __le16 priority;
+       __le16 timeslot_us;
+} __packed;
+
+enum wmi_vring_cfg_encap_trans_type {
+       WMI_VRING_ENC_TYPE_802_3                = 0,
+       WMI_VRING_ENC_TYPE_NATIVE_WIFI          = 1,
+};
+
+enum wmi_vring_cfg_ds_cfg {
+       WMI_VRING_DS_PBSS                       = 0,
+       WMI_VRING_DS_STATION                    = 1,
+       WMI_VRING_DS_AP                         = 2,
+       WMI_VRING_DS_ADDR4                      = 3,
+};
+
+enum wmi_vring_cfg_nwifi_ds_trans_type {
+       WMI_NWIFI_TX_TRANS_MODE_NO              = 0,
+       WMI_NWIFI_TX_TRANS_MODE_AP2PBSS         = 1,
+       WMI_NWIFI_TX_TRANS_MODE_STA2PBSS        = 2,
+};
+
+enum wmi_vring_cfg_schd_params_priority {
+       WMI_SCH_PRIO_REGULAR                    = 0,
+       WMI_SCH_PRIO_HIGH                       = 1,
+};
+
+struct wmi_vring_cfg {
+       struct wmi_sw_ring_cfg tx_sw_ring;
+       u8 ringid;                              /* 0-23 vrings */
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 encap_trans_type;
+       u8 ds_cfg;                              /* 802.3 DS cfg */
+       u8 nwifi_ds_trans_type;
+
+       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0)
+       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1)
+       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1)
+       #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1)
+       #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1)
+       #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2)
+       u8 mac_ctrl;
+
+       #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0)
+       #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6)
+       #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F)
+       u8 to_resolution;
+       u8 agg_max_wsize;
+       struct wmi_vring_cfg_schd schd_params;
+} __packed;
+
+enum wmi_vring_cfg_cmd_action {
+       WMI_VRING_CMD_ADD                       = 0,
+       WMI_VRING_CMD_MODIFY                    = 1,
+       WMI_VRING_CMD_DELETE                    = 2,
+};
+
+struct wmi_vring_cfg_cmd {
+       __le32 action;
+       struct wmi_vring_cfg vring_cfg;
+} __packed;
+
+/*
+ * WMI_VRING_BA_EN_CMDID
+ */
+struct wmi_vring_ba_en_cmd {
+       u8 ringid;
+       u8 agg_max_wsize;
+       __le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_VRING_BA_DIS_CMDID
+ */
+struct wmi_vring_ba_dis_cmd {
+       u8 ringid;
+       u8 reserved;
+       __le16 reason;
+} __packed;
+
+/*
+ * WMI_NOTIFY_REQ_CMDID
+ */
+struct wmi_notify_req_cmd {
+       u8 cid;
+       u8 reserved[3];
+       __le32 interval_usec;
+} __packed;
+
+/*
+ * WMI_CFG_RX_CHAIN_CMDID
+ */
+enum wmi_sniffer_cfg_mode {
+       WMI_SNIFFER_OFF                         = 0,
+       WMI_SNIFFER_ON                          = 1,
+};
+
+enum wmi_sniffer_cfg_phy_info_mode {
+       WMI_SNIFFER_PHY_INFO_DISABLED           = 0,
+       WMI_SNIFFER_PHY_INFO_ENABLED            = 1,
+};
+
+enum wmi_sniffer_cfg_phy_support {
+       WMI_SNIFFER_CP                          = 0,
+       WMI_SNIFFER_DP                          = 1,
+       WMI_SNIFFER_BOTH_PHYS                   = 2,
+};
+
+struct wmi_sniffer_cfg {
+       __le32 mode;            /* enum wmi_sniffer_cfg_mode */
+       __le32 phy_info_mode;   /* enum wmi_sniffer_cfg_phy_info_mode */
+       __le32 phy_support;     /* enum wmi_sniffer_cfg_phy_support */
+       u8 channel;
+       u8 reserved[3];
+} __packed;
+
+enum wmi_cfg_rx_chain_cmd_action {
+       WMI_RX_CHAIN_ADD                        = 0,
+       WMI_RX_CHAIN_DEL                        = 1,
+};
+
+enum wmi_cfg_rx_chain_cmd_decap_trans_type {
+       WMI_DECAP_TYPE_802_3                    = 0,
+       WMI_DECAP_TYPE_NATIVE_WIFI              = 1,
+};
+
+enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type {
+       WMI_NWIFI_RX_TRANS_MODE_NO              = 0,
+       WMI_NWIFI_RX_TRANS_MODE_PBSS2AP         = 1,
+       WMI_NWIFI_RX_TRANS_MODE_PBSS2STA        = 2,
+};
+
+struct wmi_cfg_rx_chain_cmd {
+       __le32 action;
+       struct wmi_sw_ring_cfg rx_sw_ring;
+       u8 mid;
+       u8 decap_trans_type;
+
+       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0)
+       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1)
+       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1)
+       u8 l2_802_3_offload_ctrl;
+
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0)
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1)
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1)
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1)
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1)
+       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2)
+       u8 l2_nwifi_offload_ctrl;
+
+       u8 vlan_id;
+       u8 nwifi_ds_trans_type;
+
+       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0)
+       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1)
+       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1)
+       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1)
+       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1)
+       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2)
+       u8 l3_l4_ctrl;
+
+       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0)
+       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1)
+       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1)
+       #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1)
+       #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1)
+       #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2)
+       #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2)
+       #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1)
+       #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4)
+       #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3)
+       #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1)
+       #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8)
+       u8 ring_ctrl;
+
+       __le16 prefetch_thrsh;
+       __le16 wb_thrsh;
+       __le32 itr_value;
+       __le16 host_thrsh;
+       u8 reserved[2];
+       struct wmi_sniffer_cfg sniffer_cfg;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_RESP_CMDID
+ */
+struct wmi_rcp_addba_resp_cmd {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 dialog_token;
+       __le16 status_code;
+       __le16 ba_param_set;    /* ieee80211_ba_parameterset field to send */
+       __le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_RCP_DELBA_CMDID
+ */
+struct wmi_rcp_delba_cmd {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 reserved;
+       __le16 reason;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_REQ_CMDID
+ */
+struct wmi_rcp_addba_req_cmd {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 dialog_token;
+       /* ieee80211_ba_parameterset field as it received */
+       __le16 ba_param_set;
+       __le16 ba_timeout;
+       /* ieee80211_ba_seqstrl field as it received */
+       __le16 ba_seq_ctrl;
+} __packed;
+
+/*
+ * WMI_SET_MAC_ADDRESS_CMDID
+ */
+struct wmi_set_mac_address_cmd {
+       u8 mac[WMI_MAC_LEN];
+       u8 reserved[2];
+} __packed;
+
+
+/*
+* WMI_EAPOL_TX_CMDID
+*/
+struct wmi_eapol_tx_cmd {
+       u8 dst_mac[WMI_MAC_LEN];
+       __le16 eapol_len;
+       u8 eapol[0];
+} __packed;
+
+/*
+ * WMI_ECHO_CMDID
+ *
+ * Check FW is alive
+ *
+ * WMI_DEEP_ECHO_CMDID
+ *
+ * Check FW and ucode are alive
+ *
+ * Returned event: WMI_ECHO_RSP_EVENTID
+ * same event for both commands
+ */
+struct wmi_echo_cmd {
+       __le32 value;
+} __packed;
+
+/*
+ * WMI Events
+ */
+
+/*
+ * List of Events (target to host)
+ */
+enum wmi_event_id {
+       WMI_IMM_RSP_EVENTID                     = 0x0000,
+       WMI_READY_EVENTID                       = 0x1001,
+       WMI_CONNECT_EVENTID                     = 0x1002,
+       WMI_DISCONNECT_EVENTID                  = 0x1003,
+       WMI_SCAN_COMPLETE_EVENTID               = 0x100a,
+       WMI_REPORT_STATISTICS_EVENTID           = 0x100b,
+       WMI_RD_MEM_RSP_EVENTID                  = 0x1800,
+       WMI_FW_READY_EVENTID                    = 0x1801,
+       WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID      = 0x0200,
+       WMI_ECHO_RSP_EVENTID                    = 0x1803,
+       WMI_CONFIG_MAC_DONE_EVENTID             = 0x1805,
+       WMI_CONFIG_PHY_DEBUG_DONE_EVENTID       = 0x1806,
+       WMI_ADD_STATION_DONE_EVENTID            = 0x1807,
+       WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID      = 0x1808,
+       WMI_PHY_GET_STATISTICS_EVENTID          = 0x1809,
+       WMI_FS_TUNE_DONE_EVENTID                = 0x180a,
+       WMI_CORR_MEASURE_DONE_EVENTID           = 0x180b,
+       WMI_TEMP_SENSE_DONE_EVENTID             = 0x180e,
+       WMI_DC_CALIB_DONE_EVENTID               = 0x180f,
+       WMI_IQ_TX_CALIB_DONE_EVENTID            = 0x1811,
+       WMI_IQ_RX_CALIB_DONE_EVENTID            = 0x1812,
+       WMI_SET_WORK_MODE_DONE_EVENTID          = 0x1815,
+       WMI_LO_LEAKAGE_CALIB_DONE_EVENTID       = 0x1816,
+       WMI_MARLON_R_ACTIVATE_DONE_EVENTID      = 0x1817,
+       WMI_MARLON_R_READ_DONE_EVENTID          = 0x1818,
+       WMI_MARLON_R_WRITE_DONE_EVENTID         = 0x1819,
+       WMI_MARLON_R_TXRX_SEL_DONE_EVENTID      = 0x181a,
+       WMI_SILENT_RSSI_CALIB_DONE_EVENTID      = 0x181d,
+
+       WMI_CFG_RX_CHAIN_DONE_EVENTID           = 0x1820,
+       WMI_VRING_CFG_DONE_EVENTID              = 0x1821,
+       WMI_RX_ON_DONE_EVENTID                  = 0x1822,
+       WMI_BA_STATUS_EVENTID                   = 0x1823,
+       WMI_RCP_ADDBA_REQ_EVENTID               = 0x1824,
+       WMI_ADDBA_RESP_SENT_EVENTID             = 0x1825,
+       WMI_DELBA_EVENTID                       = 0x1826,
+       WMI_GET_SSID_EVENTID                    = 0x1828,
+       WMI_GET_PCP_CHANNEL_EVENTID             = 0x182a,
+       WMI_SW_TX_COMPLETE_EVENTID              = 0x182b,
+       WMI_RX_OFF_DONE_EVENTID                 = 0x182c,
+
+       WMI_READ_MAC_RXQ_EVENTID                = 0x1830,
+       WMI_READ_MAC_TXQ_EVENTID                = 0x1831,
+       WMI_WRITE_MAC_RXQ_EVENTID               = 0x1832,
+       WMI_WRITE_MAC_TXQ_EVENTID               = 0x1833,
+       WMI_WRITE_MAC_XQ_FIELD_EVENTID          = 0x1834,
+
+       WMI_BEAFORMING_MGMT_DONE_EVENTID        = 0x1836,
+       WMI_BF_TXSS_MGMT_DONE_EVENTID           = 0x1837,
+       WMI_BF_RXSS_MGMT_DONE_EVENTID           = 0x1839,
+       WMI_RS_MGMT_DONE_EVENTID                = 0x1852,
+       WMI_RF_MGMT_STATUS_EVENTID              = 0x1853,
+       WMI_BF_SM_MGMT_DONE_EVENTID             = 0x1838,
+       WMI_RX_MGMT_PACKET_EVENTID              = 0x1840,
+
+       /* Performance monitoring events */
+       WMI_DATA_PORT_OPEN_EVENTID              = 0x1860,
+       WMI_WBE_LINKDOWN_EVENTID                = 0x1861,
+
+       WMI_BF_CTRL_DONE_EVENTID                = 0x1862,
+       WMI_NOTIFY_REQ_DONE_EVENTID             = 0x1863,
+       WMI_GET_STATUS_DONE_EVENTID             = 0x1864,
+
+       WMI_UNIT_TEST_EVENTID                   = 0x1900,
+       WMI_FLASH_READ_DONE_EVENTID             = 0x1902,
+       WMI_FLASH_WRITE_DONE_EVENTID            = 0x1903,
+
+       WMI_SET_CHANNEL_EVENTID                 = 0x9000,
+       WMI_ASSOC_REQ_EVENTID                   = 0x9001,
+       WMI_EAPOL_RX_EVENTID                    = 0x9002,
+       WMI_MAC_ADDR_RESP_EVENTID               = 0x9003,
+       WMI_FW_VER_EVENTID                      = 0x9004,
+};
+
+/*
+ * Events data structures
+ */
+
+/*
+ * WMI_RF_MGMT_STATUS_EVENTID
+ */
+enum wmi_rf_status {
+       WMI_RF_ENABLED                  = 0,
+       WMI_RF_DISABLED_HW              = 1,
+       WMI_RF_DISABLED_SW              = 2,
+       WMI_RF_DISABLED_HW_SW           = 3,
+};
+
+struct wmi_rf_mgmt_status_event {
+       __le32 rf_status;
+} __packed;
+
+/*
+ * WMI_GET_STATUS_DONE_EVENTID
+ */
+struct wmi_get_status_done_event {
+       __le32 is_associated;
+       u8 cid;
+       u8 reserved0[3];
+       u8 bssid[WMI_MAC_LEN];
+       u8 channel;
+       u8 reserved1;
+       u8 network_type;
+       u8 reserved2[3];
+       __le32 ssid_len;
+       u8 ssid[WMI_MAX_SSID_LEN];
+       __le32 rf_status;
+       __le32 is_secured;
+} __packed;
+
+/*
+ * WMI_FW_VER_EVENTID
+ */
+struct wmi_fw_ver_event {
+       u8 major;
+       u8 minor;
+       __le16 subminor;
+       __le16 build;
+} __packed;
+
+/*
+* WMI_MAC_ADDR_RESP_EVENTID
+*/
+struct wmi_mac_addr_resp_event {
+       u8 mac[WMI_MAC_LEN];
+       u8 auth_mode;
+       u8 crypt_mode;
+       __le32 offload_mode;
+} __packed;
+
+/*
+* WMI_EAPOL_RX_EVENTID
+*/
+struct wmi_eapol_rx_event {
+       u8 src_mac[WMI_MAC_LEN];
+       __le16 eapol_len;
+       u8 eapol[0];
+} __packed;
+
+/*
+* WMI_READY_EVENTID
+*/
+enum wmi_phy_capability {
+       WMI_11A_CAPABILITY              = 1,
+       WMI_11G_CAPABILITY              = 2,
+       WMI_11AG_CAPABILITY             = 3,
+       WMI_11NA_CAPABILITY             = 4,
+       WMI_11NG_CAPABILITY             = 5,
+       WMI_11NAG_CAPABILITY            = 6,
+       WMI_11AD_CAPABILITY             = 7,
+       WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY,
+};
+
+struct wmi_ready_event {
+       __le32 sw_version;
+       __le32 abi_version;
+       u8 mac[WMI_MAC_LEN];
+       u8 phy_capability;              /* enum wmi_phy_capability */
+       u8 reserved;
+} __packed;
+
+/*
+ * WMI_NOTIFY_REQ_DONE_EVENTID
+ */
+struct wmi_notify_req_done_event {
+       __le32 status;
+       __le64 tsf;
+       __le32 snr_val;
+       __le32 tx_tpt;
+       __le32 tx_goodput;
+       __le32 rx_goodput;
+       __le16 bf_mcs;
+       __le16 my_rx_sector;
+       __le16 my_tx_sector;
+       __le16 other_rx_sector;
+       __le16 other_tx_sector;
+       __le16 range;
+} __packed;
+
+/*
+ * WMI_CONNECT_EVENTID
+ */
+struct wmi_connect_event {
+       u8 channel;
+       u8 reserved0;
+       u8 bssid[WMI_MAC_LEN];
+       __le16 listen_interval;
+       __le16 beacon_interval;
+       u8 network_type;
+       u8 reserved1[3];
+       u8 beacon_ie_len;
+       u8 assoc_req_len;
+       u8 assoc_resp_len;
+       u8 cid;
+       u8 reserved2[3];
+       u8 assoc_info[0];
+} __packed;
+
+/*
+ * WMI_DISCONNECT_EVENTID
+ */
+enum wmi_disconnect_reason {
+       WMI_DIS_REASON_NO_NETWORK_AVAIL         = 1,
+       WMI_DIS_REASON_LOST_LINK                = 2, /* bmiss */
+       WMI_DIS_REASON_DISCONNECT_CMD           = 3,
+       WMI_DIS_REASON_BSS_DISCONNECTED         = 4,
+       WMI_DIS_REASON_AUTH_FAILED              = 5,
+       WMI_DIS_REASON_ASSOC_FAILED             = 6,
+       WMI_DIS_REASON_NO_RESOURCES_AVAIL       = 7,
+       WMI_DIS_REASON_CSERV_DISCONNECT         = 8,
+       WMI_DIS_REASON_INVALID_PROFILE          = 10,
+       WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH    = 11,
+       WMI_DIS_REASON_PROFILE_MISMATCH         = 12,
+       WMI_DIS_REASON_CONNECTION_EVICTED       = 13,
+       WMI_DIS_REASON_IBSS_MERGE               = 14,
+};
+
+struct wmi_disconnect_event {
+       __le16 protocol_reason_status;  /* reason code, see 802.11 spec. */
+       u8 bssid[WMI_MAC_LEN];          /* set if known */
+       u8 disconnect_reason;           /* see wmi_disconnect_reason_e */
+       u8 assoc_resp_len;
+       u8 assoc_info[0];
+} __packed;
+
+/*
+ * WMI_SCAN_COMPLETE_EVENTID
+ */
+struct wmi_scan_complete_event {
+       __le32 status;
+} __packed;
+
+/*
+ * WMI_BA_STATUS_EVENTID
+ */
+enum wmi_vring_ba_status {
+       WMI_BA_AGREED                   = 0,
+       WMI_BA_NON_AGREED               = 1,
+};
+
+struct wmi_vring_ba_status_event {
+       __le16 status;
+       u8 reserved[2];
+       u8 ringid;
+       u8 agg_wsize;
+       __le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_DELBA_EVENTID
+ */
+struct wmi_delba_event {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 from_initiator;
+       __le16 reason;
+} __packed;
+
+/*
+ * WMI_VRING_CFG_DONE_EVENTID
+ */
+enum wmi_vring_cfg_done_event_status {
+       WMI_VRING_CFG_SUCCESS           = 0,
+       WMI_VRING_CFG_FAILURE           = 1,
+};
+
+struct wmi_vring_cfg_done_event {
+       u8 ringid;
+       u8 status;
+       u8 reserved[2];
+       __le32 tx_vring_tail_ptr;
+} __packed;
+
+/*
+ * WMI_ADDBA_RESP_SENT_EVENTID
+ */
+enum wmi_rcp_addba_resp_sent_event_status {
+       WMI_ADDBA_SUCCESS               = 0,
+       WMI_ADDBA_FAIL                  = 1,
+};
+
+struct wmi_rcp_addba_resp_sent_event {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 reserved;
+       __le16 status;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_REQ_EVENTID
+ */
+struct wmi_rcp_addba_req_event {
+
+       #define CIDXTID_CID_POS (0)
+       #define CIDXTID_CID_LEN (4)
+       #define CIDXTID_CID_MSK (0xF)
+       #define CIDXTID_TID_POS (4)
+       #define CIDXTID_TID_LEN (4)
+       #define CIDXTID_TID_MSK (0xF0)
+       u8 cidxtid;
+
+       u8 dialog_token;
+       __le16 ba_param_set;    /* ieee80211_ba_parameterset as it received */
+       __le16 ba_timeout;
+       __le16 ba_seq_ctrl;     /* ieee80211_ba_seqstrl field as it received */
+} __packed;
+
+/*
+ * WMI_CFG_RX_CHAIN_DONE_EVENTID
+ */
+enum wmi_cfg_rx_chain_done_event_status {
+       WMI_CFG_RX_CHAIN_SUCCESS        = 1,
+};
+
+struct wmi_cfg_rx_chain_done_event {
+       __le32 rx_ring_tail_ptr;        /* Rx V-Ring Tail pointer */
+       __le32 status;
+} __packed;
+
+/*
+ * WMI_WBE_LINKDOWN_EVENTID
+ */
+enum wmi_wbe_link_down_event_reason {
+       WMI_WBE_REASON_USER_REQUEST     = 0,
+       WMI_WBE_REASON_RX_DISASSOC      = 1,
+       WMI_WBE_REASON_BAD_PHY_LINK     = 2,
+};
+
+struct wmi_wbe_link_down_event {
+       u8 cid;
+       u8 reserved[3];
+       __le32 reason;
+} __packed;
+
+/*
+ * WMI_DATA_PORT_OPEN_EVENTID
+ */
+struct wmi_data_port_open_event {
+       u8 cid;
+       u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_GET_PCP_CHANNEL_EVENTID
+ */
+struct wmi_get_pcp_channel_event {
+       u8 channel;
+       u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_SW_TX_COMPLETE_EVENTID
+ */
+enum wmi_sw_tx_status {
+       WMI_TX_SW_STATUS_SUCCESS                = 0,
+       WMI_TX_SW_STATUS_FAILED_NO_RESOURCES    = 1,
+       WMI_TX_SW_STATUS_FAILED_TX              = 2,
+};
+
+struct wmi_sw_tx_complete_event {
+       u8 status;      /* enum wmi_sw_tx_status */
+       u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_GET_SSID_EVENTID
+ */
+struct wmi_get_ssid_event {
+       __le32 ssid_len;
+       u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_RX_MGMT_PACKET_EVENTID
+ */
+struct wmi_rx_mgmt_info {
+       u8 mcs;
+       s8 snr;
+       __le16 range;
+       __le16 stype;
+       __le16 status;
+       __le32 len;
+       u8 qid;
+       u8 mid;
+       u8 cid;
+       u8 channel;     /* From Radio MNGR */
+} __packed;
+
+struct wmi_rx_mgmt_packet_event {
+       struct wmi_rx_mgmt_info info;
+       u8 payload[0];
+} __packed;
+
+/*
+ * WMI_ECHO_RSP_EVENTID
+ */
+struct wmi_echo_event {
+       __le32 echoed_value;
+} __packed;
+
+#endif /* __WILOCITY_WMI_H__ */
index b298e5d68be2f0a58cf02d45d2ccd9a1e1e464bd..10e288d470e75be03ef936048fe70574ac3ea2c2 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/hw_random.h>
 #include <linux/bcma/bcma.h>
 #include <linux/ssb/ssb.h>
+#include <linux/completion.h>
 #include <net/mac80211.h>
 
 #include "debugfs.h"
@@ -722,6 +723,10 @@ enum b43_firmware_file_type {
 struct b43_request_fw_context {
        /* The device we are requesting the fw for. */
        struct b43_wldev *dev;
+       /* a completion event structure needed if this call is asynchronous */
+       struct completion fw_load_complete;
+       /* a pointer to the firmware object */
+       const struct firmware *blob;
        /* The type of firmware to request. */
        enum b43_firmware_file_type req_type;
        /* Error messages for each firmware type. */
index 16ab280359bd9ffbb9ee68770606d949b3060e6a..806e34c19281792b4444ad1e6b8ea03724c9c773 100644 (file)
@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
                b43warn(wl, text);
 }
 
+static void b43_fw_cb(const struct firmware *firmware, void *context)
+{
+       struct b43_request_fw_context *ctx = context;
+
+       ctx->blob = firmware;
+       complete(&ctx->fw_load_complete);
+}
+
 int b43_do_request_fw(struct b43_request_fw_context *ctx,
                      const char *name,
-                     struct b43_firmware_file *fw)
+                     struct b43_firmware_file *fw, bool async)
 {
-       const struct firmware *blob;
        struct b43_fw_header *hdr;
        u32 size;
        int err;
@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
                B43_WARN_ON(1);
                return -ENOSYS;
        }
-       err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
+       if (async) {
+               /* do this part asynchronously */
+               init_completion(&ctx->fw_load_complete);
+               err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
+                                             ctx->dev->dev->dev, GFP_KERNEL,
+                                             ctx, b43_fw_cb);
+               if (err < 0) {
+                       pr_err("Unable to load firmware\n");
+                       return err;
+               }
+               /* stall here until fw ready */
+               wait_for_completion(&ctx->fw_load_complete);
+               if (ctx->blob)
+                       goto fw_ready;
+       /* On some ARM systems, the async request will fail, but the next sync
+        * request works. For this reason, we dall through here
+        */
+       }
+       err = request_firmware(&ctx->blob, ctx->fwname,
+                              ctx->dev->dev->dev);
        if (err == -ENOENT) {
                snprintf(ctx->errors[ctx->req_type],
                         sizeof(ctx->errors[ctx->req_type]),
-                        "Firmware file \"%s\" not found\n", ctx->fwname);
+                        "Firmware file \"%s\" not found\n",
+                        ctx->fwname);
                return err;
        } else if (err) {
                snprintf(ctx->errors[ctx->req_type],
@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
                         ctx->fwname, err);
                return err;
        }
-       if (blob->size < sizeof(struct b43_fw_header))
+fw_ready:
+       if (ctx->blob->size < sizeof(struct b43_fw_header))
                goto err_format;
-       hdr = (struct b43_fw_header *)(blob->data);
+       hdr = (struct b43_fw_header *)(ctx->blob->data);
        switch (hdr->type) {
        case B43_FW_TYPE_UCODE:
        case B43_FW_TYPE_PCM:
                size = be32_to_cpu(hdr->size);
-               if (size != blob->size - sizeof(struct b43_fw_header))
+               if (size != ctx->blob->size - sizeof(struct b43_fw_header))
                        goto err_format;
                /* fallthrough */
        case B43_FW_TYPE_IV:
@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
                goto err_format;
        }
 
-       fw->data = blob;
+       fw->data = ctx->blob;
        fw->filename = name;
        fw->type = ctx->req_type;
 
@@ -2172,7 +2200,7 @@ err_format:
        snprintf(ctx->errors[ctx->req_type],
                 sizeof(ctx->errors[ctx->req_type]),
                 "Firmware file \"%s\" format error.\n", ctx->fwname);
-       release_firmware(blob);
+       release_firmware(ctx->blob);
 
        return -EPROTO;
 }
@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
                        goto err_no_ucode;
                }
        }
-       err = b43_do_request_fw(ctx, filename, &fw->ucode);
+       err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
        if (err)
                goto err_load;
 
@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
        else
                goto err_no_pcm;
        fw->pcm_request_failed = false;
-       err = b43_do_request_fw(ctx, filename, &fw->pcm);
+       err = b43_do_request_fw(ctx, filename, &fw->pcm, false);
        if (err == -ENOENT) {
                /* We did not find a PCM file? Not fatal, but
                 * core rev <= 10 must do without hwcrypto then. */
@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
        default:
                goto err_no_initvals;
        }
-       err = b43_do_request_fw(ctx, filename, &fw->initvals);
+       err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
        if (err)
                goto err_load;
 
@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
        default:
                goto err_no_initvals;
        }
-       err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
+       err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
        if (err)
                goto err_load;
 
index 8c684cd3352942ccaadcf843290d014cbb8599bd..abac25ee958dad54f140c550ef62ba05bf2bc3ae 100644 (file)
@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
 
 
 struct b43_request_fw_context;
-int b43_do_request_fw(struct b43_request_fw_context *ctx,
-                     const char *name,
-                     struct b43_firmware_file *fw);
+int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name,
+                     struct b43_firmware_file *fw, bool async);
 void b43_do_release_fw(struct b43_firmware_file *fw);
 
 #endif /* B43_MAIN_H_ */
index 1261a9b84e04aaf348df15e8bb2ad0e00a213255..75464ad4fbd188ce1fb135302539dfa02caa3fbb 100644 (file)
@@ -3091,10 +3091,11 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
 
        len = wpa_ie->len + TLV_HDR_LEN;
        data = (u8 *)wpa_ie;
-       offset = 0;
+       offset = TLV_HDR_LEN;
        if (!is_rsn_ie)
                offset += VS_IE_FIXED_HDR_LEN;
-       offset += WPA_IE_VERSION_LEN;
+       else
+               offset += WPA_IE_VERSION_LEN;
 
        /* check for multicast cipher suite */
        if (offset + WPA_IE_MIN_OUI_LEN > len) {
index 796836b0f4699ccf07cdb73bc1acdd6122b60e33..822781cf15d41900aabd941fe79956191e1328ed 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 Broadcom Corporation
+ * Copyright (c) 2012 Canonical Ltd.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
index 1fbd8ecbe2ea293a28d6a65648fe011a2fff3fa6..e5fd20994bec256df4ec88f96182006e54ada0d6 100644 (file)
@@ -36,6 +36,7 @@
 #include "debug.h"
 
 #define N_TX_QUEUES    4 /* #tx queues on mac80211<->driver interface */
+#define BRCMS_FLUSH_TIMEOUT    500 /* msec */
 
 /* Flags we support */
 #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
@@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 }
 
+static bool brcms_tx_flush_completed(struct brcms_info *wl)
+{
+       bool result;
+
+       spin_lock_bh(&wl->lock);
+       result = brcms_c_tx_flush_completed(wl->wlc);
+       spin_unlock_bh(&wl->lock);
+       return result;
+}
+
 static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct brcms_info *wl = hw->priv;
+       int ret;
 
        no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
 
-       /* wait for packet queue and dma fifos to run empty */
-       spin_lock_bh(&wl->lock);
-       brcms_c_wait_for_tx_completion(wl->wlc, drop);
-       spin_unlock_bh(&wl->lock);
+       ret = wait_event_timeout(wl->tx_flush_wq,
+                                brcms_tx_flush_completed(wl),
+                                msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));
+
+       brcms_dbg_mac80211(wl->wlc->hw->d11core,
+                          "ret=%d\n", jiffies_to_msecs(ret));
 }
 
 static const struct ieee80211_ops brcms_ops = {
@@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data)
 
  done:
        spin_unlock_bh(&wl->lock);
+       wake_up(&wl->tx_flush_wq);
 }
 
 /*
@@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
 
        atomic_set(&wl->callbacks, 0);
 
+       init_waitqueue_head(&wl->tx_flush_wq);
+
        /* setup the bottom half handler */
        tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
 
@@ -1407,9 +1424,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
 #endif
        t->ms = ms;
        t->periodic = (bool) periodic;
-       t->set = true;
-
-       atomic_inc(&t->wl->callbacks);
+       if (!t->set) {
+               t->set = true;
+               atomic_inc(&t->wl->callbacks);
+       }
 
        ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
 }
@@ -1608,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
        spin_lock_bh(&wl->lock);
        return blocked;
 }
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void brcms_msleep(struct brcms_info *wl, uint ms)
-{
-       spin_unlock_bh(&wl->lock);
-       msleep(ms);
-       spin_lock_bh(&wl->lock);
-}
index 9358bd5ebd35d016058d1238d11aca6880fdae19..947ccacf43e6f498dacfaceed5c3853c00c99d96 100644 (file)
@@ -68,6 +68,8 @@ struct brcms_info {
        spinlock_t lock;        /* per-device perimeter lock */
        spinlock_t isr_lock;    /* per-device ISR synchronization lock */
 
+       /* tx flush */
+       wait_queue_head_t tx_flush_wq;
 
        /* timer related fields */
        atomic_t callbacks;     /* # outstanding callback functions */
@@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
 extern void brcms_free_timer(struct brcms_timer *timer);
 extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
 extern bool brcms_del_timer(struct brcms_timer *timer);
-extern void brcms_msleep(struct brcms_info *wl, uint ms);
 extern void brcms_dpc(unsigned long data);
 extern void brcms_timer(struct brcms_timer *t);
 extern void brcms_fatal_error(struct brcms_info *wl);
index 17594de4199ef58a30488e2c7579ec02c521d9ea..8b5839008af32a11afef6d4042db67a0d8a9c16d 100644 (file)
@@ -1027,7 +1027,6 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 static bool
 brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 {
-       bool morepending = false;
        struct bcma_device *core;
        struct tx_status txstatus, *txs;
        u32 s1, s2;
@@ -1041,23 +1040,20 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
        txs = &txstatus;
        core = wlc_hw->d11core;
        *fatal = false;
-       s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
-       while (!(*fatal)
-              && (s1 & TXS_V)) {
-               /* !give others some time to run! */
-               if (n >= max_tx_num) {
-                       morepending = true;
-                       break;
-               }
 
+       while (n < max_tx_num) {
+               s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
                if (s1 == 0xffffffff) {
                        brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
                                  __func__);
                        *fatal = true;
                        return false;
                }
-               s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
+               /* only process when valid */
+               if (!(s1 & TXS_V))
+                       break;
 
+               s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
                txs->status = s1 & TXS_STATUS_MASK;
                txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
                txs->sequence = s2 & TXS_SEQ_MASK;
@@ -1065,15 +1061,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
                txs->lasttxtime = 0;
 
                *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
-
-               s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
+               if (*fatal == true)
+                       return false;
                n++;
        }
 
-       if (*fatal)
-               return false;
-
-       return morepending;
+       return n >= max_tx_num;
 }
 
 static void brcms_c_tbtt(struct brcms_c_info *wlc)
@@ -7518,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
        return wlc->band->bandunit;
 }
 
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc)
 {
-       int timeout = 20;
        int i;
 
        /* Kick DMA to send any pending AMPDU */
        for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
                if (wlc->hw->di[i])
-                       dma_txflush(wlc->hw->di[i]);
-
-       /* wait for queue and DMA fifos to run dry */
-       while (brcms_txpktpendtot(wlc) > 0) {
-               brcms_msleep(wlc->wl, 1);
-
-               if (--timeout == 0)
-                       break;
-       }
+                       dma_kick_tx(wlc->hw->di[i]);
 
-       WARN_ON_ONCE(timeout == 0);
+       return !brcms_txpktpendtot(wlc);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
index 606b534347bc93984cb9aefb38acd6981f3af8de..21a824232478f2ac02d593495ac5fe82ff94df77 100644 (file)
@@ -1343,13 +1343,13 @@ static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
 
        wlc_lcnphy_rx_gain_override_enable(pi, true);
        wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-       usleep_range(500, 500);
+       udelay(500);
        write_radio_reg(pi, RADIO_2064_REG112, 0);
        if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
                return false;
 
        wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-       usleep_range(500, 500);
+       udelay(500);
        write_radio_reg(pi, RADIO_2064_REG112, 0);
        if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
                return false;
index 4fb2834f4e6483f7c9321666c75598e6f9fa21fd..b0f14b7b8616e63ed5f2ed954ff47eddab7ff0d0 100644 (file)
@@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
 extern void brcms_c_scan_start(struct brcms_c_info *wlc);
 extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
 extern int brcms_c_get_curband(struct brcms_c_info *wlc);
-extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
-                                          bool drop);
 extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
 extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
 extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
@@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
 extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
 extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
+extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
 
 #endif                         /* _BRCM_PUB_H_ */
index d604b4036a764358e52bd2c2ca9d02bd24f14ce9..3726cd6fcd754812d65cb38d89782e96aace0de8 100644 (file)
@@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,
 
        if (count) {
                char *p = buffer;
-               strncpy(buffer, buf, min(sizeof(buffer), count));
+               strlcpy(buffer, buf, sizeof(buffer));
                channel = simple_strtoul(p, NULL, 0);
                if (channel)
                        params.channel = channel;
index 7e16d10a7f140e4bc0a1414af1ec317f7284b9c6..90b8970eadf0fa7c296be194c2d18ef9266b1043 100644 (file)
@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il)
 
        memset(&il->staging, 0, sizeof(il->staging));
 
-       if (!il->vif) {
+       switch (il->iw_mode) {
+       case NL80211_IFTYPE_UNSPECIFIED:
                il->staging.dev_type = RXON_DEV_TYPE_ESS;
-       } else if (il->vif->type == NL80211_IFTYPE_STATION) {
+               break;
+       case NL80211_IFTYPE_STATION:
                il->staging.dev_type = RXON_DEV_TYPE_ESS;
                il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
-       } else if (il->vif->type == NL80211_IFTYPE_ADHOC) {
+               break;
+       case NL80211_IFTYPE_ADHOC:
                il->staging.dev_type = RXON_DEV_TYPE_IBSS;
                il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
                il->staging.filter_flags =
                    RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
-       } else {
+               break;
+       default:
                IL_ERR("Unsupported interface type %d\n", il->vif->type);
                return;
        }
@@ -4550,8 +4554,7 @@ out:
 EXPORT_SYMBOL(il_mac_add_interface);
 
 static void
-il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
-                     bool mode_change)
+il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif)
 {
        lockdep_assert_held(&il->mutex);
 
@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
                il_force_scan_end(il);
        }
 
-       if (!mode_change)
-               il_set_mode(il);
-
+       il_set_mode(il);
 }
 
 void
@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        WARN_ON(il->vif != vif);
        il->vif = NULL;
-
-       il_teardown_interface(il, vif, false);
+       il->iw_mode = NL80211_IFTYPE_UNSPECIFIED;
+       il_teardown_interface(il, vif);
        memset(il->bssid, 0, ETH_ALEN);
 
        D_MAC80211("leave\n");
@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        }
 
        /* success */
-       il_teardown_interface(il, vif, true);
        vif->type = newtype;
        vif->p2p = false;
-       err = il_set_mode(il);
-       WARN_ON(err);
-       /*
-        * We've switched internally, but submitting to the
-        * device may have failed for some reason. Mask this
-        * error, because otherwise mac80211 will not switch
-        * (and set the interface type back) and we'll be
-        * out of sync with it.
-        */
+       il->iw_mode = newtype;
+       il_teardown_interface(il, vif);
        err = 0;
 
 out:
index da21328ca8ed84e9e06e3aebde44fade0973e870..279796419ea0ca036800483aad59321e881efbe5 100644 (file)
@@ -1079,6 +1079,8 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv,
 {
        u16 status = le16_to_cpu(tx_resp->status.status);
 
+       info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
        info->status.rates[0].count = tx_resp->failure_frame + 1;
        info->flags |= iwl_tx_status_to_mac80211(status);
        iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
index dad4c4aad91f2a461cdebfc9ac879b51a36db827..8389cd38338ba70766561d13c35591e1073faca6 100644 (file)
@@ -1166,6 +1166,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
        else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
                 !trans_pcie->inta)
                iwl_enable_interrupts(trans);
+       return IRQ_HANDLED;
 
 none:
        /* re-enable interrupts here since we don't have anything to service. */
index a875499f89452d7ab4a4307b72c0475d5829f470..cdb11b3964e27dd68de20ac68ab8442772a070a1 100644 (file)
@@ -1459,7 +1459,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
        struct cfg80211_ssid req_ssid;
        int ret, auth_type = 0;
        struct cfg80211_bss *bss = NULL;
-       u8 is_scanning_required = 0, config_bands = 0;
+       u8 is_scanning_required = 0;
 
        memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
 
@@ -1478,19 +1478,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
        /* disconnect before try to associate */
        mwifiex_deauthenticate(priv, NULL);
 
-       if (channel) {
-               if (mode == NL80211_IFTYPE_STATION) {
-                       if (channel->band == IEEE80211_BAND_2GHZ)
-                               config_bands = BAND_B | BAND_G | BAND_GN;
-                       else
-                               config_bands = BAND_A | BAND_AN;
-
-                       if (!((config_bands | priv->adapter->fw_bands) &
-                             ~priv->adapter->fw_bands))
-                               priv->adapter->config_bands = config_bands;
-               }
-       }
-
        /* As this is new association, clear locally stored
         * keys and security related flags */
        priv->sec_info.wpa_enabled = false;
@@ -1707,9 +1694,9 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
 
                if (cfg80211_get_chandef_type(&params->chandef) !=
                                                NL80211_CHAN_NO_HT)
-                       config_bands |= BAND_GN;
+                       config_bands |= BAND_G | BAND_GN;
        } else {
-               if (cfg80211_get_chandef_type(&params->chandef) !=
+               if (cfg80211_get_chandef_type(&params->chandef) ==
                                                NL80211_CHAN_NO_HT)
                        config_bands = BAND_A;
                else
index 13fbc4eb15952fe375be1e10c55518bb2b6b3836..b879e1338a54f5347a7a5f0b955b98a3f3566b66 100644 (file)
@@ -161,7 +161,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
 
        if (pdev) {
                card = (struct pcie_service_card *) pci_get_drvdata(pdev);
-               if (!card || card->adapter) {
+               if (!card || !card->adapter) {
                        pr_err("Card or adapter structure is not valid\n");
                        return 0;
                }
index 9189a32b7844b713815636d03517e7532da31f94..973a9d90e9ea06542fe6b7e9169c0de6d4922531 100644 (file)
@@ -1563,7 +1563,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
                        scan_rsp->number_of_sets);
                ret = -1;
-               goto done;
+               goto check_next_scan;
        }
 
        bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
@@ -1634,7 +1634,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                if (!beacon_size || beacon_size > bytes_left) {
                        bss_info += bytes_left;
                        bytes_left = 0;
-                       return -1;
+                       ret = -1;
+                       goto check_next_scan;
                }
 
                /* Initialize the current working beacon pointer for this BSS
@@ -1690,7 +1691,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                                dev_err(priv->adapter->dev,
                                        "%s: bytes left < IE length\n",
                                        __func__);
-                               goto done;
+                               goto check_next_scan;
                        }
                        if (element_id == WLAN_EID_DS_PARAMS) {
                                channel = *(current_ptr + sizeof(struct ieee_types_header));
@@ -1753,6 +1754,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                }
        }
 
+check_next_scan:
        spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
        if (list_empty(&adapter->scan_pending_q)) {
                spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
@@ -1813,7 +1815,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                }
        }
 
-done:
        return ret;
 }
 
index cb682561c43898fd6f27c03ab3aba38adbf269d8..f542bb8ccbc8d4ce6859e8fff1e45784183f8fbb 100644 (file)
@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
  */
 int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 {
-       bool cancel_flag = false;
        int status;
        struct cmd_ctrl_node *cmd_queued;
 
@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
        atomic_inc(&adapter->cmd_pending);
 
        /* Wait for completion */
-       wait_event_interruptible(adapter->cmd_wait_q.wait,
-                                *(cmd_queued->condition));
-       if (!*(cmd_queued->condition))
-               cancel_flag = true;
-
-       if (cancel_flag) {
-               mwifiex_cancel_pending_ioctl(adapter);
-               dev_dbg(adapter->dev, "cmd cancel\n");
+       status = wait_event_interruptible(adapter->cmd_wait_q.wait,
+                                         *(cmd_queued->condition));
+       if (status) {
+               dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
+               return status;
        }
 
        status = adapter->cmd_wait_q.status;
@@ -287,6 +283,20 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                if (ret)
                        goto done;
 
+               if (bss_desc) {
+                       u8 config_bands = 0;
+
+                       if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band)
+                           == HostCmd_SCAN_RADIO_TYPE_BG)
+                               config_bands = BAND_B | BAND_G | BAND_GN;
+                       else
+                               config_bands = BAND_A | BAND_AN;
+
+                       if (!((config_bands | adapter->fw_bands) &
+                             ~adapter->fw_bands))
+                               adapter->config_bands = config_bands;
+               }
+
                ret = mwifiex_check_network_compatibility(priv, bss_desc);
                if (ret)
                        goto done;
@@ -496,8 +506,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
                return false;
        }
 
-       wait_event_interruptible(adapter->hs_activate_wait_q,
-                                adapter->hs_activate_wait_q_woken);
+       if (wait_event_interruptible(adapter->hs_activate_wait_q,
+                                    adapter->hs_activate_wait_q_woken)) {
+               dev_err(adapter->dev, "hs_activate_wait_q terminated\n");
+               return false;
+       }
 
        return true;
 }
index f221b95b90b3c2935c67e9c272d5f1c2a89000d4..a00a03ea4ec99dc90a71520e1b56daa462632b38 100644 (file)
@@ -318,20 +318,20 @@ struct mwl8k_sta {
 #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
 
 static const struct ieee80211_channel mwl8k_channels_24[] = {
-       { .center_freq = 2412, .hw_value = 1, },
-       { .center_freq = 2417, .hw_value = 2, },
-       { .center_freq = 2422, .hw_value = 3, },
-       { .center_freq = 2427, .hw_value = 4, },
-       { .center_freq = 2432, .hw_value = 5, },
-       { .center_freq = 2437, .hw_value = 6, },
-       { .center_freq = 2442, .hw_value = 7, },
-       { .center_freq = 2447, .hw_value = 8, },
-       { .center_freq = 2452, .hw_value = 9, },
-       { .center_freq = 2457, .hw_value = 10, },
-       { .center_freq = 2462, .hw_value = 11, },
-       { .center_freq = 2467, .hw_value = 12, },
-       { .center_freq = 2472, .hw_value = 13, },
-       { .center_freq = 2484, .hw_value = 14, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, },
+       { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, },
 };
 
 static const struct ieee80211_rate mwl8k_rates_24[] = {
@@ -352,10 +352,10 @@ static const struct ieee80211_rate mwl8k_rates_24[] = {
 };
 
 static const struct ieee80211_channel mwl8k_channels_50[] = {
-       { .center_freq = 5180, .hw_value = 36, },
-       { .center_freq = 5200, .hw_value = 40, },
-       { .center_freq = 5220, .hw_value = 44, },
-       { .center_freq = 5240, .hw_value = 48, },
+       { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, },
+       { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
+       { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
+       { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
 };
 
 static const struct ieee80211_rate mwl8k_rates_50[] = {
@@ -4250,9 +4250,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
        p->amsdu_enabled = 0;
 
        rc = mwl8k_post_cmd(hw, &cmd->header);
+       if (!rc)
+               rc = p->station_id;
        kfree(cmd);
 
-       return rc ? rc : p->station_id;
+       return rc;
 }
 
 static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
index e71c702e2eb18e30640cd193307bb54569410b48..800a16526c8ea548b17d67ab0f7d30a50b0cc327 100644 (file)
@@ -47,6 +47,7 @@ static struct usb_device_id p54u_table[] = {
        {USB_DEVICE(0x0411, 0x0050)},   /* Buffalo WLI2-USB2-G54 */
        {USB_DEVICE(0x045e, 0x00c2)},   /* Microsoft MN-710 */
        {USB_DEVICE(0x0506, 0x0a11)},   /* 3COM 3CRWE254G72 */
+       {USB_DEVICE(0x0675, 0x0530)},   /* DrayTek Vigor 530 */
        {USB_DEVICE(0x06b9, 0x0120)},   /* Thomson SpeedTouch 120g */
        {USB_DEVICE(0x0707, 0xee06)},   /* SMC 2862W-G */
        {USB_DEVICE(0x07aa, 0x001c)},   /* Corega CG-WLUSB2GT */
@@ -82,6 +83,8 @@ static struct usb_device_id p54u_table[] = {
        {USB_DEVICE(0x06a9, 0x000e)},   /* Westell 802.11g USB (A90-211WG-01) */
        {USB_DEVICE(0x06b9, 0x0121)},   /* Thomson SpeedTouch 121g */
        {USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
+       {USB_DEVICE(0x0803, 0x4310)},   /* Zoom 4410a */
+       {USB_DEVICE(0x083a, 0x4503)},   /* T-Com Sinus 154 data II */
        {USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
        {USB_DEVICE(0x083a, 0xc501)},   /* Zoom Wireless-G 4410 */
        {USB_DEVICE(0x083a, 0xf503)},   /* Accton FD7050E ver 1010ec  */
@@ -101,6 +104,7 @@ static struct usb_device_id p54u_table[] = {
        {USB_DEVICE(0x13B1, 0x000C)},   /* Linksys WUSB54AG */
        {USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
        {USB_DEVICE(0x1435, 0x0427)},   /* Inventel UR054G */
+       /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */
        {USB_DEVICE(0x1668, 0x1050)},   /* Actiontec 802UIG-1 */
        {USB_DEVICE(0x1740, 0x1000)},   /* Senao NUB-350 */
        {USB_DEVICE(0x2001, 0x3704)},   /* DLink DWL-G122 rev A2 */
index 21b1bbb93a7e41452720a6f9ede17cba3951393e..b80bc4612581857455c2e076de835f66ac5be710 100644 (file)
@@ -57,12 +57,12 @@ config RTL8192CU
 
 config RTLWIFI
        tristate
-       depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
+       depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
        default m
 
 config RTLWIFI_DEBUG
        bool "Additional debugging output"
-       depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
+       depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
        default y
 
 config RTL8192C_COMMON
index 4494d130b37cb0d0ad585eea5142e0c312c86b26..0f8b05185edaeacb6ef686e5e5a1ca0151866916 100644 (file)
@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                                         is_tx ? "Tx" : "Rx");
 
                                if (is_tx) {
-                                       rtl_lps_leave(hw);
+                                       schedule_work(&rtlpriv->
+                                                     works.lps_leave_work);
                                        ppsc->last_delaylps_stamp_jiffies =
                                            jiffies;
                                }
@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                }
        } else if (ETH_P_ARP == ether_type) {
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                         "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
 
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
index 3deacafdcd5ed3c33c1384a9f5e84e4cd08517e8..4261e8ecc4c382d84a9b19c40d8fed2b463d5a5a 100644 (file)
@@ -743,6 +743,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 
 done:
                bufferaddress = (*((dma_addr_t *)skb->cb));
+               if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress))
+                       return;
                tmp_one = 1;
                rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
                                            HW_DESC_RXBUFF_ADDR,
@@ -1115,6 +1117,10 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
                                           PCI_DMA_FROMDEVICE);
 
                        bufferaddress = (*((dma_addr_t *)skb->cb));
+                       if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) {
+                               dev_kfree_skb_any(skb);
+                               return 1;
+                       }
                        rtlpriv->cfg->ops->set_desc((u8 *)entry, false,
                                                    HW_DESC_RXBUFF_ADDR,
                                                    (u8 *)&bufferaddress);
index 1d5d3604e3e03875f5e9ec4453ad2291c5de3c33..246e5352f2e15a850dbc7971c08bdbbcffbc7172 100644 (file)
@@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
        if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
                rtl92c_phy_sw_chnl_callback(hw);
                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-                        "sw_chnl_inprogress false schdule workitem\n");
+                        "sw_chnl_inprogress false schedule workitem\n");
                rtlphy->sw_chnl_inprogress = false;
        } else {
                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
index 173424756149b95d7d1bc9ea6eb9981fa6603130..c31795e379f7e16a1a5a208f10af3d994eff3b66 100644 (file)
@@ -611,8 +611,14 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
        dma_addr_t mapping = pci_map_single(rtlpci->pdev,
                                            skb->data, skb->len,
                                            PCI_DMA_TODEVICE);
+
        u8 bw_40 = 0;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        rcu_read_lock();
        sta = get_sta(hw, mac->vif, mac->bssid);
        if (mac->opmode == NL80211_IFTYPE_STATION) {
@@ -774,6 +780,11 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
        __le16 fc = hdr->frame_control;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
 
        if (firstseg)
index f9f3861046c1f6c4deb0a9454b872ca260618f16..a0fbf284420ec78b2570756dc4c1edd2638be057 100644 (file)
@@ -587,6 +587,11 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
        buf_len = skb->len;
        mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
                                 PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d));
        if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
                firstseg = true;
@@ -740,6 +745,11 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
        __le16 fc = hdr->frame_control;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
        if (firstseg)
                SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
index 0e9f6ebf078add38ded9595f6a454b8182148335..206561d7282f906a6662ce43610f87666362dbe3 100644 (file)
@@ -611,6 +611,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
                    PCI_DMA_TODEVICE);
        u8 bw_40 = 0;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        if (mac->opmode == NL80211_IFTYPE_STATION) {
                bw_40 = mac->bw_40;
        } else if (mac->opmode == NL80211_IFTYPE_AP ||
@@ -763,6 +768,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
 void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
        bool firstseg, bool lastseg, struct sk_buff *skb)
 {
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
@@ -770,7 +776,12 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
        dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
                        PCI_DMA_TODEVICE);
 
-    /* Clear all status        */
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
+       /* Clear all status     */
        CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S);
 
        /* This bit indicate this packet is used for FW download. */
index 39cc7938eedfe44da35ea7a37134a705cfc4db5e..3d8536bb0d2bf5055c181d5d8f4b67d25153488b 100644 (file)
@@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw)
        if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
                rtl8723ae_phy_sw_chnl_callback(hw);
                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-                        "sw_chnl_inprogress false schdule workitem\n");
+                        "sw_chnl_inprogress false schedule workitem\n");
                rtlphy->sw_chnl_inprogress = false;
        } else {
                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
index 18b0bc51766b64d21e7598be175a293422b064f4..bb7cc90bafb22f8c5bdbc61672b527a78442a715 100644 (file)
@@ -341,7 +341,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = {
        .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
 };
 
-static struct pci_device_id rtl8723ae_pci_ids[] __devinitdata = {
+static struct pci_device_id rtl8723ae_pci_ids[] = {
        {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8723, rtl8723ae_hal_cfg)},
        {},
 };
index 87331d826d73aa6bda0b4ee4a1f9a7da16dc7639..a313be8c21d28d5708fdbc34e49f0db3fa7836a2 100644 (file)
@@ -387,6 +387,11 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
                                            PCI_DMA_TODEVICE);
        u8 bw_40 = 0;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        if (mac->opmode == NL80211_IFTYPE_STATION) {
                bw_40 = mac->bw_40;
        } else if (mac->opmode == NL80211_IFTYPE_AP ||
@@ -542,6 +547,11 @@ void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw,
                                            PCI_DMA_TODEVICE);
        __le16 fc = hdr->frame_control;
 
+       if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
+               RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+                        "DMA mapping error");
+               return;
+       }
        CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
 
        if (firstseg)
index 29f0969e4ba00cd3dd299c209ac09f594346b168..1535efda3d525a0dfafe54bb4442aacec4b00446 100644 (file)
@@ -210,17 +210,16 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
        u16 index = REALTEK_USB_VENQT_CMD_IDX;
        int pipe = usb_sndctrlpipe(udev, 0); /* write_out */
        u8 *buffer;
-       dma_addr_t dma_addr;
 
-       wvalue = (u16)(addr&0x0000ffff);
-       buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr);
+       wvalue = (u16)(addr & 0x0000ffff);
+       buffer = kmalloc(len, GFP_ATOMIC);
        if (!buffer)
                return;
        memcpy(buffer, data, len);
        usb_control_msg(udev, pipe, request, reqtype, wvalue,
                        index, buffer, len, 50);
 
-       usb_free_coherent(udev, (size_t)len, buffer, dma_addr);
+       kfree(buffer);
 }
 
 static void _rtl_usb_io_handler_init(struct device *dev,
@@ -543,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
        WARN_ON(skb_queue_empty(&rx_queue));
        while (!skb_queue_empty(&rx_queue)) {
                _skb = skb_dequeue(&rx_queue);
-               _rtl_usb_rx_process_agg(hw, skb);
-               ieee80211_rx_irqsafe(hw, skb);
+               _rtl_usb_rx_process_agg(hw, _skb);
+               ieee80211_rx_irqsafe(hw, _skb);
        }
 }
 
@@ -640,6 +639,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
                        RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
                                 "Failed to prep_rx_urb!!\n");
                        err = PTR_ERR(skb);
+                       usb_free_urb(urb);
                        goto err_out;
                }
 
index 94b79c3338c4260200306f180ff053b87006faa6..9d7f1723dd8f750126337d7792a0614fea8ca601 100644 (file)
@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);
 /* Notify xenvif that ring now has space to send an skb to the frontend */
 void xenvif_notify_tx_completion(struct xenvif *vif);
 
+/* Prevent the device from generating any further traffic. */
+void xenvif_carrier_off(struct xenvif *vif);
+
 /* Returns number of ring slots required to send an skb to the frontend */
 unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
 
index b7d41f8c338a8372cea8bfe6649386c6a0d8b090..b8c5193bd420030a363ba30c14e8b485a8d6c5cc 100644 (file)
@@ -343,17 +343,22 @@ err:
        return err;
 }
 
-void xenvif_disconnect(struct xenvif *vif)
+void xenvif_carrier_off(struct xenvif *vif)
 {
        struct net_device *dev = vif->dev;
-       if (netif_carrier_ok(dev)) {
-               rtnl_lock();
-               netif_carrier_off(dev); /* discard queued packets */
-               if (netif_running(dev))
-                       xenvif_down(vif);
-               rtnl_unlock();
-               xenvif_put(vif);
-       }
+
+       rtnl_lock();
+       netif_carrier_off(dev); /* discard queued packets */
+       if (netif_running(dev))
+               xenvif_down(vif);
+       rtnl_unlock();
+       xenvif_put(vif);
+}
+
+void xenvif_disconnect(struct xenvif *vif)
+{
+       if (netif_carrier_ok(vif->dev))
+               xenvif_carrier_off(vif);
 
        atomic_dec(&vif->refcnt);
        wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
index f2d6b78d901d92d3965fe3bd849751f04fb7ccf3..2b9520c46e97a8de263b10f602bdb8cc35af0277 100644 (file)
@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif)
        atomic_dec(&netbk->netfront_count);
 }
 
-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx);
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
+                                 u8 status);
 static void make_tx_response(struct xenvif *vif,
                             struct xen_netif_tx_request *txp,
                             s8       st);
@@ -879,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif,
 
        do {
                make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               if (cons >= end)
+               if (cons == end)
                        break;
                txp = RING_GET_REQUEST(&vif->tx, cons++);
        } while (1);
@@ -888,6 +889,13 @@ static void netbk_tx_err(struct xenvif *vif,
        xenvif_put(vif);
 }
 
+static void netbk_fatal_tx_err(struct xenvif *vif)
+{
+       netdev_err(vif->dev, "fatal error; disabling device\n");
+       xenvif_carrier_off(vif);
+       xenvif_put(vif);
+}
+
 static int netbk_count_requests(struct xenvif *vif,
                                struct xen_netif_tx_request *first,
                                struct xen_netif_tx_request *txp,
@@ -901,19 +909,22 @@ static int netbk_count_requests(struct xenvif *vif,
 
        do {
                if (frags >= work_to_do) {
-                       netdev_dbg(vif->dev, "Need more frags\n");
+                       netdev_err(vif->dev, "Need more frags\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
                if (unlikely(frags >= MAX_SKB_FRAGS)) {
-                       netdev_dbg(vif->dev, "Too many frags\n");
+                       netdev_err(vif->dev, "Too many frags\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
                memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
                       sizeof(*txp));
                if (txp->size > first->size) {
-                       netdev_dbg(vif->dev, "Frags galore\n");
+                       netdev_err(vif->dev, "Frag is bigger than frame.\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
@@ -921,8 +932,9 @@ static int netbk_count_requests(struct xenvif *vif,
                frags++;
 
                if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
-                       netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n",
+                       netdev_err(vif->dev, "txp->offset: %x, size: %u\n",
                                 txp->offset, txp->size);
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
        } while ((txp++)->flags & XEN_NETTXF_more_data);
@@ -966,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
                pending_idx = netbk->pending_ring[index];
                page = xen_netbk_alloc_page(netbk, skb, pending_idx);
                if (!page)
-                       return NULL;
+                       goto err;
 
                gop->source.u.ref = txp->gref;
                gop->source.domid = vif->domid;
@@ -988,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
        }
 
        return gop;
+err:
+       /* Unwind, freeing all pages and sending error responses. */
+       while (i-- > start) {
+               xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]),
+                                     XEN_NETIF_RSP_ERROR);
+       }
+       /* The head too, if necessary. */
+       if (start)
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
+
+       return NULL;
 }
 
 static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
@@ -996,30 +1019,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 {
        struct gnttab_copy *gop = *gopp;
        u16 pending_idx = *((u16 *)skb->data);
-       struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
-       struct xenvif *vif = pending_tx_info[pending_idx].vif;
-       struct xen_netif_tx_request *txp;
        struct skb_shared_info *shinfo = skb_shinfo(skb);
        int nr_frags = shinfo->nr_frags;
        int i, err, start;
 
        /* Check status of header. */
        err = gop->status;
-       if (unlikely(err)) {
-               pending_ring_idx_t index;
-               index = pending_index(netbk->pending_prod++);
-               txp = &pending_tx_info[pending_idx].req;
-               make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               netbk->pending_ring[index] = pending_idx;
-               xenvif_put(vif);
-       }
+       if (unlikely(err))
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
 
        /* Skip first skb fragment if it is on same page as header fragment. */
        start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
 
        for (i = start; i < nr_frags; i++) {
                int j, newerr;
-               pending_ring_idx_t index;
 
                pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
 
@@ -1028,16 +1041,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
                if (likely(!newerr)) {
                        /* Had a previous error? Invalidate this fragment. */
                        if (unlikely(err))
-                               xen_netbk_idx_release(netbk, pending_idx);
+                               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                        continue;
                }
 
                /* Error on this fragment: respond to client with an error. */
-               txp = &netbk->pending_tx_info[pending_idx].req;
-               make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               index = pending_index(netbk->pending_prod++);
-               netbk->pending_ring[index] = pending_idx;
-               xenvif_put(vif);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
 
                /* Not the first error? Preceding frags already invalidated. */
                if (err)
@@ -1045,10 +1054,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 
                /* First error: invalidate header and preceding fragments. */
                pending_idx = *((u16 *)skb->data);
-               xen_netbk_idx_release(netbk, pending_idx);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                for (j = start; j < i; j++) {
                        pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
-                       xen_netbk_idx_release(netbk, pending_idx);
+                       xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                }
 
                /* Remember the error: invalidate all subsequent fragments. */
@@ -1082,7 +1091,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
 
                /* Take an extra reference to offset xen_netbk_idx_release */
                get_page(netbk->mmap_pages[pending_idx]);
-               xen_netbk_idx_release(netbk, pending_idx);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
        }
 }
 
@@ -1095,7 +1104,8 @@ static int xen_netbk_get_extras(struct xenvif *vif,
 
        do {
                if (unlikely(work_to_do-- <= 0)) {
-                       netdev_dbg(vif->dev, "Missing extra info\n");
+                       netdev_err(vif->dev, "Missing extra info\n");
+                       netbk_fatal_tx_err(vif);
                        return -EBADR;
                }
 
@@ -1104,8 +1114,9 @@ static int xen_netbk_get_extras(struct xenvif *vif,
                if (unlikely(!extra.type ||
                             extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
                        vif->tx.req_cons = ++cons;
-                       netdev_dbg(vif->dev,
+                       netdev_err(vif->dev,
                                   "Invalid extra type: %d\n", extra.type);
+                       netbk_fatal_tx_err(vif);
                        return -EINVAL;
                }
 
@@ -1121,13 +1132,15 @@ static int netbk_set_skb_gso(struct xenvif *vif,
                             struct xen_netif_extra_info *gso)
 {
        if (!gso->u.gso.size) {
-               netdev_dbg(vif->dev, "GSO size must not be zero.\n");
+               netdev_err(vif->dev, "GSO size must not be zero.\n");
+               netbk_fatal_tx_err(vif);
                return -EINVAL;
        }
 
        /* Currently only TCPv4 S.O. is supported. */
        if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
-               netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+               netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+               netbk_fatal_tx_err(vif);
                return -EINVAL;
        }
 
@@ -1264,9 +1277,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 
                /* Get a netif from the list with work to do. */
                vif = poll_net_schedule_list(netbk);
+               /* This can sometimes happen because the test of
+                * list_empty(net_schedule_list) at the top of the
+                * loop is unlocked.  Just go back and have another
+                * look.
+                */
                if (!vif)
                        continue;
 
+               if (vif->tx.sring->req_prod - vif->tx.req_cons >
+                   XEN_NETIF_TX_RING_SIZE) {
+                       netdev_err(vif->dev,
+                                  "Impossible number of requests. "
+                                  "req_prod %d, req_cons %d, size %ld\n",
+                                  vif->tx.sring->req_prod, vif->tx.req_cons,
+                                  XEN_NETIF_TX_RING_SIZE);
+                       netbk_fatal_tx_err(vif);
+                       continue;
+               }
+
                RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
                if (!work_to_do) {
                        xenvif_put(vif);
@@ -1294,17 +1323,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
                        work_to_do = xen_netbk_get_extras(vif, extras,
                                                          work_to_do);
                        idx = vif->tx.req_cons;
-                       if (unlikely(work_to_do < 0)) {
-                               netbk_tx_err(vif, &txreq, idx);
+                       if (unlikely(work_to_do < 0))
                                continue;
-                       }
                }
 
                ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do);
-               if (unlikely(ret < 0)) {
-                       netbk_tx_err(vif, &txreq, idx - ret);
+               if (unlikely(ret < 0))
                        continue;
-               }
+
                idx += ret;
 
                if (unlikely(txreq.size < ETH_HLEN)) {
@@ -1316,11 +1342,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 
                /* No crossing a page as the payload mustn't fragment. */
                if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
-                       netdev_dbg(vif->dev,
+                       netdev_err(vif->dev,
                                   "txreq.offset: %x, size: %u, end: %lu\n",
                                   txreq.offset, txreq.size,
                                   (txreq.offset&~PAGE_MASK) + txreq.size);
-                       netbk_tx_err(vif, &txreq, idx);
+                       netbk_fatal_tx_err(vif);
                        continue;
                }
 
@@ -1348,8 +1374,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
                        gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
 
                        if (netbk_set_skb_gso(vif, skb, gso)) {
+                               /* Failure in netbk_set_skb_gso is fatal. */
                                kfree_skb(skb);
-                               netbk_tx_err(vif, &txreq, idx);
                                continue;
                        }
                }
@@ -1448,7 +1474,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
                        txp->size -= data_len;
                } else {
                        /* Schedule a response immediately. */
-                       xen_netbk_idx_release(netbk, pending_idx);
+                       xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                }
 
                if (txp->flags & XEN_NETTXF_csum_blank)
@@ -1500,7 +1526,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk)
        xen_netbk_tx_submit(netbk);
 }
 
-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
+                                 u8 status)
 {
        struct xenvif *vif;
        struct pending_tx_info *pending_tx_info;
@@ -1514,7 +1541,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
 
        vif = pending_tx_info->vif;
 
-       make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY);
+       make_tx_response(vif, &pending_tx_info->req, status);
 
        index = pending_index(netbk->pending_prod++);
        netbk->pending_ring[index] = pending_idx;
index c26e28b4bd9f985a4d7c6d3307d969bb671bf6f7..7ffa43bd7cf9e9f3b1fc43f83d0ec4c53b355765 100644 (file)
@@ -1015,29 +1015,10 @@ err:
                i = xennet_fill_frags(np, skb, &tmpq);
 
                /*
-                * Truesize approximates the size of true data plus
-                * any supervisor overheads. Adding hypervisor
-                * overheads has been shown to significantly reduce
-                * achievable bandwidth with the default receive
-                * buffer size. It is therefore not wise to account
-                * for it here.
-                *
-                * After alloc_skb(RX_COPY_THRESHOLD), truesize is set
-                * to RX_COPY_THRESHOLD + the supervisor
-                * overheads. Here, we add the size of the data pulled
-                * in xennet_fill_frags().
-                *
-                * We also adjust for any unused space in the main
-                * data area by subtracting (RX_COPY_THRESHOLD -
-                * len). This is especially important with drivers
-                * which split incoming packets into header and data,
-                * using only 66 bytes of the main data area (see the
-                * e1000 driver for example.)  On such systems,
-                * without this last adjustement, our achievable
-                * receive throughout using the standard receive
-                * buffer size was cut by 25%(!!!).
-                */
-               skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
+                 * Truesize is the actual allocation size, even if the
+                 * allocation is only partially used.
+                 */
+               skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags;
                skb->len += skb->data_len;
 
                if (rx->flags & XEN_NETRXF_csum_blank)
index 7da9071b68b60669c7d24441dee721b1c82c87fd..2a9c8d93d2e8a302e8db87b91160e7fdd301a77d 100644 (file)
@@ -361,8 +361,8 @@ static struct nfc_phy_ops i2c_phy_ops = {
        .disable = pn544_hci_i2c_disable,
 };
 
-static int __devinit pn544_hci_i2c_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int pn544_hci_i2c_probe(struct i2c_client *client,
+                              const struct i2c_device_id *id)
 {
        struct pn544_i2c_phy *phy;
        struct pn544_nfc_platform_data *pdata;
@@ -442,7 +442,7 @@ err_phy_alloc:
        return r;
 }
 
-static __devexit int pn544_hci_i2c_remove(struct i2c_client *client)
+static int pn544_hci_i2c_remove(struct i2c_client *client)
 {
        struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
        struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
@@ -469,7 +469,7 @@ static struct i2c_driver pn544_hci_i2c_driver = {
                  },
        .probe = pn544_hci_i2c_probe,
        .id_table = pn544_hci_i2c_id_table,
-       .remove = __devexit_p(pn544_hci_i2c_remove),
+       .remove = pn544_hci_i2c_remove,
 };
 
 static int __init pn544_hci_i2c_init(void)
index fb6a1fe21b931c861424a3829dedef4ee083cef2..8e4e86b78428da19302e02d36203deac21a909e8 100644 (file)
@@ -430,7 +430,7 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
  * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
  * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
  */
-static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+static void quirk_cirrus_cardbus(struct pci_dev *dev)
 {
        u8 new_irq = dev->irq - 1;
        printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
index fdd63a6a62d6b4532da27a1a7ed7cd0ab7857c0c..2ef7103270bb7eb250ae15e16650c17a46a643d7 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/init.h>                /* for __init and __devinit */
+#include <linux/init.h>                /* for __init */
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
index 352f96180bc71f848464b6f9a9a5ad914d92004d..050773c368238d0d6fe7ffdd53db1e3ecc5ebc62 100644 (file)
@@ -137,7 +137,7 @@ struct parport_operations parport_gsc_ops =
 /*
  * Checks for port existence, all ports support SPP MODE
  */
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
 {
        unsigned char r, w;
 
@@ -201,7 +201,7 @@ static int __devinit parport_SPP_supported(struct parport *pb)
  * be misdetected here is rather academic. 
  */
 
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
 {
        int ok = 0;
   
@@ -232,10 +232,9 @@ static int __devinit parport_PS2_supported(struct parport *pb)
 
 /* --- Initialisation code -------------------------------- */
 
-struct parport *__devinit parport_gsc_probe_port (unsigned long base,
-                                                unsigned long base_hi,
-                                                int irq, int dma,
-                                                struct pci_dev *dev)
+struct parport *parport_gsc_probe_port(unsigned long base,
+                                      unsigned long base_hi, int irq,
+                                      int dma, struct pci_dev *dev)
 {
        struct parport_gsc_private *priv;
        struct parport_operations *ops;
@@ -345,9 +344,9 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
 
 #define PARPORT_GSC_OFFSET 0x800
 
-static int __devinitdata parport_count;
+static int parport_count;
 
-static int __devinit parport_init_chip(struct parisc_device *dev)
+static int parport_init_chip(struct parisc_device *dev)
 {
        struct parport *p;
        unsigned long port;
@@ -382,7 +381,7 @@ static int __devinit parport_init_chip(struct parisc_device *dev)
        return 0;
 }
 
-static int __devexit parport_remove_chip(struct parisc_device *dev)
+static int parport_remove_chip(struct parisc_device *dev)
 {
        struct parport *p = dev_get_drvdata(&dev->dev);
        if (p) {
@@ -415,15 +414,15 @@ static struct parisc_driver parport_driver = {
        .name           = "Parallel",
        .id_table       = parport_tbl,
        .probe          = parport_init_chip,
-       .remove         = __devexit_p(parport_remove_chip),
+       .remove         = parport_remove_chip,
 };
 
-int __devinit parport_gsc_init(void)
+int parport_gsc_init(void)
 {
        return register_parisc_driver(&parport_driver);
 }
 
-static void __devexit parport_gsc_exit(void)
+static void parport_gsc_exit(void)
 {
        unregister_parisc_driver(&parport_driver);
 }
index 5abffe58a9d2108c2e4fc8aa66ef39fc7bcfee33..903e1285fda06ce30c84bf79b44078e733048c38 100644 (file)
@@ -953,7 +953,7 @@ static struct superio_struct *find_free_superio(void)
 
 
 /* Super-IO chipset detection, Winbond, SMSC */
-static void __devinit show_parconfig_smsc37c669(int io, int key)
+static void show_parconfig_smsc37c669(int io, int key)
 {
        int cr1, cr4, cra, cr23, cr26, cr27;
        struct superio_struct *s;
@@ -1038,7 +1038,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key)
 }
 
 
-static void __devinit show_parconfig_winbond(int io, int key)
+static void show_parconfig_winbond(int io, int key)
 {
        int cr30, cr60, cr61, cr70, cr74, crf0;
        struct superio_struct *s;
@@ -1106,8 +1106,7 @@ static void __devinit show_parconfig_winbond(int io, int key)
        }
 }
 
-static void __devinit decode_winbond(int efer, int key, int devid,
-                                                       int devrev, int oldid)
+static void decode_winbond(int efer, int key, int devid, int devrev, int oldid)
 {
        const char *type = "unknown";
        int id, progif = 2;
@@ -1159,7 +1158,7 @@ static void __devinit decode_winbond(int efer, int key, int devid,
                show_parconfig_winbond(efer, key);
 }
 
-static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
+static void decode_smsc(int efer, int key, int devid, int devrev)
 {
        const char *type = "unknown";
        void (*func)(int io, int key);
@@ -1193,7 +1192,7 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
 }
 
 
-static void __devinit winbond_check(int io, int key)
+static void winbond_check(int io, int key)
 {
        int origval, devid, devrev, oldid, x_devid, x_devrev, x_oldid;
 
@@ -1231,7 +1230,7 @@ out:
        release_region(io, 3);
 }
 
-static void __devinit winbond_check2(int io, int key)
+static void winbond_check2(int io, int key)
 {
        int origval[3], devid, devrev, oldid, x_devid, x_devrev, x_oldid;
 
@@ -1272,7 +1271,7 @@ out:
        release_region(io, 3);
 }
 
-static void __devinit smsc_check(int io, int key)
+static void smsc_check(int io, int key)
 {
        int origval, id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev;
 
@@ -1316,7 +1315,7 @@ out:
 }
 
 
-static void __devinit detect_and_report_winbond(void)
+static void detect_and_report_winbond(void)
 {
        if (verbose_probing)
                printk(KERN_DEBUG "Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n");
@@ -1329,7 +1328,7 @@ static void __devinit detect_and_report_winbond(void)
        winbond_check2(0x250, 0x89);
 }
 
-static void __devinit detect_and_report_smsc(void)
+static void detect_and_report_smsc(void)
 {
        if (verbose_probing)
                printk(KERN_DEBUG "SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n");
@@ -1339,7 +1338,7 @@ static void __devinit detect_and_report_smsc(void)
        smsc_check(0x370, 0x44);
 }
 
-static void __devinit detect_and_report_it87(void)
+static void detect_and_report_it87(void)
 {
        u16 dev;
        u8 origval, r;
@@ -1796,24 +1795,24 @@ static int parport_ECPEPP_supported(struct parport *pb)
 #else /* No IEEE 1284 support */
 
 /* Don't bother probing for modes we know we won't use. */
-static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }
+static int parport_PS2_supported(struct parport *pb) { return 0; }
 #ifdef CONFIG_PARPORT_PC_FIFO
 static int parport_ECP_supported(struct parport *pb)
 {
        return 0;
 }
 #endif
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
 {
        return 0;
 }
 
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
 {
        return 0;
 }
 
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
 {
        return 0;
 }
@@ -2269,9 +2268,8 @@ EXPORT_SYMBOL(parport_pc_unregister_port);
 #ifdef CONFIG_PCI
 
 /* ITE support maintained by Rich Liu <richliu@poorman.org> */
-static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
-                                        int autodma,
-                                        const struct parport_pc_via_data *via)
+static int sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, int autodma,
+                             const struct parport_pc_via_data *via)
 {
        short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
        u32 ite8872set;
@@ -2377,10 +2375,10 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
 
 /* VIA 8231 support by Pavel Fedin <sonic_amiga@rambler.ru>
    based on VIA 686a support code by Jeff Garzik <jgarzik@pobox.com> */
-static int __devinitdata parport_init_mode;
+static int parport_init_mode;
 
 /* Data for two known VIA chips */
-static struct parport_pc_via_data via_686a_data __devinitdata = {
+static struct parport_pc_via_data via_686a_data = {
        0x51,
        0x50,
        0x85,
@@ -2389,7 +2387,7 @@ static struct parport_pc_via_data via_686a_data __devinitdata = {
        0xF0,
        0xE6
 };
-static struct parport_pc_via_data via_8231_data __devinitdata = {
+static struct parport_pc_via_data via_8231_data = {
        0x45,
        0x44,
        0x50,
@@ -2399,9 +2397,8 @@ static struct parport_pc_via_data via_8231_data __devinitdata = {
        0xF6
 };
 
-static int __devinit sio_via_probe(struct pci_dev *pdev, int autoirq,
-                                   int autodma,
-                                   const struct parport_pc_via_data *via)
+static int sio_via_probe(struct pci_dev *pdev, int autoirq, int autodma,
+                        const struct parport_pc_via_data *via)
 {
        u8 tmp, tmp2, siofunc;
        u8 ppcontrol = 0;
@@ -2575,7 +2572,7 @@ static struct parport_pc_superio {
        int (*probe) (struct pci_dev *pdev, int autoirq, int autodma,
                      const struct parport_pc_via_data *via);
        const struct parport_pc_via_data *via;
-} parport_pc_superio_info[] __devinitdata = {
+} parport_pc_superio_info[] = {
        { sio_via_probe, &via_686a_data, },
        { sio_via_probe, &via_8231_data, },
        { sio_ite_8872_probe, NULL, },
@@ -2860,7 +2857,7 @@ static int parport_pc_pci_probe(struct pci_dev *dev,
        return -ENODEV;
 }
 
-static void __devexit parport_pc_pci_remove(struct pci_dev *dev)
+static void parport_pc_pci_remove(struct pci_dev *dev)
 {
        struct pci_parport_data *data = pci_get_drvdata(dev);
        int i;
@@ -2879,7 +2876,7 @@ static struct pci_driver parport_pc_pci_driver = {
        .name           = "parport_pc",
        .id_table       = parport_pc_pci_tbl,
        .probe          = parport_pc_pci_probe,
-       .remove         = __devexit_p(parport_pc_pci_remove),
+       .remove         = parport_pc_pci_remove,
 };
 
 static int __init parport_pc_init_superio(int autoirq, int autodma)
@@ -2983,7 +2980,7 @@ static struct pnp_driver parport_pc_pnp_driver = {
 static struct pnp_driver parport_pc_pnp_driver;
 #endif /* CONFIG_PNP */
 
-static int __devinit parport_pc_platform_probe(struct platform_device *pdev)
+static int parport_pc_platform_probe(struct platform_device *pdev)
 {
        /* Always succeed, the actual probing is done in
         * parport_pc_probe_port(). */
@@ -2999,7 +2996,7 @@ static struct platform_driver parport_pc_platform_driver = {
 };
 
 /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
-static int __devinit __attribute__((unused))
+static int __attribute__((unused))
 parport_pc_find_isa_ports(int autoirq, int autodma)
 {
        int count = 0;
index 1631eeaf440e5bf29b33463ba5c65cb2d6da49de..ef6169adb845072fc73396a4d49a2ac45c472bfc 100644 (file)
@@ -87,7 +87,8 @@ struct parport_pc_pci {
                                struct parport_pc_pci *card, int failed);
 };
 
-static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par, int autoirq, int autodma)
+static int netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *par,
+                               int autoirq, int autodma)
 {
        /* the rule described below doesn't hold for this device */
        if (dev->device == PCI_DEVICE_ID_NETMOS_9835 &&
@@ -111,7 +112,7 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
        return 0;
 }
 
-static struct parport_pc_pci cards[] __devinitdata = {
+static struct parport_pc_pci cards[] = {
        /* titan_110l */                { 1, { { 3, -1 }, } },
        /* titan_210l */                { 1, { { 3, -1 }, } },
        /* netmos_9xx5_combo */         { 1, { { 2, -1 }, }, netmos_parallel_init },
@@ -258,7 +259,7 @@ MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
  * Cards not tested are marked n/t
  * If you have one of these cards and it works for you, please tell me..
  */
-static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
+static struct pciserial_board pci_parport_serial_boards[] = {
        [titan_110l] = {
                .flags          = FL_BASE1 | FL_BASE_BARS,
                .num_ports      = 1,
@@ -479,8 +480,7 @@ struct parport_serial_private {
 };
 
 /* Register the serial port(s) of a PCI card. */
-static int __devinit serial_register (struct pci_dev *dev,
-                                     const struct pci_device_id *id)
+static int serial_register(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        struct pciserial_board *board;
@@ -501,8 +501,7 @@ static int __devinit serial_register (struct pci_dev *dev,
 }
 
 /* Register the parallel port(s) of a PCI card. */
-static int __devinit parport_register (struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct parport_pc_pci *card;
        struct parport_serial_private *priv = pci_get_drvdata (dev);
@@ -563,8 +562,8 @@ static int __devinit parport_register (struct pci_dev *dev,
        return 0;
 }
 
-static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
-                                              const struct pci_device_id *id)
+static int parport_serial_pci_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
 {
        struct parport_serial_private *priv;
        int err;
@@ -599,7 +598,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
        return 0;
 }
 
-static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
+static void parport_serial_pci_remove(struct pci_dev *dev)
 {
        struct parport_serial_private *priv = pci_get_drvdata (dev);
        int i;
@@ -664,7 +663,7 @@ static struct pci_driver parport_serial_pci_driver = {
        .name           = "parport_serial",
        .id_table       = parport_serial_pci_tbl,
        .probe          = parport_serial_pci_probe,
-       .remove         = __devexit_p(parport_serial_pci_remove),
+       .remove         = parport_serial_pci_remove,
 #ifdef CONFIG_PM
        .suspend        = parport_serial_pci_suspend,
        .resume         = parport_serial_pci_resume,
index 983a2d2df6595d908c371460fc5b0ca57ca07786..5c4b6a1db6cad94e078d0a60489832b265fc5fea 100644 (file)
@@ -265,7 +265,7 @@ static struct parport_operations parport_sunbpp_ops =
        .owner          = THIS_MODULE,
 };
 
-static int __devinit bpp_probe(struct platform_device *op)
+static int bpp_probe(struct platform_device *op)
 {
        struct parport_operations *ops;
        struct bpp_regs __iomem *regs;
@@ -330,7 +330,7 @@ out_unmap:
        return err;
 }
 
-static int __devexit bpp_remove(struct platform_device *op)
+static int bpp_remove(struct platform_device *op)
 {
        struct parport *p = dev_get_drvdata(&op->dev);
        struct parport_operations *ops = p->ops;
@@ -367,7 +367,7 @@ static struct platform_driver bpp_sbus_driver = {
                .of_match_table = bpp_match,
        },
        .probe          = bpp_probe,
-       .remove         = __devexit_p(bpp_remove),
+       .remove         = bpp_remove,
 };
 
 module_platform_driver(bpp_sbus_driver);
index 26ffd3e3fb7463f84ce4385691fe19e028a26d0a..2c113de943233db361a41e2bdcd92202c37a32b7 100644 (file)
@@ -44,7 +44,6 @@ extern bool pciehp_poll_mode;
 extern int pciehp_poll_time;
 extern bool pciehp_debug;
 extern bool pciehp_force;
-extern struct workqueue_struct *pciehp_wq;
 
 #define dbg(format, arg...)                                            \
 do {                                                                   \
@@ -78,6 +77,7 @@ struct slot {
        struct hotplug_slot *hotplug_slot;
        struct delayed_work work;       /* work for button event */
        struct mutex lock;
+       struct workqueue_struct *wq;
 };
 
 struct event_info {
index 916bf4f53abadc16d9205ac41dc9e3edc6f839ec..939bd1d4b5b138b8f8bbe319007973579a6c39df 100644 (file)
@@ -42,7 +42,6 @@ bool pciehp_debug;
 bool pciehp_poll_mode;
 int pciehp_poll_time;
 bool pciehp_force;
-struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +339,13 @@ static int __init pcied_init(void)
 {
        int retval = 0;
 
-       pciehp_wq = alloc_workqueue("pciehp", 0, 0);
-       if (!pciehp_wq)
-               return -ENOMEM;
-
        pciehp_firmware_init();
        retval = pcie_port_service_register(&hpdriver_portdrv);
        dbg("pcie_port_service_register = %d\n", retval);
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       if (retval) {
-               destroy_workqueue(pciehp_wq);
+       if (retval)
                dbg("Failure to register service\n");
-       }
+
        return retval;
 }
 
@@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void)
 {
        dbg("unload_pciehpd()\n");
        pcie_port_service_unregister(&hpdriver_portdrv);
-       destroy_workqueue(pciehp_wq);
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
index 27f44295a65738976b4be0f07f4cd33b04e2cc85..38f01867917521a6402e92dbaaf5add19b27a640 100644 (file)
@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
        info->p_slot = p_slot;
        INIT_WORK(&info->work, interrupt_event_handler);
 
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 
        return 0;
 }
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
                kfree(info);
                goto out;
        }
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
  out:
        mutex_unlock(&p_slot->lock);
 }
@@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot)
                if (ATTN_LED(ctrl))
                        pciehp_set_attention_status(p_slot, 0);
 
-               queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
+               queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
                break;
        case BLINKINGOFF_STATE:
        case BLINKINGON_STATE:
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
        else
                p_slot->state = POWERON_STATE;
 
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 }
 
 static void interrupt_event_handler(struct work_struct *work)
index 13b2eaf7ba434f205896785a17eaf335842fbd66..5127f3f418211496ddf44b335ccc5ab44fbac856 100644 (file)
@@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl)
 static int pcie_init_slot(struct controller *ctrl)
 {
        struct slot *slot;
+       char name[32];
 
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
 
+       snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
+       slot->wq = alloc_workqueue(name, 0, 0);
+       if (!slot->wq)
+               goto abort;
+
        slot->ctrl = ctrl;
        mutex_init(&slot->lock);
        INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
        ctrl->slot = slot;
        return 0;
+abort:
+       kfree(slot);
+       return -ENOMEM;
 }
 
 static void pcie_cleanup_slot(struct controller *ctrl)
 {
        struct slot *slot = ctrl->slot;
        cancel_delayed_work(&slot->work);
-       flush_workqueue(pciehp_wq);
+       destroy_workqueue(slot->wq);
        kfree(slot);
 }
 
index ca64932e658b0c5e981c5bb746663045da9cc7ce..b849f995075a8cd13927ce0ee725279638b5796e 100644 (file)
@@ -46,8 +46,6 @@
 extern bool shpchp_poll_mode;
 extern int shpchp_poll_time;
 extern bool shpchp_debug;
-extern struct workqueue_struct *shpchp_wq;
-extern struct workqueue_struct *shpchp_ordered_wq;
 
 #define dbg(format, arg...)                                            \
 do {                                                                   \
@@ -91,6 +89,7 @@ struct slot {
        struct list_head        slot_list;
        struct delayed_work work;       /* work for button event */
        struct mutex lock;
+       struct workqueue_struct *wq;
        u8 hp_slot;
 };
 
index b6de307248e43cedf52a0a27eacf9211b61efe72..3100c52c837cfceccc7314646898f30846c96b39 100644 (file)
@@ -39,8 +39,6 @@
 bool shpchp_debug;
 bool shpchp_poll_mode;
 int shpchp_poll_time;
-struct workqueue_struct *shpchp_wq;
-struct workqueue_struct *shpchp_ordered_wq;
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl)
                slot->device = ctrl->slot_device_offset + i;
                slot->hpc_ops = ctrl->hpc_ops;
                slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
+
+               snprintf(name, sizeof(name), "shpchp-%d", slot->number);
+               slot->wq = alloc_workqueue(name, 0, 0);
+               if (!slot->wq) {
+                       retval = -ENOMEM;
+                       goto error_info;
+               }
+
                mutex_init(&slot->lock);
                INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
 
@@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl)
                if (retval) {
                        ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
                                 retval);
-                       goto error_info;
+                       goto error_slotwq;
                }
 
                get_power_status(hotplug_slot, &info->power_status);
@@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl)
        }
 
        return 0;
+error_slotwq:
+       destroy_workqueue(slot->wq);
 error_info:
        kfree(info);
 error_hpslot:
@@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl)
                slot = list_entry(tmp, struct slot, slot_list);
                list_del(&slot->slot_list);
                cancel_delayed_work(&slot->work);
-               flush_workqueue(shpchp_wq);
-               flush_workqueue(shpchp_ordered_wq);
+               destroy_workqueue(slot->wq);
                pci_hp_deregister(slot->hotplug_slot);
        }
 }
@@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = {
 
 static int __init shpcd_init(void)
 {
-       int retval = 0;
-
-       shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
-       if (!shpchp_wq)
-               return -ENOMEM;
-
-       shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
-       if (!shpchp_ordered_wq) {
-               destroy_workqueue(shpchp_wq);
-               return -ENOMEM;
-       }
+       int retval;
 
        retval = pci_register_driver(&shpc_driver);
        dbg("%s: pci_register_driver = %d\n", __func__, retval);
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       if (retval) {
-               destroy_workqueue(shpchp_ordered_wq);
-               destroy_workqueue(shpchp_wq);
-       }
+
        return retval;
 }
 
@@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void)
 {
        dbg("unload_shpchpd()\n");
        pci_unregister_driver(&shpc_driver);
-       destroy_workqueue(shpchp_ordered_wq);
-       destroy_workqueue(shpchp_wq);
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
index f9b5a52e4115c321367547c30644b545200928a9..58499277903a4ab4a6225982d88876de399120e2 100644 (file)
@@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
        info->p_slot = p_slot;
        INIT_WORK(&info->work, interrupt_event_handler);
 
-       queue_work(shpchp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 
        return 0;
 }
@@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
                kfree(info);
                goto out;
        }
-       queue_work(shpchp_ordered_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
  out:
        mutex_unlock(&p_slot->lock);
 }
@@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot)
                p_slot->hpc_ops->green_led_blink(p_slot);
                p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-               queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
+               queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
                break;
        case BLINKINGOFF_STATE:
        case BLINKINGON_STATE:
index bafd2bbcaf6541d1983fababa4563ae174837e15..c18e5bf444faa693d41c6a9103ef7ab8982b07da 100644 (file)
@@ -739,7 +739,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf);
 /**
  * pci_sriov_set_totalvfs -- reduce the TotalVFs available
  * @dev: the PCI PF device
- * numvfs: number that should be used for TotalVFs supported
+ * @numvfs: number that should be used for TotalVFs supported
  *
  * Should be called from PF driver's probe routine with
  * device's mutex held.
index 5099636a6e5f65782ea87fbb9c25a0aeeeed282e..00cc78c7aa045e9eb5ff747afce8ac3b66a57e7d 100644 (file)
@@ -845,6 +845,32 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
 }
 EXPORT_SYMBOL(pci_enable_msi_block);
 
+int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
+{
+       int ret, pos, nvec;
+       u16 msgctl;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (!pos)
+               return -EINVAL;
+
+       pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+       ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+
+       if (maxvec)
+               *maxvec = ret;
+
+       do {
+               nvec = ret;
+               ret = pci_enable_msi_block(dev, nvec);
+       } while (ret > 0);
+
+       if (ret < 0)
+               return ret;
+       return nvec;
+}
+EXPORT_SYMBOL(pci_enable_msi_block_auto);
+
 void pci_msi_shutdown(struct pci_dev *dev)
 {
        struct msi_desc *desc;
index 05b78b16d20bdca1acb822e7654360102fb09072..9c6e9bb674ec54835d40e09b6c77d0683cd9265d 100644 (file)
@@ -422,77 +422,60 @@ static ssize_t sriov_numvfs_show(struct device *dev,
 }
 
 /*
- * num_vfs > 0; number of vfs to enable
- * num_vfs = 0; disable all vfs
+ * num_vfs > 0; number of VFs to enable
+ * num_vfs = 0; disable all VFs
  *
  * Note: SRIOV spec doesn't allow partial VF
- *       disable, so its all or none.
+ *       disable, so it's all or none.
  */
 static ssize_t sriov_numvfs_store(struct device *dev,
                                  struct device_attribute *attr,
                                  const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       int num_vfs_enabled = 0;
-       int num_vfs;
-       int ret = 0;
-       u16 total;
+       int ret;
+       u16 num_vfs;
 
-       if (kstrtoint(buf, 0, &num_vfs) < 0)
-               return -EINVAL;
+       ret = kstrtou16(buf, 0, &num_vfs);
+       if (ret < 0)
+               return ret;
+
+       if (num_vfs > pci_sriov_get_totalvfs(pdev))
+               return -ERANGE;
+
+       if (num_vfs == pdev->sriov->num_VFs)
+               return count;           /* no change */
 
        /* is PF driver loaded w/callback */
        if (!pdev->driver || !pdev->driver->sriov_configure) {
-               dev_info(&pdev->dev,
-                        "Driver doesn't support SRIOV configuration via sysfs\n");
+               dev_info(&pdev->dev, "Driver doesn't support SRIOV configuration via sysfs\n");
                return -ENOSYS;
        }
 
-       /* if enabling vf's ... */
-       total = pci_sriov_get_totalvfs(pdev);
-       /* Requested VFs to enable < totalvfs and none enabled already */
-       if ((num_vfs > 0) && (num_vfs <= total)) {
-               if (pdev->sriov->num_VFs == 0) {
-                       num_vfs_enabled =
-                               pdev->driver->sriov_configure(pdev, num_vfs);
-                       if ((num_vfs_enabled >= 0) &&
-                           (num_vfs_enabled != num_vfs)) {
-                               dev_warn(&pdev->dev,
-                                        "Only %d VFs enabled\n",
-                                        num_vfs_enabled);
-                               return count;
-                       } else if (num_vfs_enabled < 0)
-                               /* error code from driver callback */
-                               return num_vfs_enabled;
-               } else if (num_vfs == pdev->sriov->num_VFs) {
-                       dev_warn(&pdev->dev,
-                                "%d VFs already enabled; no enable action taken\n",
-                                num_vfs);
-                       return count;
-               } else {
-                       dev_warn(&pdev->dev,
-                                "%d VFs already enabled. Disable before enabling %d VFs\n",
-                                pdev->sriov->num_VFs, num_vfs);
-                       return -EINVAL;
-               }
+       if (num_vfs == 0) {
+               /* disable VFs */
+               ret = pdev->driver->sriov_configure(pdev, 0);
+               if (ret < 0)
+                       return ret;
+               return count;
        }
 
-       /* disable vfs */
-       if (num_vfs == 0) {
-               if (pdev->sriov->num_VFs != 0) {
-                       ret = pdev->driver->sriov_configure(pdev, 0);
-                       return ret ? ret : count;
-               } else {
-                       dev_warn(&pdev->dev,
-                                "All VFs disabled; no disable action taken\n");
-                       return count;
-               }
+       /* enable VFs */
+       if (pdev->sriov->num_VFs) {
+               dev_warn(&pdev->dev, "%d VFs already enabled. Disable before enabling %d VFs\n",
+                        pdev->sriov->num_VFs, num_vfs);
+               return -EBUSY;
        }
 
-       dev_err(&pdev->dev,
-               "Invalid value for number of VFs to enable: %d\n", num_vfs);
+       ret = pdev->driver->sriov_configure(pdev, num_vfs);
+       if (ret < 0)
+               return ret;
 
-       return -EINVAL;
+       if (ret != num_vfs)
+               dev_warn(&pdev->dev, "%d VFs requested; only %d enabled\n",
+                        num_vfs, ret);
+
+       return count;
 }
 
 static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
index 6c8bc5809787d7e2a4b82c72c590918c20f49665..fde4a32a0295082a95de76b6ea08dc1d59fdc2a9 100644 (file)
@@ -82,4 +82,4 @@ endchoice
 
 config PCIE_PME
        def_bool y
-       depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI
+       depends on PCIEPORTBUS && PM_RUNTIME && ACPI
index 421bbc5fee324b485f409e7a025338bc524eecf5..564d97f94b6cd4d248b7cdad8b3b4e138144ff97 100644 (file)
@@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work)
                        continue;
                }
                do_recovery(pdev, entry.severity);
+               pci_dev_put(pdev);
        }
 }
 #endif
index 3ea51736f18db45be7c40280626eb0d803c157b1..5ab14251839d0f06c395ac0dfc064c166cf3b75a 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "aerdrv.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ras.h>
+
 #define AER_AGENT_RECEIVER             0
 #define AER_AGENT_REQUESTER            1
 #define AER_AGENT_COMPLETER            2
@@ -121,12 +124,11 @@ static const char *aer_agent_string[] = {
        "Transmitter ID"
 };
 
-static void __aer_print_error(const char *prefix,
+static void __aer_print_error(struct pci_dev *dev,
                              struct aer_err_info *info)
 {
        int i, status;
        const char *errmsg = NULL;
-
        status = (info->status & ~info->mask);
 
        for (i = 0; i < 32; i++) {
@@ -141,26 +143,22 @@ static void __aer_print_error(const char *prefix,
                                aer_uncorrectable_error_string[i] : NULL;
 
                if (errmsg)
-                       printk("%s""   [%2d] %-22s%s\n", prefix, i, errmsg,
+                       dev_err(&dev->dev, "   [%2d] %-22s%s\n", i, errmsg,
                                info->first_error == i ? " (First)" : "");
                else
-                       printk("%s""   [%2d] Unknown Error Bit%s\n", prefix, i,
-                               info->first_error == i ? " (First)" : "");
+                       dev_err(&dev->dev, "   [%2d] Unknown Error Bit%s\n",
+                               i, info->first_error == i ? " (First)" : "");
        }
 }
 
 void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 {
        int id = ((dev->bus->number << 8) | dev->devfn);
-       char prefix[44];
-
-       snprintf(prefix, sizeof(prefix), "%s%s %s: ",
-                (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR,
-                dev_driver_string(&dev->dev), dev_name(&dev->dev));
 
        if (info->status == 0) {
-               printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, "
-                       "id=%04x(Unregistered Agent ID)\n", prefix,
+               dev_err(&dev->dev,
+                       "PCIe Bus Error: severity=%s, type=Unaccessible, "
+                       "id=%04x(Unregistered Agent ID)\n",
                        aer_error_severity_string[info->severity], id);
        } else {
                int layer, agent;
@@ -168,22 +166,24 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
                layer = AER_GET_LAYER_ERROR(info->severity, info->status);
                agent = AER_GET_AGENT(info->severity, info->status);
 
-               printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
-                       prefix, aer_error_severity_string[info->severity],
+               dev_err(&dev->dev,
+                       "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+                       aer_error_severity_string[info->severity],
                        aer_error_layer[layer], id, aer_agent_string[agent]);
 
-               printk("%s""  device [%04x:%04x] error status/mask=%08x/%08x\n",
-                       prefix, dev->vendor, dev->device,
+               dev_err(&dev->dev,
+                       "  device [%04x:%04x] error status/mask=%08x/%08x\n",
+                       dev->vendor, dev->device,
                        info->status, info->mask);
 
-               __aer_print_error(prefix, info);
+               __aer_print_error(dev, info);
 
                if (info->tlp_header_valid) {
                        unsigned char *tlp = (unsigned char *) &info->tlp;
-                       printk("%s""  TLP Header:"
+                       dev_err(&dev->dev, "  TLP Header:"
                                " %02x%02x%02x%02x %02x%02x%02x%02x"
                                " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-                               prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+                               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
                                *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
                                *(tlp + 11), *(tlp + 10), *(tlp + 9),
                                *(tlp + 8), *(tlp + 15), *(tlp + 14),
@@ -192,8 +192,11 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
        }
 
        if (info->id && info->error_dev_num > 1 && info->id == id)
-               printk("%s""  Error of this Agent(%04x) is reported first\n",
-                       prefix, id);
+               dev_err(&dev->dev,
+                          "  Error of this Agent(%04x) is reported first\n",
+                       id);
+       trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
+                       info->severity);
 }
 
 void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
@@ -217,7 +220,7 @@ int cper_severity_to_aer(int cper_severity)
 }
 EXPORT_SYMBOL_GPL(cper_severity_to_aer);
 
-void cper_print_aer(const char *prefix, int cper_severity,
+void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity,
                    struct aer_capability_regs *aer)
 {
        int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
@@ -239,25 +242,27 @@ void cper_print_aer(const char *prefix, int cper_severity,
        }
        layer = AER_GET_LAYER_ERROR(aer_severity, status);
        agent = AER_GET_AGENT(aer_severity, status);
-       printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n",
-              prefix, status, mask);
+       dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",
+              status, mask);
        cper_print_bits(prefix, status, status_strs, status_strs_size);
-       printk("%s""aer_layer=%s, aer_agent=%s\n", prefix,
+       dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
               aer_error_layer[layer], aer_agent_string[agent]);
        if (aer_severity != AER_CORRECTABLE)
-               printk("%s""aer_uncor_severity: 0x%08x\n",
-                      prefix, aer->uncor_severity);
+               dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n",
+                      aer->uncor_severity);
        if (tlp_header_valid) {
                const unsigned char *tlp;
                tlp = (const unsigned char *)&aer->header_log;
-               printk("%s""aer_tlp_header:"
+               dev_err(&dev->dev, "aer_tlp_header:"
                        " %02x%02x%02x%02x %02x%02x%02x%02x"
                        " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-                       prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+                       *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
                        *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
                        *(tlp + 11), *(tlp + 10), *(tlp + 9),
                        *(tlp + 8), *(tlp + 15), *(tlp + 14),
                        *(tlp + 13), *(tlp + 12));
        }
+       trace_aer_event(dev_name(&dev->dev), (status & ~mask),
+                       aer_severity);
 }
 #endif
index b52630b8eada26ad35f8304e436c63f3e064edd3..8474b6a4fc9bb714e7ab85cf539353fd151b8125 100644 (file)
@@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus)
 {
        struct pci_dev *child;
 
+       if (aspm_force)
+               return;
+
        /*
         * Clear any ASPM setup that the firmware has carried out on this bus
         */
index d4824cb78b499c950c6f3f27aace03ff7a5fa53d..08c243ab034e9bc9172dfd593f4cb0ceabbe2f60 100644 (file)
@@ -134,10 +134,28 @@ static int pcie_port_runtime_resume(struct device *dev)
        return 0;
 }
 
+static int pci_dev_pme_poll(struct pci_dev *pdev, void *data)
+{
+       bool *pme_poll = data;
+
+       if (pdev->pme_poll)
+               *pme_poll = true;
+       return 0;
+}
+
 static int pcie_port_runtime_idle(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       bool pme_poll = false;
+
+       /*
+        * If any subordinate device needs pme poll, we should keep
+        * the port in D0, because we need port in D0 to poll it.
+        */
+       pci_walk_bus(pdev->subordinate, pci_dev_pme_poll, &pme_poll);
        /* Delay for a short while to prevent too frequent suspend/resume */
-       pm_schedule_suspend(dev, 10);
+       if (!pme_poll)
+               pm_schedule_suspend(dev, 10);
        return -EBUSY;
 }
 #else
index 8f7a6344e79e4ca31f7db08ac63a2d4f168649e1..0369fb6fc1da412d2f55d8346d2dca0a9424b158 100644 (file)
@@ -2725,7 +2725,7 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
        if (PCI_FUNC(dev->devfn))
                return;
        /*
-        * RICOH 0xe823 SD/MMC card reader fails to recognize
+        * RICOH 0xe822 and 0xe823 SD/MMC card readers fail to recognize
         * certain types of SD/MMC cards. Lowering the SD base
         * clock frequency from 200Mhz to 50Mhz fixes this issue.
         *
@@ -2736,7 +2736,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
         * 0xf9  - Key register for 0x150
         * 0xfc  - key register for 0xe1
         */
-       if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
+       if (dev->device == PCI_DEVICE_ID_RICOH_R5CE822 ||
+           dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
                pci_write_config_byte(dev, 0xf9, 0xfc);
                pci_write_config_byte(dev, 0x150, 0x10);
                pci_write_config_byte(dev, 0xf9, 0x00);
@@ -2763,6 +2764,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
index 7c0fd9252e6f03c1b1f17f53282be0c5a1fdb57d..84954a726a94d058ecf2e95100dcb01800cc434b 100644 (file)
@@ -19,6 +19,8 @@ static void pci_free_resources(struct pci_dev *dev)
 
 static void pci_stop_dev(struct pci_dev *dev)
 {
+       pci_pme_active(dev, false);
+
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
index c31aeb01bb0002cc648b603c6c526ad83f9ab9a9..a5f3c8ca480e1f078d43f0884f1d4a299fccd660 100644 (file)
@@ -181,12 +181,11 @@ config PINCTRL_COH901
 
 config PINCTRL_SAMSUNG
        bool
-       depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
 
-config PINCTRL_EXYNOS4
-       bool "Pinctrl driver data for Exynos4 SoC"
+config PINCTRL_EXYNOS
+       bool "Pinctrl driver data for Samsung EXYNOS SoCs"
        depends on OF && GPIOLIB
        select PINCTRL_SAMSUNG
 
index fc4606f27dc793897aac033797f2e680e80f3dad..6e87e52eab5d4a2676e2baec9fee1c6c85b5962e 100644 (file)
@@ -36,7 +36,7 @@ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
 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_EXYNOS  += pinctrl-exynos.o
 obj-$(CONFIG_PINCTRL_EXYNOS5440)       += pinctrl-exynos5440.o
 obj-$(CONFIG_PINCTRL_XWAY)     += pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)   += pinctrl-lantiq.o
index 5cdee8669ea35a8221e17c364e50df0d4c90c781..59f5a965bdc40ad47e566bc1969f236ba06d8689 100644 (file)
@@ -700,7 +700,7 @@ static struct pinctrl *create_pinctrl(struct device *dev)
                }
        }
 
-       /* Add the pinmux to the global list */
+       /* Add the pinctrl handle to the global list */
        list_add_tail(&p->node, &pinctrl_list);
 
        return p;
index c907647de6addcb79b00c6cb20679bcd2d686df5..48e21a2294830f4ad3379ae3f6973bb944e82962 100644 (file)
@@ -367,7 +367,7 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
 
-static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id armada_370_pinctrl_of_match[] = {
        { .compatible = "marvell,mv88f6710-pinctrl" },
        { },
 };
@@ -382,7 +382,7 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
        MPP_GPIO_RANGE(2,  64, 64,  2),
 };
 
-static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
+static int armada_370_pinctrl_probe(struct platform_device *pdev)
 {
        struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
 
@@ -399,7 +399,7 @@ static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
        return mvebu_pinctrl_probe(pdev);
 }
 
-static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev)
+static int armada_370_pinctrl_remove(struct platform_device *pdev)
 {
        return mvebu_pinctrl_remove(pdev);
 }
@@ -411,7 +411,7 @@ static struct platform_driver armada_370_pinctrl_driver = {
                .of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
        },
        .probe = armada_370_pinctrl_probe,
-       .remove = __devexit_p(armada_370_pinctrl_remove),
+       .remove = armada_370_pinctrl_remove,
 };
 
 module_platform_driver(armada_370_pinctrl_driver);
index 40bd52a46b4edc4e4b74a51100c432781ca9ff3a..ab5dc04b3e8a1fc961a1766461f06c67e002cb2f 100644 (file)
@@ -349,7 +349,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
 
-static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id armada_xp_pinctrl_of_match[] = {
        {
                .compatible = "marvell,mv78230-pinctrl",
                .data       = (void *) V_MV78230,
@@ -394,7 +394,7 @@ static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
        MPP_GPIO_RANGE(2,  64, 64,  3),
 };
 
-static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
+static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 {
        struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
        const struct of_device_id *match =
@@ -446,7 +446,7 @@ static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
        return mvebu_pinctrl_probe(pdev);
 }
 
-static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev)
+static int armada_xp_pinctrl_remove(struct platform_device *pdev)
 {
        return mvebu_pinctrl_remove(pdev);
 }
@@ -458,7 +458,7 @@ static struct platform_driver armada_xp_pinctrl_driver = {
                .of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
        },
        .probe = armada_xp_pinctrl_probe,
-       .remove = __devexit_p(armada_xp_pinctrl_remove),
+       .remove = armada_xp_pinctrl_remove,
 };
 
 module_platform_driver(armada_xp_pinctrl_driver);
index 40c9c3eecd94560e4cc816dc1d1a2461d36616ef..428ea96a94d356a3caee8b971a1df51d8c9564c3 100644 (file)
@@ -579,29 +579,32 @@ static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
 
 static struct clk *clk;
 
-static struct of_device_id dove_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id dove_pinctrl_of_match[] = {
        { .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
        { }
 };
 
-static int __devinit dove_pinctrl_probe(struct platform_device *pdev)
+static int dove_pinctrl_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match =
                of_match_device(dove_pinctrl_of_match, &pdev->dev);
-       pdev->dev.platform_data = match->data;
+       pdev->dev.platform_data = (void *)match->data;
 
        /*
         * General MPP Configuration Register is part of pdma registers.
         * grab clk to make sure it is ticking.
         */
        clk = devm_clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(clk))
-               clk_prepare_enable(clk);
+       if (IS_ERR(clk)) {
+               dev_err(&pdev->dev, "Unable to get pdma clock");
+               return PTR_RET(clk);
+       }
+       clk_prepare_enable(clk);
 
        return mvebu_pinctrl_probe(pdev);
 }
 
-static int __devexit dove_pinctrl_remove(struct platform_device *pdev)
+static int dove_pinctrl_remove(struct platform_device *pdev)
 {
        int ret;
 
@@ -618,7 +621,7 @@ static struct platform_driver dove_pinctrl_driver = {
                .of_match_table = of_match_ptr(dove_pinctrl_of_match),
        },
        .probe = dove_pinctrl_probe,
-       .remove = __devexit_p(dove_pinctrl_remove),
+       .remove = dove_pinctrl_remove,
 };
 
 module_platform_driver(dove_pinctrl_driver);
index fa6ce31c94d9c3f74eab91de2b16db361370c283..cdd483df673eaf5d38d522ba3e8f5ef26f835c3c 100644 (file)
@@ -66,9 +66,9 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
                MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
                MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1, 0))),
        MPP_MODE(6,
-               MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1, 1)),
-               MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1, 1)),
-               MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
+               MPP_VAR_FUNCTION(0x1, "sysrst", "out",   V(1, 1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
        MPP_MODE(7,
                MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
                MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0, 1)),
@@ -444,7 +444,7 @@ static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
        .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
 };
 
-static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id kirkwood_pinctrl_of_match[] = {
        { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
        { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
        { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
@@ -454,15 +454,15 @@ static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
        { }
 };
 
-static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+static int kirkwood_pinctrl_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match =
                of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
-       pdev->dev.platform_data = match->data;
+       pdev->dev.platform_data = (void *)match->data;
        return mvebu_pinctrl_probe(pdev);
 }
 
-static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+static int kirkwood_pinctrl_remove(struct platform_device *pdev)
 {
        return mvebu_pinctrl_remove(pdev);
 }
@@ -474,7 +474,7 @@ static struct platform_driver kirkwood_pinctrl_driver = {
                .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
        },
        .probe = kirkwood_pinctrl_probe,
-       .remove = __devexit_p(kirkwood_pinctrl_remove),
+       .remove = kirkwood_pinctrl_remove,
 };
 
 module_platform_driver(kirkwood_pinctrl_driver);
index 6c44b7e8964c48678d806f59a784da5c025ac993..c689c04a4f523248e9b2712e77d7e041f5b074d7 100644 (file)
@@ -478,8 +478,7 @@ static struct pinctrl_ops mvebu_pinctrl_ops = {
        .dt_free_map = mvebu_pinctrl_dt_free_map,
 };
 
-static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
-                                  const char *name)
+static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
 {
        while (funcs->num_groups) {
                /* function already there */
@@ -494,8 +493,8 @@ static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
        return 0;
 }
 
-static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
-                                                  struct mvebu_pinctrl *pctl)
+static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
+                                        struct mvebu_pinctrl *pctl)
 {
        struct mvebu_pinctrl_function *funcs;
        int num = 0;
@@ -568,7 +567,7 @@ static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
        return 0;
 }
 
-int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
+int mvebu_pinctrl_probe(struct platform_device *pdev)
 {
        struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
        struct device_node *np = pdev->dev.of_node;
@@ -745,7 +744,7 @@ int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
        return 0;
 }
 
-int __devexit mvebu_pinctrl_remove(struct platform_device *pdev)
+int mvebu_pinctrl_remove(struct platform_device *pdev)
 {
        struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
        pinctrl_unregister(pctl->pctldev);
index c5e757157183de6ae7e084c46d82baec8fd7db4b..471c71f7f8b611fb87e0d2330627801b5124288d 100644 (file)
@@ -265,7 +265,7 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
        /* create mux map */
        parent = of_get_parent(np);
        if (!parent) {
-               kfree(new_map);
+               devm_kfree(pctldev->dev, new_map);
                return -EINVAL;
        }
        new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
@@ -792,8 +792,8 @@ static struct pinctrl_desc at91_pinctrl_desc = {
 
 static const char *gpio_compat = "atmel,at91rm9200-gpio";
 
-static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
-                                             struct device_node *np)
+static void at91_pinctrl_child_count(struct at91_pinctrl *info,
+                                    struct device_node *np)
 {
        struct device_node *child;
 
@@ -807,8 +807,8 @@ static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
        }
 }
 
-static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
-                                         struct device_node *np)
+static int at91_pinctrl_mux_mask(struct at91_pinctrl *info,
+                                struct device_node *np)
 {
        int ret = 0;
        int size;
@@ -840,10 +840,9 @@ static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
        return ret;
 }
 
-static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
-                               struct at91_pin_group *grp,
-                               struct at91_pinctrl *info,
-                               u32 index)
+static int 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;
@@ -889,8 +888,8 @@ static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
        return 0;
 }
 
-static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
-                       struct at91_pinctrl *info, u32 index)
+static int at91_pinctrl_parse_functions(struct device_node *np,
+                                       struct at91_pinctrl *info, u32 index)
 {
        struct device_node *child;
        struct at91_pmx_func *func;
@@ -926,14 +925,14 @@ static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
        return 0;
 }
 
-static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id at91_pinctrl_of_match[] = {
        { .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)
+static int at91_pinctrl_probe_dt(struct platform_device *pdev,
+                                struct at91_pinctrl *info)
 {
        int ret = 0;
        int i, j;
@@ -999,7 +998,7 @@ static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit at91_pinctrl_probe(struct platform_device *pdev)
+static int at91_pinctrl_probe(struct platform_device *pdev)
 {
        struct at91_pinctrl *info;
        struct pinctrl_pin_desc *pdesc;
@@ -1063,7 +1062,7 @@ err:
        return ret;
 }
 
-static int __devexit at91_pinctrl_remove(struct platform_device *pdev)
+static int at91_pinctrl_remove(struct platform_device *pdev)
 {
        struct at91_pinctrl *info = platform_get_drvdata(pdev);
 
@@ -1443,7 +1442,7 @@ static struct gpio_chip at91_gpio_template = {
        .ngpio                  = MAX_NB_GPIO_PER_BANK,
 };
 
-static void __devinit at91_gpio_probe_fixup(void)
+static void at91_gpio_probe_fixup(void)
 {
        unsigned i;
        struct at91_gpio_chip *at91_gpio, *last = NULL;
@@ -1461,13 +1460,13 @@ static void __devinit at91_gpio_probe_fixup(void)
        }
 }
 
-static struct of_device_id at91_gpio_of_match[] __devinitdata = {
+static struct of_device_id at91_gpio_of_match[] = {
        { .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)
+static int at91_gpio_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct resource *res;
@@ -1609,7 +1608,7 @@ static struct platform_driver at91_pinctrl_driver = {
                .of_match_table = of_match_ptr(at91_pinctrl_of_match),
        },
        .probe = at91_pinctrl_probe,
-       .remove = __devexit_p(at91_pinctrl_remove),
+       .remove = at91_pinctrl_remove,
 };
 
 static int __init at91_pinctrl_init(void)
index 0b0e9b49a1b5c168d745f54ec901d7a5e2ae657e..d347b9f2eae305f810b4232cd16f274ac4231ada 100644 (file)
@@ -936,7 +936,7 @@ static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
        .npins = BCM2835_NUM_GPIOS,
 };
 
-static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
+static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
index b8635f634e91c1497f0158421371d521a233e190..142729914c347fc305e32449c11f637a44ad654f 100644 (file)
@@ -117,7 +117,7 @@ struct exynos5440_pinctrl_priv_data {
 };
 
 /* list of all possible config options supported */
-struct pin_config {
+static struct pin_config {
        char            *prop_cfg;
        unsigned int    cfg_type;
 } pcfgs[] = {
@@ -599,7 +599,7 @@ static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offse
 }
 
 /* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
-static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
+static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
                        struct device_node *cfg_np, unsigned int **pin_list,
                        unsigned int *npins)
 {
@@ -630,7 +630,7 @@ static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
  * Parse the information about all the available pin groups and pin functions
  * from device node of the pin-controller.
  */
-static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
+static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
                                struct exynos5440_pinctrl_priv_data *priv)
 {
        struct device *dev = &pdev->dev;
@@ -723,7 +723,7 @@ static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
 }
 
 /* register the pinctrl interface with the pinctrl subsystem */
-static int __init exynos5440_pinctrl_register(struct platform_device *pdev,
+static int exynos5440_pinctrl_register(struct platform_device *pdev,
                                struct exynos5440_pinctrl_priv_data *priv)
 {
        struct device *dev = &pdev->dev;
@@ -798,7 +798,7 @@ static int __init exynos5440_pinctrl_register(struct platform_device *pdev,
 }
 
 /* register the gpiolib interface with the gpiolib subsystem */
-static int __init exynos5440_gpiolib_register(struct platform_device *pdev,
+static int exynos5440_gpiolib_register(struct platform_device *pdev,
                                struct exynos5440_pinctrl_priv_data *priv)
 {
        struct gpio_chip *gc;
@@ -831,7 +831,7 @@ static int __init exynos5440_gpiolib_register(struct platform_device *pdev,
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
-static int __init exynos5440_gpiolib_unregister(struct platform_device *pdev,
+static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
                                struct exynos5440_pinctrl_priv_data *priv)
 {
        int ret = gpiochip_remove(priv->gc);
@@ -842,7 +842,7 @@ static int __init exynos5440_gpiolib_unregister(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit exynos5440_pinctrl_probe(struct platform_device *pdev)
+static int exynos5440_pinctrl_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos5440_pinctrl_priv_data *priv;
index 131d86d7c2a5ec0229f8c3d34acfffdbaaaf44f1..43a6f1ffc786eee9c01580b60dd986739a8d4d57 100644 (file)
@@ -425,10 +425,10 @@ static int imx_pinctrl_get_pin_id_and_mux(const struct imx_pinctrl_soc_info *inf
        return 0;
 }
 
-static int __devinit imx_pinctrl_parse_groups(struct device_node *np,
-                               struct imx_pin_group *grp,
-                               struct imx_pinctrl_soc_info *info,
-                               u32 index)
+static int imx_pinctrl_parse_groups(struct device_node *np,
+                                   struct imx_pin_group *grp,
+                                   struct imx_pinctrl_soc_info *info,
+                                   u32 index)
 {
        unsigned int pin_func_id;
        int ret, size;
@@ -482,8 +482,9 @@ static int __devinit imx_pinctrl_parse_groups(struct device_node *np,
        return 0;
 }
 
-static int __devinit imx_pinctrl_parse_functions(struct device_node *np,
-                       struct imx_pinctrl_soc_info *info, u32 index)
+static int imx_pinctrl_parse_functions(struct device_node *np,
+                                      struct imx_pinctrl_soc_info *info,
+                                      u32 index)
 {
        struct device_node *child;
        struct imx_pmx_func *func;
@@ -517,7 +518,7 @@ static int __devinit imx_pinctrl_parse_functions(struct device_node *np,
        return 0;
 }
 
-static int __devinit imx_pinctrl_probe_dt(struct platform_device *pdev,
+static int imx_pinctrl_probe_dt(struct platform_device *pdev,
                                struct imx_pinctrl_soc_info *info)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -560,8 +561,8 @@ static int __devinit imx_pinctrl_probe_dt(struct platform_device *pdev,
        return 0;
 }
 
-int __devinit imx_pinctrl_probe(struct platform_device *pdev,
-                               struct imx_pinctrl_soc_info *info)
+int imx_pinctrl_probe(struct platform_device *pdev,
+                     struct imx_pinctrl_soc_info *info)
 {
        struct imx_pinctrl *ipctl;
        struct resource *res;
index 04364f7822b78a6c9589808f733bb10c2e0f0691..e76d75c9d1ba5635dbbddf70fc6c53a0c9898afa 100644 (file)
@@ -267,7 +267,7 @@ static struct mxs_pinctrl_soc_data imx23_pinctrl_data = {
        .npins = ARRAY_SIZE(imx23_pins),
 };
 
-static int __devinit imx23_pinctrl_probe(struct platform_device *pdev)
+static int imx23_pinctrl_probe(struct platform_device *pdev)
 {
        return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data);
 }
index e1af2ba89004700e3ef27b3d24d72a9d673df542..79c9c8d296af8b1e67e5c05c2e7963b4307c8c24 100644 (file)
@@ -383,7 +383,7 @@ static struct mxs_pinctrl_soc_data imx28_pinctrl_data = {
        .npins = ARRAY_SIZE(imx28_pins),
 };
 
-static int __devinit imx28_pinctrl_probe(struct platform_device *pdev)
+static int imx28_pinctrl_probe(struct platform_device *pdev)
 {
        return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data);
 }
index 1dbf5278acecf9d8979f1e425b5aa1470c262ab9..6e214110e3d5253833c57f0be8489e464a85f8cb 100644 (file)
@@ -1564,7 +1564,7 @@ static struct of_device_id imx35_pinctrl_of_match[] = {
        { /* sentinel */ }
 };
 
-static int __devinit imx35_pinctrl_probe(struct platform_device *pdev)
+static int imx35_pinctrl_probe(struct platform_device *pdev)
 {
        return imx_pinctrl_probe(pdev, &imx35_pinctrl_info);
 }
index 131216558a7b32b4d871b8aa4d5cfc83e98d86d4..9a92aaad150fd2db544a9053c182d75bc4ced7f0 100644 (file)
@@ -1291,7 +1291,7 @@ static struct of_device_id imx51_pinctrl_of_match[] = {
        { /* sentinel */ }
 };
 
-static int __devinit imx51_pinctrl_probe(struct platform_device *pdev)
+static int imx51_pinctrl_probe(struct platform_device *pdev)
 {
        return imx_pinctrl_probe(pdev, &imx51_pinctrl_info);
 }
index ec404869177573e86ce8be7798526ef724d8c284..2c9c8e2334da2524f9d9127375cbc7456cda6aae 100644 (file)
@@ -1371,7 +1371,7 @@ static struct imx_pin_reg imx53_pin_regs[] = {
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 0, 0x7F8, 1), /* MX53_PAD_GPIO_8__ESAI1_TX5_RX0 */
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 1, 0x000, 0), /* MX53_PAD_GPIO_8__GPIO1_8 */
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 2, 0x000, 0), /* MX53_PAD_GPIO_8__EPIT2_EPITO */
-       IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 3, 0x760, 3), /* MX53_PAD_GPIO_8__CAN1_RXCAN */
+       IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 3, 0x760, 2), /* MX53_PAD_GPIO_8__CAN1_RXCAN */
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 4, 0x880, 5), /* MX53_PAD_GPIO_8__UART2_RXD_MUX */
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 5, 0x000, 0), /* MX53_PAD_GPIO_8__FIRI_TXD */
        IMX_PIN_REG(MX53_PAD_GPIO_8, 0x6C8, 0x338, 6, 0x000, 0), /* MX53_PAD_GPIO_8__SPDIF_SRCLK */
@@ -1618,7 +1618,7 @@ static struct of_device_id imx53_pinctrl_of_match[] = {
        { /* sentinel */ }
 };
 
-static int __devinit imx53_pinctrl_probe(struct platform_device *pdev)
+static int imx53_pinctrl_probe(struct platform_device *pdev)
 {
        return imx_pinctrl_probe(pdev, &imx53_pinctrl_info);
 }
index 844ab13c93a3254c5048e2aa60ec0f3cc0c0af06..663346bb765e756bd96189dfd189bb5e2f620d09 100644 (file)
@@ -2302,7 +2302,7 @@ static struct of_device_id imx6q_pinctrl_of_match[] = {
        { /* sentinel */ }
 };
 
-static int __devinit imx6q_pinctrl_probe(struct platform_device *pdev)
+static int imx6q_pinctrl_probe(struct platform_device *pdev)
 {
        return imx_pinctrl_probe(pdev, &imx6q_pinctrl_info);
 }
index 4fbb3db3f1c1688b146e2a91e657926a426c1e37..4afa56a3a51dd140965e68d88a0161d70c1de378 100644 (file)
@@ -686,7 +686,7 @@ static struct pxa3xx_pinmux_info mmp2_info = {
        .ds_shift       = MMP2_DS_SHIFT,
 };
 
-static int __devinit mmp2_pinmux_probe(struct platform_device *pdev)
+static int mmp2_pinmux_probe(struct platform_device *pdev)
 {
        return pxa3xx_pinctrl_register(pdev, &mmp2_info);
 }
index 180f16379ec1430af6a3a431ea8588d21290a881..23af9f1f9c35e6d9d7793075ad7ec2df92070043 100644 (file)
@@ -146,7 +146,7 @@ free:
 static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
                            struct pinctrl_map *map, unsigned num_maps)
 {
-       int i;
+       u32 i;
 
        for (i = 0; i < num_maps; i++) {
                if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
@@ -203,7 +203,7 @@ static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector,
        void __iomem *reg;
        u8 bank, shift;
        u16 pin;
-       int i;
+       u32 i;
 
        for (i = 0; i < g->npins; i++) {
                bank = PINID_TO_BANK(g->pins[i]);
@@ -256,7 +256,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
        void __iomem *reg;
        u8 ma, vol, pull, bank, shift;
        u16 pin;
-       int i;
+       u32 i;
 
        ma = CONFIG_TO_MA(config);
        vol = CONFIG_TO_VOL(config);
@@ -335,9 +335,9 @@ static struct pinctrl_desc mxs_pinctrl_desc = {
        .owner = THIS_MODULE,
 };
 
-static int __devinit mxs_pinctrl_parse_group(struct platform_device *pdev,
-                                            struct device_node *np, int idx,
-                                            const char **out_name)
+static int mxs_pinctrl_parse_group(struct platform_device *pdev,
+                                  struct device_node *np, int idx,
+                                  const char **out_name)
 {
        struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
        struct mxs_group *g = &d->soc->groups[idx];
@@ -345,8 +345,7 @@ static int __devinit mxs_pinctrl_parse_group(struct platform_device *pdev,
        const char *propname = "fsl,pinmux-ids";
        char *group;
        int length = strlen(np->name) + SUFFIX_LEN;
-       int i;
-       u32 val;
+       u32 val, i;
 
        group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
        if (!group)
@@ -384,8 +383,8 @@ static int __devinit mxs_pinctrl_parse_group(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit mxs_pinctrl_probe_dt(struct platform_device *pdev,
-                                         struct mxs_pinctrl_data *d)
+static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
+                               struct mxs_pinctrl_data *d)
 {
        struct mxs_pinctrl_soc_data *soc = d->soc;
        struct device_node *np = pdev->dev.of_node;
@@ -476,8 +475,8 @@ static int __devinit mxs_pinctrl_probe_dt(struct platform_device *pdev,
        return 0;
 }
 
-int __devinit mxs_pinctrl_probe(struct platform_device *pdev,
-                               struct mxs_pinctrl_soc_data *soc)
+int mxs_pinctrl_probe(struct platform_device *pdev,
+                     struct mxs_pinctrl_soc_data *soc)
 {
        struct device_node *np = pdev->dev.of_node;
        struct mxs_pinctrl_data *d;
index 7d88ae35211976f2db4372aa6d377822651524d4..30b4da91ef7ee8d4679513efe39ce6bd7e572700 100644 (file)
@@ -1251,8 +1251,7 @@ static const struct nmk_pinctrl_soc_data nmk_db8500_soc = {
        .prcm_gpiocr_registers = db8500_prcm_gpiocr_regs,
 };
 
-void __devinit
-nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
+void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
 {
        *soc = &nmk_db8500_soc;
 }
index bb6a4016322aa7daa1ee7063127557cb5eb52a1d..d7ba5443bae05593fe71dc5f54e2b9dbc9369c0a 100644 (file)
@@ -1260,8 +1260,7 @@ static const struct nmk_pinctrl_soc_data nmk_db8540_soc = {
        .prcm_gpiocr_registers = db8540_prcm_gpiocr_regs,
 };
 
-void __devinit
-nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
+void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
 {
        *soc = &nmk_db8540_soc;
 }
index 7d432c3bc3590f2f85f803584a6f0d93d4496eb3..924a3393fa82b4dce3799e62bebbc9748b98fdde 100644 (file)
@@ -350,8 +350,7 @@ static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = {
        .ngroups = ARRAY_SIZE(nmk_stn8815_groups),
 };
 
-void __devinit
-nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
+void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
 {
        *soc = &nmk_stn8815_soc;
 }
index ef66f98e9202c28b2b13ede8fac9bd5d7d3e55bc..5767b18ebdff6d1639bd37c6007f9c93553a3f58 100644 (file)
@@ -259,6 +259,9 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
        const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
        const u16 *gpiocr_regs;
 
+       if (!npct->prcm_base)
+               return;
+
        if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) {
                dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n",
                        alt_num);
@@ -673,7 +676,7 @@ 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)
+static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
 {
        int i;
        u16 reg;
@@ -682,6 +685,9 @@ static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
        const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
        const u16 *gpiocr_regs;
 
+       if (!npct->prcm_base)
+               return NMK_GPIO_ALT_C;
+
        for (i = 0; i < npct->soc->npins_altcx; i++) {
                if (npct->soc->altcx_pins[i].pin == gpio)
                        break;
@@ -1306,7 +1312,7 @@ const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
        .xlate = irq_domain_xlate_twocell,
 };
 
-static int __devinit nmk_gpio_probe(struct platform_device *dev)
+static int nmk_gpio_probe(struct platform_device *dev)
 {
        struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
        struct device_node *np = dev->dev.of_node;
@@ -1846,7 +1852,7 @@ static const struct of_device_id nmk_pinctrl_match[] = {
        {},
 };
 
-static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
+static int 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;
@@ -1887,9 +1893,12 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
                                "failed to ioremap PRCM registers\n");
                        return -ENOMEM;
                }
-       } else {
+       } else if (version == PINCTRL_NMK_STN8815) {
                dev_info(&pdev->dev,
                         "No PRCM base, assume no ALT-Cx control is available\n");
+       } else {
+               dev_err(&pdev->dev, "missing PRCM base address\n");
+               return -EINVAL;
        }
 
        /*
index cb771e4a63550cca944104d81179829d68c47f50..d9cd2b457484d53159b09c88c669663211e627e1 100644 (file)
@@ -615,7 +615,7 @@ static struct pxa3xx_pinmux_info pxa168_info = {
        .ds_shift       = PXA168_DS_SHIFT,
 };
 
-static int __devinit pxa168_pinmux_probe(struct platform_device *pdev)
+static int pxa168_pinmux_probe(struct platform_device *pdev)
 {
        return pxa3xx_pinctrl_register(pdev, &pxa168_info);
 }
index 5fecd221b830ae21841ba9dd162248e2cf36aa7c..a2f917b847fba7d1d84e746ffff2d5fc19906515 100644 (file)
@@ -971,7 +971,7 @@ static struct pxa3xx_pinmux_info pxa910_info = {
        .ds_shift       = PXA910_DS_SHIFT,
 };
 
-static int __devinit pxa910_pinmux_probe(struct platform_device *pdev)
+static int pxa910_pinmux_probe(struct platform_device *pdev)
 {
        return pxa3xx_pinctrl_register(pdev, &pxa910_info);
 }
index 8f31b656c4e95be33ad04d7256f9594286f37a56..fd7b24cd89084d923dd2cc1cc2a581695a040deb 100644 (file)
@@ -37,7 +37,7 @@
 #define FSUFFIX_LEN            sizeof(FUNCTION_SUFFIX)
 
 /* list of all possible config options supported */
-struct pin_config {
+static struct pin_config {
        char            *prop_cfg;
        unsigned int    cfg_type;
 } pcfgs[] = {
@@ -549,9 +549,11 @@ static int samsung_gpio_to_irq(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 __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)
+static int 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)
 {
        struct device *dev = &pdev->dev;
        struct property *prop;
@@ -596,8 +598,8 @@ static int __devinit 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 __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
-                               struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
+                                   struct samsung_pinctrl_drv_data *drvdata)
 {
        struct device *dev = &pdev->dev;
        struct device_node *dev_np = dev->of_node;
@@ -691,8 +693,8 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
 }
 
 /* register the pinctrl interface with the pinctrl subsystem */
-static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
-                               struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_pinctrl_register(struct platform_device *pdev,
+                                   struct samsung_pinctrl_drv_data *drvdata)
 {
        struct pinctrl_desc *ctrldesc = &drvdata->pctl;
        struct pinctrl_pin_desc *pindesc, *pdesc;
@@ -778,8 +780,8 @@ static const struct gpio_chip samsung_gpiolib_chip = {
 };
 
 /* register the gpiolib interface with the gpiolib subsystem */
-static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
-                               struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_gpiolib_register(struct platform_device *pdev,
+                                   struct samsung_pinctrl_drv_data *drvdata)
 {
        struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
        struct samsung_pin_bank *bank = ctrl->pin_banks;
@@ -816,8 +818,8 @@ fail:
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
-static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
-                               struct samsung_pinctrl_drv_data *drvdata)
+static int samsung_gpiolib_unregister(struct platform_device *pdev,
+                                     struct samsung_pinctrl_drv_data *drvdata)
 {
        struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
        struct samsung_pin_bank *bank = ctrl->pin_banks;
@@ -881,7 +883,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
        return ctrl;
 }
 
-static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
+static int samsung_pinctrl_probe(struct platform_device *pdev)
 {
        struct samsung_pinctrl_drv_data *drvdata;
        struct device *dev = &pdev->dev;
index 5addfd16e3cc461fe7f967e67d2eea072fc62b1b..e2d4e67f7e882c5314d7bfc82235be586c48a438 100644 (file)
@@ -104,7 +104,7 @@ struct samsung_pinctrl_drv_data;
 
 /**
  * struct samsung_pin_bank: represent a controller pin-bank.
- * @reg_offset: starting offset of the pin-bank registers.
+ * @pctl_offset: starting offset of the pin-bank registers.
  * @pin_base: starting pin number of the bank.
  * @nr_pins: number of pins included in this bank.
  * @func_width: width of the function selector bit field.
index 79642831bba2ecc1524f0b884dde808170ca9e16..5c32e880bcb24315b4b2db260294106765eb4240 100644 (file)
@@ -30,7 +30,6 @@
 #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,16 +76,6 @@ struct pcs_function {
        struct list_head node;
 };
 
-/**
- * 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
@@ -414,26 +403,9 @@ 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 pin)
+                       struct pinctrl_gpio_range *range, unsigned offset)
 {
-       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;
+       return -ENOTSUPP;
 }
 
 static struct pinmux_ops pcs_pinmux_ops = {
@@ -493,7 +465,7 @@ static struct pinconf_ops pcs_pinconf_ops = {
  * @pcs: pcs driver instance
  * @offset: register offset from base
  */
-static int __devinit pcs_add_pin(struct pcs_device *pcs, unsigned offset)
+static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
 {
        struct pinctrl_pin_desc *pin;
        struct pcs_name *pn;
@@ -526,7 +498,7 @@ static int __devinit pcs_add_pin(struct pcs_device *pcs, unsigned offset)
  * If your hardware needs holes in the address space, then just set
  * up multiple driver instances.
  */
-static int __devinit pcs_allocate_pin_table(struct pcs_device *pcs)
+static int pcs_allocate_pin_table(struct pcs_device *pcs)
 {
        int mux_bytes, nr_pins, i;
 
@@ -907,51 +879,7 @@ 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)
+static int pcs_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *match;
@@ -1047,10 +975,6 @@ 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 a4f0c5e487d5eae6c2b1f29c5aebf596df2f40d2..d02498b30c6ef1f4a0eb33a6f3dd23ea46850324 100644 (file)
@@ -1246,7 +1246,23 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
        return of_iomap(np, 0);
 }
 
-static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
+static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
+       const struct of_phandle_args *gpiospec,
+       u32 *flags)
+{
+       if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
+               return -EINVAL;
+
+       if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc)
+               return -EINVAL;
+
+       if (flags)
+               *flags = gpiospec->args[1];
+
+       return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE;
+}
+
+static int sirfsoc_pinmux_probe(struct platform_device *pdev)
 {
        int ret;
        struct sirfsoc_pmx *spmx;
@@ -1663,7 +1679,45 @@ const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {
        .xlate = irq_domain_xlate_twocell,
 };
 
-static int __devinit sirfsoc_gpio_probe(struct device_node *np)
+static void sirfsoc_gpio_set_pullup(const u32 *pullups)
+{
+       int i, n;
+       const unsigned long *p = (const unsigned long *)pullups;
+
+       for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
+               n = find_first_bit(p + i, BITS_PER_LONG);
+               while (n < BITS_PER_LONG) {
+                       u32 offset = SIRFSOC_GPIO_CTRL(i, n);
+                       u32 val = readl(sgpio_bank[i].chip.regs + offset);
+                       val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+                       val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
+                       writel(val, sgpio_bank[i].chip.regs + offset);
+
+                       n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
+               }
+       }
+}
+
+static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
+{
+       int i, n;
+       const unsigned long *p = (const unsigned long *)pulldowns;
+
+       for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
+               n = find_first_bit(p + i, BITS_PER_LONG);
+               while (n < BITS_PER_LONG) {
+                       u32 offset = SIRFSOC_GPIO_CTRL(i, n);
+                       u32 val = readl(sgpio_bank[i].chip.regs + offset);
+                       val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+                       val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
+                       writel(val, sgpio_bank[i].chip.regs + offset);
+
+                       n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
+               }
+       }
+}
+
+static int sirfsoc_gpio_probe(struct device_node *np)
 {
        int i, err = 0;
        struct sirfsoc_gpio_bank *bank;
@@ -1671,6 +1725,8 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
        struct platform_device *pdev;
        bool is_marco = false;
 
+       u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
+
        pdev = of_find_device_by_node(np);
        if (!pdev)
                return -ENODEV;
@@ -1696,6 +1752,8 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
                bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
                bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
                bank->chip.gc.of_node = np;
+               bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
+               bank->chip.gc.of_gpio_n_cells = 2;
                bank->chip.regs = regs;
                bank->id = i;
                bank->is_marco = is_marco;
@@ -1726,6 +1784,14 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
                irq_set_handler_data(bank->parent_irq, bank);
        }
 
+       if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
+               SIRFSOC_GPIO_NO_OF_BANKS))
+               sirfsoc_gpio_set_pullup(pullups);
+
+       if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
+               SIRFSOC_GPIO_NO_OF_BANKS))
+               sirfsoc_gpio_set_pulldown(pulldowns);
+
        return 0;
 
 out:
index e356b0380fa74985d1f2bc311c6cc476d4bfb187..ae1e4bb3259da953b448df78d31df92b79fa8a9b 100644 (file)
@@ -687,7 +687,7 @@ static struct pinctrl_desc tegra_pinctrl_desc = {
        .owner = THIS_MODULE,
 };
 
-int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
+int tegra_pinctrl_probe(struct platform_device *pdev,
                        const struct tegra_pinctrl_soc_data *soc_data)
 {
        struct tegra_pmx *pmx;
index 1524bfd666028d9d638bb09d747f4c065c24f4d9..e848189038f0654dce86ed020075ff3ddddbc107 100644 (file)
@@ -2856,7 +2856,7 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
        .ngroups = ARRAY_SIZE(tegra20_groups),
 };
 
-static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
+static int tegra20_pinctrl_probe(struct platform_device *pdev)
 {
        return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
 }
index cf579ebf346f9c1b6a5ffebefbe576e16f304f4a..9ad87ea735d4b6240c9702e67bede26f78dacce3 100644 (file)
@@ -3722,7 +3722,7 @@ static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
        .ngroups = ARRAY_SIZE(tegra30_groups),
 };
 
-static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
+static int tegra30_pinctrl_probe(struct platform_device *pdev)
 {
        return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
 }
index 8c039ad22baf0eb44e78f2ceca9af5e3747b7644..718ec576268332ec76a5ab30a75e2865e53ed403 100644 (file)
@@ -1062,7 +1062,7 @@ static struct pinctrl_desc u300_pmx_desc = {
        .owner = THIS_MODULE,
 };
 
-static int __devinit u300_pmx_probe(struct platform_device *pdev)
+static int u300_pmx_probe(struct platform_device *pdev)
 {
        struct u300_pmx *upmx;
        struct resource *res;
index ad90984ec5008a7f39f64e6a498102af13cba583..5f0eb04c23364de9ff8a427e4ee4af9e9cd7b155 100644 (file)
@@ -674,7 +674,7 @@ static const struct of_device_id xway_match[] = {
 };
 MODULE_DEVICE_TABLE(of, xway_match);
 
-static int __devinit pinmux_xway_probe(struct platform_device *pdev)
+static int pinmux_xway_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match;
        const struct pinctrl_xway_soc *xway_soc;
index 4c045053bbddd1e8a557861f7a73eb51ec64a97e..3cf4ecd9302cf6279b87928579c9c39ae28d4316 100644 (file)
@@ -451,8 +451,7 @@ int spear310_o2p(int offset)
                return offset + 2;
 }
 
-static int __devinit plgpio_probe_dt(struct platform_device *pdev,
-               struct plgpio *plgpio)
+static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)
 {
        struct device_node *np = pdev->dev.of_node;
        int ret = -EINVAL;
@@ -522,7 +521,7 @@ static int __devinit plgpio_probe_dt(struct platform_device *pdev,
 end:
        return ret;
 }
-static int __devinit plgpio_probe(struct platform_device *pdev)
+static int plgpio_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct plgpio *plgpio;
index 922c057521a16f69abdb95af3c52d0600942d790..6a7dae70db081b04255c588dd45fd07e0fa2458c 100644 (file)
@@ -82,9 +82,8 @@ 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)
+void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+                                unsigned count, u16 reg)
 {
        int i, j;
 
@@ -93,7 +92,7 @@ pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
                        gpio_pingroup[i].muxregs[j].reg = reg;
 }
 
-void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
+void pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
 {
        struct spear_pingroup *pgroup;
        struct spear_modemux *modemux;
@@ -358,8 +357,8 @@ static struct pinctrl_desc spear_pinctrl_desc = {
        .owner = THIS_MODULE,
 };
 
-int __devinit spear_pinctrl_probe(struct platform_device *pdev,
-               struct spear_pinctrl_machdata *machdata)
+int spear_pinctrl_probe(struct platform_device *pdev,
+                       struct spear_pinctrl_machdata *machdata)
 {
        struct device_node *np = pdev->dev.of_node;
        struct resource *res;
index 1be46ecc6d917176857fd2da7f2248dae4c8c657..dc8bf85ecb2aa5ae33f8de6dc6057dfd526fcbbd 100644 (file)
@@ -192,12 +192,11 @@ 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);
+void pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+                                unsigned count, u16 reg);
+int spear_pinctrl_probe(struct platform_device *pdev,
+                       struct spear_pinctrl_machdata *machdata);
 int spear_pinctrl_remove(struct platform_device *pdev);
 
 #define SPEAR_PIN_0_TO_101             \
index e40d785a3fc29229161bbf92a5ae9d044e99ef69..1a8bbfec60ca7748242701c687b22b8d93b43b99 100644 (file)
@@ -2699,7 +2699,7 @@ static struct of_device_id spear1310_pinctrl_of_match[] = {
        {},
 };
 
-static int __devinit spear1310_pinctrl_probe(struct platform_device *pdev)
+static int spear1310_pinctrl_probe(struct platform_device *pdev)
 {
        return spear_pinctrl_probe(pdev, &spear1310_machdata);
 }
index 8deaaff3156ca00cd92a5d3fc950d8919a57894a..873966e2b99f2ebbe64c6a9921fe7a5fa9a497a2 100644 (file)
@@ -2015,7 +2015,7 @@ static struct of_device_id spear1340_pinctrl_of_match[] = {
        {},
 };
 
-static int __devinit spear1340_pinctrl_probe(struct platform_device *pdev)
+static int spear1340_pinctrl_probe(struct platform_device *pdev)
 {
        return spear_pinctrl_probe(pdev, &spear1340_machdata);
 }
index f48e466e605a1494caecd5cd3c4828dbc88503cc..4777c0d0e730928e0f04c6f7e8e48cb240f0244e 100644 (file)
@@ -653,7 +653,7 @@ static struct of_device_id spear300_pinctrl_of_match[] = {
        {},
 };
 
-static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
+static int spear300_pinctrl_probe(struct platform_device *pdev)
 {
        int ret;
 
index 5b954c19a6d2c536026e976b695a991ff6fbff74..06c7e6f1c7f2817cf8d5b446472a37c05d046e80 100644 (file)
@@ -378,7 +378,7 @@ static struct of_device_id spear310_pinctrl_of_match[] = {
        {},
 };
 
-static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
+static int spear310_pinctrl_probe(struct platform_device *pdev)
 {
        int ret;
 
index e9a5e6d39242f0f9ddc2de04240f23b2534eb501..b8e290a8c8c994fe8394ce21b593ab4199d03017 100644 (file)
@@ -3417,7 +3417,7 @@ static struct of_device_id spear320_pinctrl_of_match[] = {
        {},
 };
 
-static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
+static int spear320_pinctrl_probe(struct platform_device *pdev)
 {
        int ret;
 
index 934d861a32359bb553ce17966d152f089b31c04d..afed7018a2b5fe9b006de12716814a2dc00502d0 100644 (file)
@@ -125,8 +125,11 @@ static const struct key_entry acer_wmi_keymap[] = {
        {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
        {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
        {KE_IGNORE, 0x81, {KEY_SLEEP} },
-       {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
+       {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */
+       {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
+       {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
        {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
+       {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
        {KE_END, 0}
 };
 
@@ -147,6 +150,7 @@ struct event_return_value {
 #define ACER_WMID3_GDS_THREEG          (1<<6)  /* 3G */
 #define ACER_WMID3_GDS_WIMAX           (1<<7)  /* WiMAX */
 #define ACER_WMID3_GDS_BLUETOOTH       (1<<11) /* BT */
+#define ACER_WMID3_GDS_TOUCHPAD                (1<<1)  /* Touchpad */
 
 struct lm_input_params {
        u8 function_num;        /* Function Number */
@@ -335,7 +339,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = {
 };
 
 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
-static struct dmi_system_id __devinitdata acer_blacklist[] = {
+static struct dmi_system_id acer_blacklist[] = {
        {
                .ident = "Acer Aspire One (SSD)",
                .matches = {
@@ -875,7 +879,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
        struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
        struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
-       u32 tmp;
+       u32 tmp = 0;
        acpi_status status;
 
        status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result);
@@ -884,14 +888,14 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
                return status;
 
        obj = (union acpi_object *) result.pointer;
-       if (obj && obj->type == ACPI_TYPE_BUFFER &&
-               (obj->buffer.length == sizeof(u32) ||
-               obj->buffer.length == sizeof(u64))) {
-               tmp = *((u32 *) obj->buffer.pointer);
-       } else if (obj->type == ACPI_TYPE_INTEGER) {
-               tmp = (u32) obj->integer.value;
-       } else {
-               tmp = 0;
+       if (obj) {
+               if (obj->type == ACPI_TYPE_BUFFER &&
+                       (obj->buffer.length == sizeof(u32) ||
+                       obj->buffer.length == sizeof(u64))) {
+                       tmp = *((u32 *) obj->buffer.pointer);
+               } else if (obj->type == ACPI_TYPE_INTEGER) {
+                       tmp = (u32) obj->integer.value;
+               }
        }
 
        if (out)
@@ -1193,12 +1197,14 @@ static acpi_status WMID_set_capabilities(void)
                return status;
 
        obj = (union acpi_object *) out.pointer;
-       if (obj && obj->type == ACPI_TYPE_BUFFER &&
-               (obj->buffer.length == sizeof(u32) ||
-               obj->buffer.length == sizeof(u64))) {
-               devices = *((u32 *) obj->buffer.pointer);
-       } else if (obj->type == ACPI_TYPE_INTEGER) {
-               devices = (u32) obj->integer.value;
+       if (obj) {
+               if (obj->type == ACPI_TYPE_BUFFER &&
+                       (obj->buffer.length == sizeof(u32) ||
+                       obj->buffer.length == sizeof(u64))) {
+                       devices = *((u32 *) obj->buffer.pointer);
+               } else if (obj->type == ACPI_TYPE_INTEGER) {
+                       devices = (u32) obj->integer.value;
+               }
        } else {
                kfree(out.pointer);
                return AE_ERROR;
@@ -1330,7 +1336,7 @@ static struct led_classdev mail_led = {
        .brightness_set = mail_led_set,
 };
 
-static int __devinit acer_led_init(struct device *dev)
+static int acer_led_init(struct device *dev)
 {
        return led_classdev_register(dev, &mail_led);
 }
@@ -1372,7 +1378,7 @@ static const struct backlight_ops acer_bl_ops = {
        .update_status = update_bl_status,
 };
 
-static int __devinit acer_backlight_init(struct device *dev)
+static int acer_backlight_init(struct device *dev)
 {
        struct backlight_properties props;
        struct backlight_device *bd;
@@ -1676,6 +1682,7 @@ static void acer_wmi_notify(u32 value, void *context)
        acpi_status status;
        u16 device_state;
        const struct key_entry *key;
+       u32 scancode;
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
@@ -1712,6 +1719,7 @@ static void acer_wmi_notify(u32 value, void *context)
                        pr_warn("Unknown key number - 0x%x\n",
                                return_value.key_num);
                } else {
+                       scancode = return_value.key_num;
                        switch (key->keycode) {
                        case KEY_WLAN:
                        case KEY_BLUETOOTH:
@@ -1725,9 +1733,11 @@ static void acer_wmi_notify(u32 value, void *context)
                                        rfkill_set_sw_state(bluetooth_rfkill,
                                                !(device_state & ACER_WMID3_GDS_BLUETOOTH));
                                break;
+                       case KEY_TOUCHPAD_TOGGLE:
+                               scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ?
+                                               KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF;
                        }
-                       sparse_keymap_report_entry(acer_wmi_input_dev, key,
-                                                  1, true);
+                       sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
                }
                break;
        case WMID_ACCEL_EVENT:
@@ -1946,12 +1956,14 @@ static u32 get_wmid_devices(void)
                return 0;
 
        obj = (union acpi_object *) out.pointer;
-       if (obj && obj->type == ACPI_TYPE_BUFFER &&
-               (obj->buffer.length == sizeof(u32) ||
-               obj->buffer.length == sizeof(u64))) {
-               devices = *((u32 *) obj->buffer.pointer);
-       } else if (obj->type == ACPI_TYPE_INTEGER) {
-               devices = (u32) obj->integer.value;
+       if (obj) {
+               if (obj->type == ACPI_TYPE_BUFFER &&
+                       (obj->buffer.length == sizeof(u32) ||
+                       obj->buffer.length == sizeof(u64))) {
+                       devices = *((u32 *) obj->buffer.pointer);
+               } else if (obj->type == ACPI_TYPE_INTEGER) {
+                       devices = (u32) obj->integer.value;
+               }
        }
 
        kfree(out.pointer);
@@ -1961,7 +1973,7 @@ static u32 get_wmid_devices(void)
 /*
  * Platform device
  */
-static int __devinit acer_platform_probe(struct platform_device *device)
+static int acer_platform_probe(struct platform_device *device)
 {
        int err;
 
index c2e3e63d2c157880efe22ab44ae1ba049427aa8a..f94467c0522506b51247c028cd79fee2767cbcaf 100644 (file)
@@ -515,7 +515,7 @@ static int acerhdf_suspend(struct device *dev)
        return 0;
 }
 
-static int __devinit acerhdf_probe(struct platform_device *device)
+static int acerhdf_probe(struct platform_device *device)
 {
        return 0;
 }
index 1deca7f6c4eace047cd2c871105aab77da43d08b..6296f078b7bc78eb57e89314e869f10c93a90eef 100644 (file)
@@ -74,7 +74,7 @@ static const struct rfkill_ops amilo_m7440_rfkill_ops = {
        .set_block = amilo_m7440_rfkill_set_block
 };
 
-static const struct dmi_system_id __devinitconst amilo_rfkill_id_table[] = {
+static const struct dmi_system_id amilo_rfkill_id_table[] = {
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -95,7 +95,7 @@ static const struct dmi_system_id __devinitconst amilo_rfkill_id_table[] = {
 static struct platform_device *amilo_rfkill_pdev;
 static struct rfkill *amilo_rfkill_dev;
 
-static int __devinit amilo_rfkill_probe(struct platform_device *device)
+static int amilo_rfkill_probe(struct platform_device *device)
 {
        int rc;
        const struct dmi_system_id *system_id =
index db8f63841b4265922b5a630c020e00cb4f490ad3..f74bfcbb7bad8ce0e329ee9b0fe099451da1486e 100644 (file)
@@ -411,8 +411,7 @@ static int gmux_resume(struct pnp_dev *pnp)
        return 0;
 }
 
-static int __devinit gmux_probe(struct pnp_dev *pnp,
-                               const struct pnp_device_id *id)
+static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        struct apple_gmux_data *gmux_data;
        struct resource *res;
@@ -577,7 +576,7 @@ err_free:
        return ret;
 }
 
-static void __devexit gmux_remove(struct pnp_dev *pnp)
+static void gmux_remove(struct pnp_dev *pnp)
 {
        struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
 
@@ -609,7 +608,7 @@ static const struct pnp_device_id gmux_device_ids[] = {
 static struct pnp_driver gmux_pnp_driver = {
        .name           = "apple-gmux",
        .probe          = gmux_probe,
-       .remove         = __devexit_p(gmux_remove),
+       .remove         = gmux_remove,
        .id_table       = gmux_device_ids,
        .suspend        = gmux_suspend,
        .resume         = gmux_resume
index 4b568df56643f846de78a3228582342fb3a89c67..fcde4e528819c04daf4b919ba00d70a20f7456c3 100644 (file)
@@ -860,8 +860,10 @@ static ssize_t show_infos(struct device *dev,
        /*
         * The HWRS method return informations about the hardware.
         * 0x80 bit is for WLAN, 0x100 for Bluetooth.
+        * 0x40 for WWAN, 0x10 for WIMAX.
         * The significance of others is yet to be found.
-        * If we don't find the method, we assume the device are present.
+        * We don't currently use this for device detection, and it
+        * takes several seconds to run on some systems.
         */
        rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);
        if (!ACPI_FAILURE(rv))
@@ -1682,7 +1684,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *model = NULL;
-       unsigned long long bsts_result, hwrs_result;
+       unsigned long long bsts_result;
        char *string = NULL;
        acpi_status status;
 
@@ -1741,20 +1743,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
                return -ENOMEM;
        }
 
-       if (*string)
+       if (string)
                pr_notice("  %s model detected\n", string);
 
-       /*
-        * The HWRS method return informations about the hardware.
-        * 0x80 bit is for WLAN, 0x100 for Bluetooth,
-        * 0x40 for WWAN, 0x10 for WIMAX.
-        * The significance of others is yet to be found.
-        */
-       status =
-           acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);
-       if (!ACPI_FAILURE(status))
-               pr_notice("  HWRS returned %x", (int)hwrs_result);
-
        if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
                asus->have_rsts = true;
 
@@ -1763,7 +1754,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
        return AE_OK;
 }
 
-static int __devinit asus_acpi_init(struct asus_laptop *asus)
+static int asus_acpi_init(struct asus_laptop *asus)
 {
        int result = 0;
 
@@ -1823,7 +1814,7 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        return result;
 }
 
-static void __devinit asus_dmi_check(void)
+static void asus_dmi_check(void)
 {
        const char *model;
 
@@ -1839,7 +1830,7 @@ static void __devinit asus_dmi_check(void)
 
 static bool asus_device_present;
 
-static int __devinit asus_acpi_add(struct acpi_device *device)
+static int asus_acpi_add(struct acpi_device *device)
 {
        struct asus_laptop *asus;
        int result;
index 1887e2f166a43edeb449ae2851c8f77a8a63bcfc..475cc52425119a1a874347218d2a6cd5de1e4990 100644 (file)
@@ -713,15 +713,15 @@ static struct attribute_group compal_attribute_group = {
        .attrs = compal_attributes
 };
 
-static int __devinit compal_probe(struct platform_device *);
-static int __devexit compal_remove(struct platform_device *);
+static int compal_probe(struct platform_device *);
+static int compal_remove(struct platform_device *);
 static struct platform_driver compal_driver = {
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
        },
        .probe  = compal_probe,
-       .remove = __devexit_p(compal_remove)
+       .remove = compal_remove,
 };
 
 static enum power_supply_property compal_bat_properties[] = {
@@ -1015,7 +1015,7 @@ err_backlight:
        return ret;
 }
 
-static int __devinit compal_probe(struct platform_device *pdev)
+static int compal_probe(struct platform_device *pdev)
 {
        int err;
        struct compal_data *data;
@@ -1067,7 +1067,7 @@ static void __exit compal_cleanup(void)
        pr_info("Driver unloaded\n");
 }
 
-static int __devexit compal_remove(struct platform_device *pdev)
+static int compal_remove(struct platform_device *pdev)
 {
        struct compal_data *data;
 
index 927c33af67ecc994b46ae2802a25f1cd5bfac5ed..fa3ee6209572976b71d623585ecfb026842d5645 100644 (file)
@@ -115,7 +115,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = {
 };
 MODULE_DEVICE_TABLE(dmi, dell_device_table);
 
-static struct dmi_system_id __devinitdata dell_quirks[] = {
+static struct dmi_system_id dell_quirks[] = {
        {
                .callback = dmi_matched,
                .ident = "Dell Vostro V130",
@@ -503,7 +503,7 @@ static struct led_classdev touchpad_led = {
        .flags = LED_CORE_SUSPENDRESUME,
 };
 
-static int __devinit touchpad_led_init(struct device *dev)
+static int touchpad_led_init(struct device *dev)
 {
        return led_classdev_register(dev, &touchpad_led);
 }
index 5ca264179f4e32a758102b0a05f865164250534b..528e9495458d35f3396efeb6a3ce6e78e201bcd9 100644 (file)
@@ -1375,7 +1375,7 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)
        cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
 }
 
-static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
+static int eeepc_acpi_init(struct eeepc_laptop *eeepc)
 {
        unsigned int init_flags;
        int result;
@@ -1407,7 +1407,7 @@ static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
        return 0;
 }
 
-static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
+static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
 {
        /*
         * If the following call to set_acpi() fails, it's because there's no
@@ -1419,7 +1419,7 @@ static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
 
 static bool eeepc_device_present;
 
-static int __devinit eeepc_acpi_add(struct acpi_device *device)
+static int eeepc_acpi_add(struct acpi_device *device)
 {
        struct eeepc_laptop *eeepc;
        int result;
index f77484528b1b2a74c1d0c483b637e810623cc585..174ca01c4aa71fda16dac075bc3171860c70c06e 100644 (file)
@@ -192,8 +192,8 @@ static void fujitsu_reset(void)
        fujitsu_send_state();
 }
 
-static int __devinit input_fujitsu_setup(struct device *parent,
-                                        const char *name, const char *phys)
+static int input_fujitsu_setup(struct device *parent, const char *name,
+                              const char *phys)
 {
        struct input_dev *idev;
        int error;
@@ -277,21 +277,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void __devinit fujitsu_dmi_common(const struct dmi_system_id *dmi)
+static void fujitsu_dmi_common(const struct dmi_system_id *dmi)
 {
        pr_info("%s\n", dmi->ident);
        memcpy(fujitsu.config.keymap, dmi->driver_data,
                        sizeof(fujitsu.config.keymap));
 }
 
-static int __devinit fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
+static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
 {
        fujitsu_dmi_common(dmi);
        fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
        return 1;
 }
 
-static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
+static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
 {
        fujitsu_dmi_common(dmi);
        fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
@@ -366,8 +366,7 @@ static const struct dmi_system_id dmi_ids[] __initconst = {
        { NULL }
 };
 
-static acpi_status __devinit
-fujitsu_walk_resources(struct acpi_resource *res, void *data)
+static acpi_status fujitsu_walk_resources(struct acpi_resource *res, void *data)
 {
        switch (res->type) {
        case ACPI_RESOURCE_TYPE_IRQ:
@@ -390,7 +389,7 @@ fujitsu_walk_resources(struct acpi_resource *res, void *data)
        }
 }
 
-static int __devinit acpi_fujitsu_add(struct acpi_device *adev)
+static int acpi_fujitsu_add(struct acpi_device *adev)
 {
        acpi_status status;
        int error;
@@ -432,7 +431,7 @@ static int __devinit acpi_fujitsu_add(struct acpi_device *adev)
        return 0;
 }
 
-static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type)
+static int acpi_fujitsu_remove(struct acpi_device *adev, int type)
 {
        free_irq(fujitsu.irq, fujitsu_interrupt);
        release_region(fujitsu.io_base, fujitsu.io_length);
index 387183a2d6ddd4405c8430137e8da3c4595b5407..1dde7accf27ccb9f4b9150a3927e7c9e8b0a3189 100644 (file)
@@ -72,7 +72,7 @@ enum hp_wmi_event_ids {
        HPWMI_LOCK_SWITCH = 7,
 };
 
-static int __devinit hp_wmi_bios_setup(struct platform_device *device);
+static int hp_wmi_bios_setup(struct platform_device *device);
 static int __exit hp_wmi_bios_remove(struct platform_device *device);
 static int hp_wmi_resume_handler(struct device *device);
 
@@ -619,7 +619,7 @@ static void cleanup_sysfs(struct platform_device *device)
        device_remove_file(&device->dev, &dev_attr_tablet);
 }
 
-static int __devinit hp_wmi_rfkill_setup(struct platform_device *device)
+static int hp_wmi_rfkill_setup(struct platform_device *device)
 {
        int err;
        int wireless = 0;
@@ -698,7 +698,7 @@ register_wifi_error:
        return err;
 }
 
-static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device)
+static int hp_wmi_rfkill2_setup(struct platform_device *device)
 {
        int err, i;
        struct bios_rfkill2_state state;
@@ -778,7 +778,7 @@ fail:
        return err;
 }
 
-static int __devinit hp_wmi_bios_setup(struct platform_device *device)
+static int hp_wmi_bios_setup(struct platform_device *device)
 {
        int err;
 
index 7481146a5b473c1cab6745a7d6ac1ae76e66257e..97c2be195efc36eeb76bd848f2c1327be7f168c2 100644 (file)
@@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) {
        if (force)
                pr_warn("module loaded by force\n");
        /* first ensure that we are running on IBM HW */
-       else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
+       else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table))
                return -ENODEV;
 
        /* Get the address for the Extended BIOS Data Area */
index 5ff4f2e314d2857656de31f127823dc8d20556af..64bfb30a52e9a022c3a1c08be8f4f59c0a8a5ee6 100644 (file)
@@ -298,7 +298,7 @@ static const struct file_operations debugfs_cfg_fops = {
        .release = single_release,
 };
 
-static int __devinit ideapad_debugfs_init(struct ideapad_private *priv)
+static int ideapad_debugfs_init(struct ideapad_private *priv)
 {
        struct dentry *node;
 
@@ -468,8 +468,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
                        rfkill_set_hw_state(priv->rfk[i], hw_blocked);
 }
 
-static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
-                                            int dev)
+static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int ret;
@@ -519,7 +518,7 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
 /*
  * Platform device
  */
-static int __devinit ideapad_platform_init(struct ideapad_private *priv)
+static int ideapad_platform_init(struct ideapad_private *priv)
 {
        int result;
 
@@ -569,7 +568,7 @@ static const struct key_entry ideapad_keymap[] = {
        { KE_END, 0 },
 };
 
-static int __devinit ideapad_input_init(struct ideapad_private *priv)
+static int ideapad_input_init(struct ideapad_private *priv)
 {
        struct input_dev *inputdev;
        int error;
@@ -776,7 +775,7 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
        }
 }
 
-static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
+static int ideapad_acpi_add(struct acpi_device *adevice)
 {
        int ret, i;
        int cfg;
@@ -835,7 +834,7 @@ platform_failed:
        return ret;
 }
 
-static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
+static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int i;
index bcbad8452a6f0ca5bb818b684837e207ffef7b5f..f59683aa13d5d9ce522355ba98eeaa2898f56f01 100644 (file)
@@ -56,7 +56,7 @@ static irqreturn_t mfld_pb_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mfld_pb_probe(struct platform_device *pdev)
+static int mfld_pb_probe(struct platform_device *pdev)
 {
        struct input_dev *input;
        int irq = platform_get_irq(pdev, 0);
@@ -121,7 +121,7 @@ err_free_input:
        return error;
 }
 
-static int __devexit mfld_pb_remove(struct platform_device *pdev)
+static int mfld_pb_remove(struct platform_device *pdev)
 {
        struct input_dev *input = platform_get_drvdata(pdev);
        int irq = platform_get_irq(pdev, 0);
@@ -139,7 +139,7 @@ static struct platform_driver mfld_pb_driver = {
                .owner = THIS_MODULE,
        },
        .probe  = mfld_pb_probe,
-       .remove = __devexit_p(mfld_pb_remove),
+       .remove = mfld_pb_remove,
 };
 
 module_platform_driver(mfld_pb_driver);
index 93de09019d1d53649621eda7e83529fcd75624fa..81c491e74b3471e5433a8024df690476489a4fdc 100644 (file)
@@ -563,7 +563,7 @@ static struct platform_driver mid_thermal_driver = {
                .pm = &mid_thermal_pm,
        },
        .probe = mid_thermal_probe,
-       .remove = __devexit_p(mid_thermal_remove),
+       .remove = mid_thermal_remove,
        .id_table = therm_id_table,
 };
 
index 79a0c2f6be53996c2771ffd532e517a6ac8bef4e..f6f18cde0f11c70f035e88c1da80f96506e0b3ab 100644 (file)
@@ -278,12 +278,12 @@ static void oaktrail_backlight_exit(void)
                backlight_device_unregister(oaktrail_bl_device);
 }
 
-static int __devinit oaktrail_probe(struct platform_device *pdev)
+static int oaktrail_probe(struct platform_device *pdev)
 {
        return 0;
 }
 
-static int __devexit oaktrail_remove(struct platform_device *pdev)
+static int oaktrail_remove(struct platform_device *pdev)
 {
        return 0;
 }
@@ -294,7 +294,7 @@ static struct platform_driver oaktrail_driver = {
                .owner = THIS_MODULE,
        },
        .probe  = oaktrail_probe,
-       .remove = __devexit_p(oaktrail_remove)
+       .remove = oaktrail_remove,
 };
 
 static int dmi_check_cb(const struct dmi_system_id *id)
index 1686c1e07d5d250c03d27fe24077f0c3f43b00d7..6f4b7289a0598d8fc514a1e2cbd5b3ed401532f0 100644 (file)
@@ -230,7 +230,7 @@ static irqreturn_t pmic_irq_handler(int irq, void *data)
        return ret;
 }
 
-static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
+static int platform_pmic_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        int irq = platform_get_irq(pdev, 0);
index dd90d15f52101e24296b30523d68056e01bac7df..d1f0300531766f64ab741ccbd4d388db0644d427 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/ctype.h>
+#include <linux/efi.h>
 #include <acpi/video.h>
 
 /*
@@ -1523,6 +1524,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
         .driver_data = &samsung_broken_acpi_video,
        },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N250P",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
+               DMI_MATCH(DMI_BOARD_NAME, "N250P"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -1534,6 +1545,9 @@ static int __init samsung_init(void)
        struct samsung_laptop *samsung;
        int ret;
 
+       if (efi_enabled(EFI_BOOT))
+               return -ENODEV;
+
        quirks = &samsung_unknown;
        if (!force && !dmi_check_system(samsung_dmi_table))
                return -ENODEV;
index 1e54ae74274cddbb95323f827ecc11de0d228050..5f770059fd4d3aa3115140fd5afcc7a7832eca53 100644 (file)
@@ -77,7 +77,7 @@ static int samsungq10_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
                          samsungq10_suspend, samsungq10_resume);
 
-static int __devinit samsungq10_probe(struct platform_device *pdev)
+static int samsungq10_probe(struct platform_device *pdev)
 {
 
        struct backlight_properties props;
@@ -99,7 +99,7 @@ static int __devinit samsungq10_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit samsungq10_remove(struct platform_device *pdev)
+static int samsungq10_remove(struct platform_device *pdev)
 {
 
        struct backlight_device *bd = platform_get_drvdata(pdev);
@@ -119,7 +119,7 @@ static struct platform_driver samsungq10_driver = {
                .pm     = &samsungq10_pm_ops,
        },
        .probe          = samsungq10_probe,
-       .remove         = __devexit_p(samsungq10_remove),
+       .remove         = samsungq10_remove,
 };
 
 static struct platform_device *samsungq10_device;
index daaddec68def7e1c7cb11e4fe6d54e4193943c55..b8ad71f7863fa2b0fa9c741e9605ffdfe5a92fcf 100644 (file)
@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle handle, char *name, int *value,
 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
                void *buffer, size_t buflen)
 {
+       int ret = 0;
        size_t len = len;
        union acpi_object *object = __call_snc_method(handle, name, value);
 
        if (!object)
                return -EINVAL;
 
-       if (object->type == ACPI_TYPE_BUFFER)
+       if (object->type == ACPI_TYPE_BUFFER) {
                len = MIN(buflen, object->buffer.length);
+               memcpy(buffer, object->buffer.pointer, len);
 
-       else if (object->type == ACPI_TYPE_INTEGER)
+       } else if (object->type == ACPI_TYPE_INTEGER) {
                len = MIN(buflen, sizeof(object->integer.value));
+               memcpy(buffer, &object->integer.value, len);
 
-       else {
+       else {
                pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
                                ACPI_TYPE_BUFFER, object->type);
-               kfree(object);
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
-       memcpy(buffer, object->buffer.pointer, len);
        kfree(object);
-       return 0;
+       return ret;
 }
 
 struct sony_nc_handles {
index e24f5ae475af019815b10a07e2febaabd29135c6..9b93fdb61ed7c03733ead31aaa7f0ef632a6bd00 100644 (file)
@@ -187,7 +187,7 @@ static int __init tc1100_probe(struct platform_device *device)
 }
 
 
-static int __devexit tc1100_remove(struct platform_device *device)
+static int tc1100_remove(struct platform_device *device)
 {
        sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group);
 
@@ -241,7 +241,7 @@ static struct platform_driver tc1100_driver = {
                .pm = &tc1100_pm_ops,
 #endif
        },
-       .remove = __devexit_p(tc1100_remove),
+       .remove = tc1100_remove,
 };
 
 static int __init tc1100_init(void)
index 75dd651664ae6f14dbfc43ce42d2a9632368b513..f946ca7cb76271a321ce900f5c59b3a07538552b 100644 (file)
@@ -6732,7 +6732,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
        return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
 }
 
-static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
+static struct snd_kcontrol_new volume_alsa_control_vol = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Console Playback Volume",
        .index = 0,
@@ -6741,7 +6741,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
        .get = volume_alsa_vol_get,
 };
 
-static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
+static struct snd_kcontrol_new volume_alsa_control_mute = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Console Playback Switch",
        .index = 0,
index 5f1256d5e9332cf45dbdd2031987ea41fe0212cf..c2727895794ca51d7623bc820c6aeadd422fa4c5 100644 (file)
@@ -150,7 +150,7 @@ static const struct acpi_device_id toshiba_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
 
-static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
+static const struct key_entry toshiba_acpi_keymap[] = {
        { KE_KEY, 0x101, { KEY_MUTE } },
        { KE_KEY, 0x102, { KEY_ZOOMOUT } },
        { KE_KEY, 0x103, { KEY_ZOOMIN } },
@@ -875,8 +875,7 @@ static const struct file_operations version_proc_fops = {
 
 #define PROC_TOSHIBA           "toshiba"
 
-static void __devinit
-create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
+static void create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
 {
        if (dev->backlight_dev)
                proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
@@ -979,7 +978,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
                pr_info("Unknown key %x\n", scancode);
 }
 
-static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
+static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
        acpi_handle ec_handle, handle;
@@ -1069,7 +1068,7 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        return error;
 }
 
-static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
+static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
 {
        struct backlight_properties props;
        int brightness;
@@ -1154,7 +1153,7 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
        return 0;
 }
 
-static const char * __devinit find_hci_method(acpi_handle handle)
+static const char *find_hci_method(acpi_handle handle)
 {
        acpi_status status;
        acpi_handle hci_handle;
@@ -1170,7 +1169,7 @@ static const char * __devinit find_hci_method(acpi_handle handle)
        return NULL;
 }
 
-static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
+static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
        struct toshiba_acpi_dev *dev;
        const char *hci_method;
index 1da13ed34b04f9f944c7bb869f4dcafb5c036e46..4bd17248dfc612c627bede36e6a3ebc64fca43f7 100644 (file)
@@ -40,7 +40,7 @@ static const struct rfkill_ops rfkill_ops = {
        .set_block = rfkill_set_block,
 };
 
-static int __devinit xo1_rfkill_probe(struct platform_device *pdev)
+static int xo1_rfkill_probe(struct platform_device *pdev)
 {
        struct rfkill *rfk;
        int r;
@@ -60,7 +60,7 @@ static int __devinit xo1_rfkill_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit xo1_rfkill_remove(struct platform_device *pdev)
+static int xo1_rfkill_remove(struct platform_device *pdev)
 {
        struct rfkill *rfk = platform_get_drvdata(pdev);
        rfkill_unregister(rfk);
@@ -74,7 +74,7 @@ static struct platform_driver xo1_rfkill_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = xo1_rfkill_probe,
-       .remove         = __devexit_p(xo1_rfkill_remove),
+       .remove         = xo1_rfkill_remove,
 };
 
 module_platform_driver(xo1_rfkill_driver);
index cfaf5b73540bbc6b958ad7e5f15ea4822ab7c8d6..0c201317284b40e93014d0a574b3ef0ab9d81b9b 100644 (file)
@@ -298,6 +298,39 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
        return ret;
 }
 
+static char *pnp_get_resource_value(char *buf,
+                                   unsigned long type,
+                                   resource_size_t *start,
+                                   resource_size_t *end,
+                                   unsigned long *flags)
+{
+       if (start)
+               *start = 0;
+       if (end)
+               *end = 0;
+       if (flags)
+               *flags = 0;
+
+       /* TBD: allow for disabled resources */
+
+       buf = skip_spaces(buf);
+       if (start) {
+               *start = simple_strtoull(buf, &buf, 0);
+               if (end) {
+                       buf = skip_spaces(buf);
+                       if (*buf == '-') {
+                               buf = skip_spaces(buf + 1);
+                               *end = simple_strtoull(buf, &buf, 0);
+                       } else
+                               *end = *start;
+               }
+       }
+
+       /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
+
+       return buf;
+}
+
 static ssize_t pnp_set_current_resources(struct device *dmdev,
                                         struct device_attribute *attr,
                                         const char *ubuf, size_t count)
@@ -305,7 +338,6 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
        struct pnp_dev *dev = to_pnp_dev(dmdev);
        char *buf = (void *)ubuf;
        int retval = 0;
-       resource_size_t start, end;
 
        if (dev->status & PNP_ATTACHED) {
                retval = -EBUSY;
@@ -349,6 +381,10 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
                goto done;
        }
        if (!strnicmp(buf, "set", 3)) {
+               resource_size_t start;
+               resource_size_t end;
+               unsigned long flags;
+
                if (dev->active)
                        goto done;
                buf += 3;
@@ -357,42 +393,37 @@ static ssize_t pnp_set_current_resources(struct device *dmdev,
                while (1) {
                        buf = skip_spaces(buf);
                        if (!strnicmp(buf, "io", 2)) {
-                               buf = skip_spaces(buf + 2);
-                               start = simple_strtoul(buf, &buf, 0);
-                               buf = skip_spaces(buf);
-                               if (*buf == '-') {
-                                       buf = skip_spaces(buf + 1);
-                                       end = simple_strtoul(buf, &buf, 0);
-                               } else
-                                       end = start;
-                               pnp_add_io_resource(dev, start, end, 0);
-                               continue;
-                       }
-                       if (!strnicmp(buf, "mem", 3)) {
-                               buf = skip_spaces(buf + 3);
-                               start = simple_strtoul(buf, &buf, 0);
-                               buf = skip_spaces(buf);
-                               if (*buf == '-') {
-                                       buf = skip_spaces(buf + 1);
-                                       end = simple_strtoul(buf, &buf, 0);
-                               } else
-                                       end = start;
-                               pnp_add_mem_resource(dev, start, end, 0);
-                               continue;
-                       }
-                       if (!strnicmp(buf, "irq", 3)) {
-                               buf = skip_spaces(buf + 3);
-                               start = simple_strtoul(buf, &buf, 0);
-                               pnp_add_irq_resource(dev, start, 0);
-                               continue;
-                       }
-                       if (!strnicmp(buf, "dma", 3)) {
-                               buf = skip_spaces(buf + 3);
-                               start = simple_strtoul(buf, &buf, 0);
-                               pnp_add_dma_resource(dev, start, 0);
-                               continue;
-                       }
-                       break;
+                               buf = pnp_get_resource_value(buf + 2,
+                                                            IORESOURCE_IO,
+                                                            &start, &end,
+                                                            &flags);
+                               pnp_add_io_resource(dev, start, end, flags);
+                       } else if (!strnicmp(buf, "mem", 3)) {
+                               buf = pnp_get_resource_value(buf + 3,
+                                                            IORESOURCE_MEM,
+                                                            &start, &end,
+                                                            &flags);
+                               pnp_add_mem_resource(dev, start, end, flags);
+                       } else if (!strnicmp(buf, "irq", 3)) {
+                               buf = pnp_get_resource_value(buf + 3,
+                                                            IORESOURCE_IRQ,
+                                                            &start, NULL,
+                                                            &flags);
+                               pnp_add_irq_resource(dev, start, flags);
+                       } else if (!strnicmp(buf, "dma", 3)) {
+                               buf = pnp_get_resource_value(buf + 3,
+                                                            IORESOURCE_DMA,
+                                                            &start, NULL,
+                                                            &flags);
+                               pnp_add_dma_resource(dev, start, flags);
+                       } else if (!strnicmp(buf, "bus", 3)) {
+                               buf = pnp_get_resource_value(buf + 3,
+                                                            IORESOURCE_BUS,
+                                                            &start, &end,
+                                                            NULL);
+                               pnp_add_bus_resource(dev, start, end);
+                       } else
+                               break;
                }
                mutex_unlock(&pnp_res_mutex);
                goto done;
index ed9ce507149ab87efe8692b24379a82ab728184c..95cebf0185decdd48134892b43f5d45928ab3515 100644 (file)
 
 DEFINE_MUTEX(pnp_res_mutex);
 
+static struct resource *pnp_find_resource(struct pnp_dev *dev,
+                                         unsigned char rule,
+                                         unsigned long type,
+                                         unsigned int bar)
+{
+       struct resource *res = pnp_get_resource(dev, type, bar);
+
+       /* when the resource already exists, set its resource bits from rule */
+       if (res) {
+               res->flags &= ~IORESOURCE_BITS;
+               res->flags |= rule & IORESOURCE_BITS;
+       }
+
+       return res;
+}
+
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
        struct resource *res, local_res;
 
-       res = pnp_get_resource(dev, IORESOURCE_IO, idx);
+       res = pnp_find_resource(dev, rule->flags, IORESOURCE_IO, idx);
        if (res) {
                pnp_dbg(&dev->dev, "  io %d already set to %#llx-%#llx "
                        "flags %#lx\n", idx, (unsigned long long) res->start,
@@ -65,7 +81,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
 {
        struct resource *res, local_res;
 
-       res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
+       res = pnp_find_resource(dev, rule->flags, IORESOURCE_MEM, idx);
        if (res) {
                pnp_dbg(&dev->dev, "  mem %d already set to %#llx-%#llx "
                        "flags %#lx\n", idx, (unsigned long long) res->start,
@@ -78,6 +94,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
        res->start = 0;
        res->end = 0;
 
+       /* ??? rule->flags restricted to 8 bits, all tests bogus ??? */
        if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
                res->flags |= IORESOURCE_READONLY;
        if (rule->flags & IORESOURCE_MEM_CACHEABLE)
@@ -123,7 +140,7 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
                5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
        };
 
-       res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
+       res = pnp_find_resource(dev, rule->flags, IORESOURCE_IRQ, idx);
        if (res) {
                pnp_dbg(&dev->dev, "  irq %d already set to %d flags %#lx\n",
                        idx, (int) res->start, res->flags);
@@ -182,7 +199,7 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
                1, 3, 5, 6, 7, 0, 2, 4
        };
 
-       res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
+       res = pnp_find_resource(dev, rule->flags, IORESOURCE_DMA, idx);
        if (res) {
                pnp_dbg(&dev->dev, "  dma %d already set to %d flags %#lx\n",
                        idx, (int) res->start, res->flags);
index 03cc528425cb883ceb346eba27560edd20b3fda8..f034ae43e045ac03127adeca8f1db0f4cbe59b79 100644 (file)
@@ -452,10 +452,8 @@ struct abx500_bm_data ab8500_bm_data = {
        .fg_params              = &fg,
 };
 
-int __devinit
-bmdevs_of_probe(struct device *dev,
-               struct device_node *np,
-               struct abx500_bm_data **battery)
+int bmdevs_of_probe(struct device *dev, struct device_node *np,
+                   struct abx500_bm_data **battery)
 {
        struct  abx500_battery_type *btype;
        struct  device_node *np_bat_supply;
index a17d084117230071ad3d014e6225fd2e69f7c9f0..6b2238bb6a8111d1362ea00733f25787354efad6 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/power/smartreflex.h>
 
-#include <plat/cpu.h>
-
 #define SMARTREFLEX_NAME_LEN   16
 #define NVALUE_NAME_LEN                40
 #define SR_DISABLE_TIMEOUT     200
index 298c47d111b4c53470ad08a5d6fb3db1064a5c7f..1ec810ada5edd4cf4c9299016ef5326a35c800f1 100644 (file)
@@ -668,7 +668,7 @@ static int olpc_battery_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id olpc_battery_ids[] __devinitconst = {
+static const struct of_device_id olpc_battery_ids[] = {
        { .compatible = "olpc,xo1-battery" },
        {}
 };
index 0491e5335d0214e5361bab275f6b40b26eec9bd6..e290d48ddd99cab71f1effff5ae87243a11e560a 100644 (file)
@@ -29,15 +29,16 @@ static int gpio_active_low;
 
 static void gpio_poweroff_do_poweroff(void)
 {
-       BUG_ON(gpio_num == -1);
+       BUG_ON(!gpio_is_valid(gpio_num));
 
-       /* drive it active */
+       /* drive it active, also inactive->active edge */
        gpio_direction_output(gpio_num, !gpio_active_low);
        mdelay(100);
-       /* rising edge or drive inactive */
+       /* drive inactive, also active->inactive edge */
        gpio_set_value(gpio_num, gpio_active_low);
        mdelay(100);
-       /* falling edge */
+
+       /* drive it active, also inactive->active edge */
        gpio_set_value(gpio_num, !gpio_active_low);
 
        /* give it some time */
@@ -46,7 +47,7 @@ static void gpio_poweroff_do_poweroff(void)
        WARN_ON(1);
 }
 
-static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
+static int gpio_poweroff_probe(struct platform_device *pdev)
 {
        enum of_gpio_flags flags;
        bool input = false;
@@ -60,15 +61,12 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
        }
 
        gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
-       if (gpio_num < 0) {
-               pr_err("%s: Could not get GPIO configuration: %d",
-                      __func__, gpio_num);
-               return -ENODEV;
-       }
+       if (!gpio_is_valid(gpio_num))
+               return gpio_num;
+
        gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-       if (of_get_property(pdev->dev.of_node, "input", NULL))
-               input = true;
+       input = of_property_read_bool(pdev->dev.of_node, "input");
 
        ret = gpio_request(gpio_num, "poweroff-gpio");
        if (ret) {
@@ -96,10 +94,9 @@ err:
        return -ENODEV;
 }
 
-static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+static int gpio_poweroff_remove(struct platform_device *pdev)
 {
-       if (gpio_num != -1)
-               gpio_free(gpio_num);
+       gpio_free(gpio_num);
        if (pm_power_off == &gpio_poweroff_do_poweroff)
                pm_power_off = NULL;
 
@@ -113,17 +110,17 @@ static const struct of_device_id of_gpio_poweroff_match[] = {
 
 static struct platform_driver gpio_poweroff_driver = {
        .probe = gpio_poweroff_probe,
-       .remove = __devexit_p(gpio_poweroff_remove),
+       .remove = gpio_poweroff_remove,
        .driver = {
-                  .name = "poweroff-gpio",
-                  .owner = THIS_MODULE,
-                  .of_match_table = of_gpio_poweroff_match,
-                  },
+               .name = "poweroff-gpio",
+               .owner = THIS_MODULE,
+               .of_match_table = of_gpio_poweroff_match,
+       },
 };
 
 module_platform_driver(gpio_poweroff_driver);
 
 MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
 MODULE_DESCRIPTION("GPIO poweroff driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:poweroff-gpio");
index ca49d6c0ee9d6e0c51ee922416b10b5e594d46b9..8208888b844e973004ba2a146cb40bf70c1458b5 100644 (file)
@@ -197,7 +197,7 @@ static enum power_supply_property rx51_battery_props[] = {
        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 };
 
-static int __devinit rx51_battery_probe(struct platform_device *pdev)
+static int rx51_battery_probe(struct platform_device *pdev)
 {
        struct rx51_device_info *di;
        int ret;
@@ -224,7 +224,7 @@ static int __devinit rx51_battery_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit rx51_battery_remove(struct platform_device *pdev)
+static int rx51_battery_remove(struct platform_device *pdev)
 {
        struct rx51_device_info *di = platform_get_drvdata(pdev);
 
@@ -237,7 +237,7 @@ static int __devexit rx51_battery_remove(struct platform_device *pdev)
 
 static struct platform_driver rx51_battery_driver = {
        .probe = rx51_battery_probe,
-       .remove = __devexit_p(rx51_battery_remove),
+       .remove = rx51_battery_remove,
        .driver = {
                .name = "rx51-battery",
                .owner = THIS_MODULE,
index 6550555454796c0dfe2b08e477f18de49b569729..2bf0c1b608ddc1124595a1a50352041e110a4382 100644 (file)
@@ -196,7 +196,7 @@ static int pps_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver pps_gpio_driver = {
        .probe          = pps_gpio_probe,
-       .remove         =  __devexit_p(pps_gpio_remove),
+       .remove         = pps_gpio_remove,
        .driver         = {
                .name   = PPS_GPIO_NAME,
                .owner  = THIS_MODULE
index 643697f7139070d61cd03015a6d8d6980aa889e2..b139b7792e9fcf6a3c266790fa2dbeea0cf06e27 100644 (file)
@@ -1185,7 +1185,7 @@ int ps3_lpm_close(void)
 }
 EXPORT_SYMBOL_GPL(ps3_lpm_close);
 
-static int __devinit ps3_lpm_probe(struct ps3_system_bus_device *dev)
+static int ps3_lpm_probe(struct ps3_system_bus_device *dev)
 {
        dev_dbg(&dev->core, " -> %s:%u\n", __func__, __LINE__);
 
index 1b98367110c49132ef1d98999fd795f1873a9aba..f2ab435954f6b98d67bbede2b8e4b854b92ff5e4 100644 (file)
@@ -706,7 +706,7 @@ static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
        ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
 }
 
-static int __devinit ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
 {
        int result;
        struct ps3_sys_manager_ops ops;
index 93d0a8b7718aff44f5ccd8bb24c7fff94293d95f..437fc35beb7b706e130f115cfc433b5138002c43 100644 (file)
@@ -932,7 +932,7 @@ int ps3av_audio_mute(int mute)
 }
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-static int __devinit ps3av_probe(struct ps3_system_bus_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
        int res;
        int id;
index 0199eeea63b13f6d770b49897d14bb3da1173290..8f39cac661d26deb4025e2787add57f22dc50db2 100644 (file)
@@ -188,7 +188,7 @@ static int anatop_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
+static struct of_device_id of_anatop_regulator_match_tbl[] = {
        { .compatible = "fsl,anatop-regulator", },
        { /* end */ }
 };
index 0f65b246cc0c8d24c559cdeafd340232d1c55e0c..278584302f2d162c56599ad61a62ade3cdcceadd 100644 (file)
@@ -1885,9 +1885,15 @@ int regulator_can_change_voltage(struct regulator *regulator)
        struct regulator_dev    *rdev = regulator->rdev;
 
        if (rdev->constraints &&
-           rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
-           (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1)
-               return 1;
+           (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+               if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1)
+                       return 1;
+
+               if (rdev->desc->continuous_voltage_range &&
+                   rdev->constraints->min_uV && rdev->constraints->max_uV &&
+                   rdev->constraints->min_uV != rdev->constraints->max_uV)
+                       return 1;
+       }
 
        return 0;
 }
@@ -3315,7 +3321,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
  * @config: runtime configuration for regulator
  *
  * Called by regulator drivers to register a regulator.
- * Returns 0 on success.
+ * Returns a valid pointer to struct regulator_dev on success
+ * or an ERR_PTR() on error.
  */
 struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
index a4b9cb8c43175343bdfaa2a04bc51038e4003c05..1a05ac66878f7933a71d926cf574c0ba65db51b4 100644 (file)
@@ -442,9 +442,9 @@ static struct da9055_regulator_info da9055_regulator_info[] = {
  * GPIO can control regulator state and/or select the regulator register
  * set A/B for voltage ramping.
  */
-static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
-                                     struct regulator_config *config,
-                                     struct da9055_pdata *pdata, int id)
+static int da9055_gpio_init(struct da9055_regulator *regulator,
+                           struct regulator_config *config,
+                           struct da9055_pdata *pdata, int id)
 {
        struct da9055_regulator_info *info = regulator->info;
        int ret = 0;
@@ -533,7 +533,7 @@ static inline struct da9055_regulator_info *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+static int da9055_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        struct da9055_regulator *regulator;
@@ -605,7 +605,7 @@ err_regulator:
        return ret;
 }
 
-static int __devexit da9055_regulator_remove(struct platform_device *pdev)
+static int da9055_regulator_remove(struct platform_device *pdev)
 {
        struct da9055_regulator *regulator = platform_get_drvdata(pdev);
 
@@ -616,7 +616,7 @@ static int __devexit da9055_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver da9055_regulator_driver = {
        .probe = da9055_regulator_probe,
-       .remove = __devexit_p(da9055_regulator_remove),
+       .remove = da9055_regulator_remove,
        .driver = {
                .name = "da9055-regulator",
                .owner = THIS_MODULE,
index 261f3d2299bc0a5d2d074824211172be7a6b8448..89bd2faaef8cf627cddcd9f1b7a03c9b4cab5fae 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "dbx500-prcmu.h"
 
index 48d5b7608b00bd519cbb4c2434721335c91fa4d4..e5c03b534faefce8d2e8f30a5ebecd48b1a995dc 100644 (file)
@@ -246,7 +246,7 @@ static int reg_fixed_voltage_remove(struct platform_device *pdev)
 }
 
 #if defined(CONFIG_OF)
-static const struct of_device_id fixed_of_match[] __devinitconst = {
+static const struct of_device_id fixed_of_match[] = {
        { .compatible = "regulator-fixed", },
        {},
 };
index 8ae288fc150b8682c9cb597b0b4c07cd8cdfda8f..bae681ccd3ea73a24c0c0d3f98a948d9a7fd06f1 100644 (file)
@@ -365,7 +365,7 @@ static int gpio_regulator_remove(struct platform_device *pdev)
 }
 
 #if defined(CONFIG_OF)
-static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+static const struct of_device_id regulator_gpio_of_match[] = {
        { .compatible = "regulator-gpio", },
        {},
 };
index b85040caaea318b13154927bc1beb0e13aef6ad4..cca18a3c0294173293ec0bd6c26b41fbb2b6bb10 100644 (file)
@@ -379,9 +379,10 @@ static struct regulator_desc regulators[] = {
 };
 
 #ifdef CONFIG_OF
-static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max77686_platform_data *pdata)
 {
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct device_node *pmic_np, *regulators_np;
        struct max77686_regulator_data *rdata;
        struct of_regulator_match rmatch;
@@ -390,15 +391,15 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
        pmic_np = iodev->dev->of_node;
        regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
        if (!regulators_np) {
-               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               dev_err(&pdev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
        }
 
        pdata->num_regulators = ARRAY_SIZE(regulators);
-       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
                             pdata->num_regulators, GFP_KERNEL);
        if (!rdata) {
-               dev_err(iodev->dev,
+               dev_err(&pdev->dev,
                        "could not allocate memory for regulator data\n");
                return -ENOMEM;
        }
@@ -407,7 +408,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
                rmatch.name = regulators[i].name;
                rmatch.init_data = NULL;
                rmatch.of_node = NULL;
-               of_regulator_match(iodev->dev, regulators_np, &rmatch, 1);
+               of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
                rdata[i].initdata = rmatch.init_data;
                rdata[i].of_node = rmatch.of_node;
        }
@@ -417,7 +418,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
        return 0;
 }
 #else
-static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max77686_platform_data *pdata)
 {
        return 0;
@@ -440,7 +441,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
        }
 
        if (iodev->dev->of_node) {
-               ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
+               ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
                if (ret)
                        return ret;
        }
index d1a77512d83e69501c2a4a3a3e8c3f09b75f7ba6..d40cf7fdb546e9ee10b79a9ecfa74b2ae468547f 100644 (file)
@@ -237,8 +237,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       ret = of_regulator_match(pdev->dev.parent, regulators,
-                                max8907_matches,
+       ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
                                 ARRAY_SIZE(max8907_matches));
        if (ret < 0) {
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
index 3ee26387b1211e07ca8f3e9e567aa511aa82b7bd..9a8ea916300523025affd734cc2de88668e82c7f 100644 (file)
@@ -248,8 +248,8 @@ static struct regulator_ops max8973_dcdc_ops = {
        .get_mode               = max8973_dcdc_get_mode,
 };
 
-static int __devinit max8973_init_dcdc(struct max8973_chip *max,
-               struct max8973_regulator_platform_data *pdata)
+static int max8973_init_dcdc(struct max8973_chip *max,
+                            struct max8973_regulator_platform_data *pdata)
 {
        int ret;
        uint8_t control1 = 0;
@@ -359,8 +359,8 @@ static const struct regmap_config max8973_regmap_config = {
        .cache_type             = REGCACHE_RBTREE,
 };
 
-static int __devinit max8973_probe(struct i2c_client *client,
-                                    const struct i2c_device_id *id)
+static int max8973_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct max8973_regulator_platform_data *pdata;
        struct regulator_config config = { };
@@ -463,7 +463,7 @@ static int __devinit max8973_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8973_remove(struct i2c_client *client)
+static int max8973_remove(struct i2c_client *client)
 {
        struct max8973_chip *max = i2c_get_clientdata(client);
 
@@ -484,7 +484,7 @@ static struct i2c_driver max8973_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8973_probe,
-       .remove = __devexit_p(max8973_remove),
+       .remove = max8973_remove,
        .id_table = max8973_id,
 };
 
index df0eafb0dc7e63a1f4a9e8bfb989d91caa1d9f63..836908ce505e04277394622289826cee6a073b12 100644 (file)
@@ -71,26 +71,26 @@ struct voltage_map_desc {
        int step;
 };
 
-/* Voltage maps in mV */
+/* Voltage maps in uV */
 static const struct voltage_map_desc ldo_voltage_map_desc = {
-       .min = 800,     .max = 3950,    .step = 50,
+       .min = 800000,  .max = 3950000, .step = 50000,
 }; /* LDO1 ~ 18, 21 all */
 
 static const struct voltage_map_desc buck1245_voltage_map_desc = {
-       .min = 650,     .max = 2225,    .step = 25,
+       .min = 650000,  .max = 2225000, .step = 25000,
 }; /* Buck1, 2, 4, 5 */
 
 static const struct voltage_map_desc buck37_voltage_map_desc = {
-       .min = 750,     .max = 3900,    .step = 50,
+       .min = 750000,  .max = 3900000, .step = 50000,
 }; /* Buck3, 7 */
 
-/* current map in mA */
+/* current map in uA */
 static const struct voltage_map_desc charger_current_map_desc = {
-       .min = 200,     .max = 950,     .step = 50,
+       .min = 200000,  .max = 950000,  .step = 50000,
 };
 
 static const struct voltage_map_desc topoff_current_map_desc = {
-       .min = 50,      .max = 200,     .step = 10,
+       .min = 50000,   .max = 200000,  .step = 10000,
 };
 
 static const struct voltage_map_desc *reg_voltage_map[] = {
@@ -194,7 +194,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev,
        if (val > desc->max)
                return -EINVAL;
 
-       return val * 1000;
+       return val;
 }
 
 static int max8997_get_enable_register(struct regulator_dev *rdev,
@@ -485,7 +485,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
 {
        struct max8997_data *max8997 = rdev_get_drvdata(rdev);
        struct i2c_client *i2c = max8997->iodev->i2c;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
        const struct voltage_map_desc *desc;
        int rid = rdev_get_id(rdev);
        int i, reg, shift, mask, ret;
@@ -509,7 +508,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
 
        desc = reg_voltage_map[rid];
 
-       i = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+       i = max8997_get_voltage_proper_val(desc, min_uV, max_uV);
        if (i < 0)
                return i;
 
@@ -557,7 +556,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev,
        case MAX8997_BUCK4:
        case MAX8997_BUCK5:
                return DIV_ROUND_UP(desc->step * (new_selector - old_selector),
-                                   max8997->ramp_delay);
+                                   max8997->ramp_delay * 1000);
        }
 
        return 0;
@@ -656,7 +655,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
        const struct voltage_map_desc *desc;
        int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg;
        bool gpio_dvs_mode = false;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
 
        if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7)
                return -EINVAL;
@@ -681,7 +679,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
                                                selector);
 
        desc = reg_voltage_map[rid];
-       new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+       new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV);
        if (new_val < 0)
                return new_val;
 
@@ -936,7 +934,7 @@ static struct regulator_desc regulators[] = {
 };
 
 #ifdef CONFIG_OF
-static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev,
                        struct max8997_platform_data *pdata,
                        struct device_node *pmic_np)
 {
@@ -946,7 +944,7 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
                gpio = of_get_named_gpio(pmic_np,
                                        "max8997,pmic-buck125-dvs-gpios", i);
                if (!gpio_is_valid(gpio)) {
-                       dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+                       dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio);
                        return -EINVAL;
                }
                pdata->buck125_gpios[i] = gpio;
@@ -954,22 +952,23 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
        return 0;
 }
 
-static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max8997_platform_data *pdata)
 {
+       struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct device_node *pmic_np, *regulators_np, *reg_np;
        struct max8997_regulator_data *rdata;
        unsigned int i, dvs_voltage_nr = 1, ret;
 
        pmic_np = iodev->dev->of_node;
        if (!pmic_np) {
-               dev_err(iodev->dev, "could not find pmic sub-node\n");
+               dev_err(&pdev->dev, "could not find pmic sub-node\n");
                return -ENODEV;
        }
 
        regulators_np = of_find_node_by_name(pmic_np, "regulators");
        if (!regulators_np) {
-               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               dev_err(&pdev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
        }
 
@@ -978,11 +977,10 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
        for_each_child_of_node(regulators_np, reg_np)
                pdata->num_regulators++;
 
-       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
                                pdata->num_regulators, GFP_KERNEL);
        if (!rdata) {
-               dev_err(iodev->dev, "could not allocate memory for "
-                                               "regulator data\n");
+               dev_err(&pdev->dev, "could not allocate memory for regulator data\n");
                return -ENOMEM;
        }
 
@@ -993,14 +991,14 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
                                break;
 
                if (i == ARRAY_SIZE(regulators)) {
-                       dev_warn(iodev->dev, "don't know how to configure "
-                               "regulator %s\n", reg_np->name);
+                       dev_warn(&pdev->dev, "don't know how to configure regulator %s\n",
+                                reg_np->name);
                        continue;
                }
 
                rdata->id = i;
-               rdata->initdata = of_get_regulator_init_data(
-                                               iodev->dev, reg_np);
+               rdata->initdata = of_get_regulator_init_data(&pdev->dev,
+                                                            reg_np);
                rdata->reg_node = reg_np;
                rdata++;
        }
@@ -1016,7 +1014,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
 
        if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
                                                pdata->buck5_gpiodvs) {
-               ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+               ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np);
                if (ret)
                        return -EINVAL;
 
@@ -1027,8 +1025,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
                } else {
                        if (pdata->buck125_default_idx >= 8) {
                                pdata->buck125_default_idx = 0;
-                               dev_info(iodev->dev, "invalid value for "
-                               "default dvs index, using 0 instead\n");
+                               dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n");
                        }
                }
 
@@ -1042,28 +1039,28 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck1-dvs-voltage",
                                pdata->buck1_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck1 voltages not specified\n");
+               dev_err(&pdev->dev, "buck1 voltages not specified\n");
                return -EINVAL;
        }
 
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck2-dvs-voltage",
                                pdata->buck2_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck2 voltages not specified\n");
+               dev_err(&pdev->dev, "buck2 voltages not specified\n");
                return -EINVAL;
        }
 
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck5-dvs-voltage",
                                pdata->buck5_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck5 voltages not specified\n");
+               dev_err(&pdev->dev, "buck5 voltages not specified\n");
                return -EINVAL;
        }
 
        return 0;
 }
 #else
-static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max8997_platform_data *pdata)
 {
        return 0;
@@ -1087,7 +1084,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
        }
 
        if (iodev->dev->of_node) {
-               ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+               ret = max8997_pmic_dt_parse_pdata(pdev, pdata);
                if (ret)
                        return ret;
        }
@@ -1123,8 +1120,8 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                max8997->buck1_vol[i] = ret =
                        max8997_get_voltage_proper_val(
                                        &buck1245_voltage_map_desc,
-                                       pdata->buck1_voltage[i] / 1000,
-                                       pdata->buck1_voltage[i] / 1000 +
+                                       pdata->buck1_voltage[i],
+                                       pdata->buck1_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
                        goto err_out;
@@ -1132,8 +1129,8 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                max8997->buck2_vol[i] = ret =
                        max8997_get_voltage_proper_val(
                                        &buck1245_voltage_map_desc,
-                                       pdata->buck2_voltage[i] / 1000,
-                                       pdata->buck2_voltage[i] / 1000 +
+                                       pdata->buck2_voltage[i],
+                                       pdata->buck2_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
                        goto err_out;
@@ -1141,8 +1138,8 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                max8997->buck5_vol[i] = ret =
                        max8997_get_voltage_proper_val(
                                        &buck1245_voltage_map_desc,
-                                       pdata->buck5_voltage[i] / 1000,
-                                       pdata->buck5_voltage[i] / 1000 +
+                                       pdata->buck5_voltage[i],
+                                       pdata->buck5_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
                        goto err_out;
index b821d08eb64ae84b643f2cfe93cd0764738d21c9..0a8dd1cbee6fffa705b5a1bd1aa7528301ca9b96 100644 (file)
@@ -51,39 +51,39 @@ struct voltage_map_desc {
        int step;
 };
 
-/* Voltage maps */
+/* Voltage maps in uV*/
 static const struct voltage_map_desc ldo23_voltage_map_desc = {
-       .min = 800,     .step = 50,     .max = 1300,
+       .min = 800000,  .step = 50000,  .max = 1300000,
 };
 static const struct voltage_map_desc ldo456711_voltage_map_desc = {
-       .min = 1600,    .step = 100,    .max = 3600,
+       .min = 1600000, .step = 100000, .max = 3600000,
 };
 static const struct voltage_map_desc ldo8_voltage_map_desc = {
-       .min = 3000,    .step = 100,    .max = 3600,
+       .min = 3000000, .step = 100000, .max = 3600000,
 };
 static const struct voltage_map_desc ldo9_voltage_map_desc = {
-       .min = 2800,    .step = 100,    .max = 3100,
+       .min = 2800000, .step = 100000, .max = 3100000,
 };
 static const struct voltage_map_desc ldo10_voltage_map_desc = {
-       .min = 950,     .step = 50,     .max = 1300,
+       .min = 950000,  .step = 50000,  .max = 1300000,
 };
 static const struct voltage_map_desc ldo1213_voltage_map_desc = {
-       .min = 800,     .step = 100,    .max = 3300,
+       .min = 800000,  .step = 100000, .max = 3300000,
 };
 static const struct voltage_map_desc ldo1415_voltage_map_desc = {
-       .min = 1200,    .step = 100,    .max = 3300,
+       .min = 1200000, .step = 100000, .max = 3300000,
 };
 static const struct voltage_map_desc ldo1617_voltage_map_desc = {
-       .min = 1600,    .step = 100,    .max = 3600,
+       .min = 1600000, .step = 100000, .max = 3600000,
 };
 static const struct voltage_map_desc buck12_voltage_map_desc = {
-       .min = 750,     .step = 25,     .max = 1525,
+       .min = 750000,  .step = 25000,  .max = 1525000,
 };
 static const struct voltage_map_desc buck3_voltage_map_desc = {
-       .min = 1600,    .step = 100,    .max = 3600,
+       .min = 1600000, .step = 100000, .max = 3600000,
 };
 static const struct voltage_map_desc buck4_voltage_map_desc = {
-       .min = 800,     .step = 100,    .max = 2300,
+       .min = 800000,  .step = 100000, .max = 2300000,
 };
 
 static const struct voltage_map_desc *ldo_voltage_map[] = {
@@ -445,9 +445,9 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
        if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP))
                return 0;
 
-       difference = (new_selector - old_selector) * desc->step;
+       difference = (new_selector - old_selector) * desc->step / 1000;
        if (difference > 0)
-               return difference / ((val & 0x0f) + 1);
+               return DIV_ROUND_UP(difference, (val & 0x0f) + 1);
 
        return 0;
 }
@@ -702,7 +702,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck1_voltage1 / 1000))
+                      < pdata->buck1_voltage1)
                        i++;
                max8998->buck1_vol[0] = i;
                ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
@@ -713,7 +713,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck1_voltage2 / 1000))
+                      < pdata->buck1_voltage2)
                        i++;
 
                max8998->buck1_vol[1] = i;
@@ -725,7 +725,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck1_voltage3 / 1000))
+                      < pdata->buck1_voltage3)
                        i++;
 
                max8998->buck1_vol[2] = i;
@@ -737,7 +737,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck1_voltage4 / 1000))
+                      < pdata->buck1_voltage4)
                        i++;
 
                max8998->buck1_vol[3] = i;
@@ -763,7 +763,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck2_voltage1 / 1000))
+                      < pdata->buck2_voltage1)
                        i++;
                max8998->buck2_vol[0] = i;
                ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
@@ -774,7 +774,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                i = 0;
                while (buck12_voltage_map_desc.min +
                       buck12_voltage_map_desc.step*i
-                      < (pdata->buck2_voltage2 / 1000))
+                      < pdata->buck2_voltage2)
                        i++;
                max8998->buck2_vol[1] = i;
                ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
@@ -792,8 +792,8 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                        int count = (desc->max - desc->min) / desc->step + 1;
 
                        regulators[index].n_voltages = count;
-                       regulators[index].min_uV = desc->min * 1000;
-                       regulators[index].uV_step = desc->step * 1000;
+                       regulators[index].min_uV = desc->min;
+                       regulators[index].uV_step = desc->step;
                }
 
                config.dev = max8998->dev;
index 6f684916fd7914450bfea4170ee884f5538ee281..66ca769287ab3427aa9ac8695ad5a67ca5dc77c3 100644 (file)
@@ -120,6 +120,12 @@ int of_regulator_match(struct device *dev, struct device_node *node,
        if (!dev || !node)
                return -EINVAL;
 
+       for (i = 0; i < num_matches; i++) {
+               struct of_regulator_match *match = &matches[i];
+               match->init_data = NULL;
+               match->of_node = NULL;
+       }
+
        for_each_child_of_node(node, child) {
                name = of_get_property(child,
                                        "regulator-compatible", NULL);
index e915629a25cf64ed660e9ac9f2b2112b1ea228e9..c9e912f583bc57485e09909bff01b58af315d2cb 100644 (file)
@@ -806,7 +806,7 @@ static int palmas_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+static struct of_device_id of_palmas_match_tbl[] = {
        { .compatible = "ti,palmas-pmic", },
        { /* end */ }
 };
index bd062a2ffbe235cb9e4c4636b59b8676738676e8..cd9ea2ea1826bc5e6b40de856b4884637eae3103 100644 (file)
@@ -174,9 +174,9 @@ static struct regulator_ops s2mps11_buck_ops = {
        .min_uV         = S2MPS11_BUCK_MIN2,                    \
        .uV_step        = S2MPS11_BUCK_STEP2,                   \
        .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
-       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_reg       = S2MPS11_REG_B10CTRL2,                 \
        .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
-       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_reg     = S2MPS11_REG_B10CTRL1,                 \
        .enable_mask    = S2MPS11_ENABLE_MASK                   \
 }
 
index 9f991f2c525af531ec0b5450523bb2e0e75a5b54..33b65c9ad5d5be4da31d725678faeb7c5dc2b031 100644 (file)
@@ -214,7 +214,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
        int ret, reg;
        int mask = 0xc0, enable_ctrl;
-       u8 val;
+       unsigned int val;
 
        ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
        if (ret == -EINVAL)
@@ -306,7 +306,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev)
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
        int reg, mask, ret;
        int reg_id = rdev_get_id(rdev);
-       u8 val;
+       unsigned int val;
 
        ret = s5m8767_get_voltage_register(rdev, &reg);
        if (ret)
index 73dce76641265590179cb2440e75ad71ffd722d0..df395187c06301114c144305b19cdd29dedb5a22 100644 (file)
@@ -305,8 +305,8 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
        if (!regs)
                return NULL;
 
-       count = of_regulator_match(pdev->dev.parent, regs,
-                               reg_matches, TPS65217_NUM_REGULATOR);
+       count = of_regulator_match(&pdev->dev, regs, reg_matches,
+                                  TPS65217_NUM_REGULATOR);
        of_node_put(regs);
        if ((count < 0) || (count > TPS65217_NUM_REGULATOR))
                return NULL;
index 59c3770fa77dbe5b77ae1b3c96c1e105cae8f58e..b0e4c0bc85c319c9265e12ab193a0aec86156a64 100644 (file)
@@ -998,7 +998,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
                return NULL;
        }
 
-       ret = of_regulator_match(pdev->dev.parent, regulators, matches, count);
+       ret = of_regulator_match(&pdev->dev, regulators, matches, count);
        if (ret < 0) {
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
                        ret);
index b15d711bc8c66634c9792c26e15885e055aabe11..9019d0e7ecb6ad9868fa96e23fa0f77a1275fc75 100644 (file)
@@ -728,7 +728,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
                        }
                }
                rdev = regulator_register(&ri->rinfo->desc, &config);
-               if (IS_ERR_OR_NULL(rdev)) {
+               if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
                                "register regulator failed %s\n",
                                        ri->rinfo->desc.name);
index 493c8c6a241f41b1820786b993b342816002bc1c..74508cc62d67baafcc39fb3face73f1e7a810d90 100644 (file)
@@ -1064,7 +1064,7 @@ static u8 twl_get_smps_mult(void)
 #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
 #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
 
-static const struct of_device_id twl_of_match[] __devinitconst = {
+static const struct of_device_id twl_of_match[] = {
        TWL4030_OF_MATCH("ti,twl4030-vaux1", VAUX1),
        TWL4030_OF_MATCH("ti,twl4030-vaux2", VAUX2_4030),
        TWL4030_OF_MATCH("ti,twl5030-vaux2", VAUX2),
index 32c289c2ba136a732e1cb508f06360fa5ae28c48..0e396c155b3ba60d0d202af60f9aa34f84afd5bf 100644 (file)
@@ -179,7 +179,7 @@ static struct rproc_ops omap_rproc_ops = {
        .kick           = omap_rproc_kick,
 };
 
-static int __devinit omap_rproc_probe(struct platform_device *pdev)
+static int omap_rproc_probe(struct platform_device *pdev)
 {
        struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
        struct omap_rproc *oproc;
@@ -213,7 +213,7 @@ free_rproc:
        return ret;
 }
 
-static int __devexit omap_rproc_remove(struct platform_device *pdev)
+static int omap_rproc_remove(struct platform_device *pdev)
 {
        struct rproc *rproc = platform_get_drvdata(pdev);
 
@@ -225,7 +225,7 @@ static int __devexit omap_rproc_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_rproc_driver = {
        .probe = omap_rproc_probe,
-       .remove = __devexit_p(omap_rproc_remove),
+       .remove = omap_rproc_remove,
        .driver = {
                .name = "omap-rproc",
                .owner = THIS_MODULE,
index 027096fe6a124dc9edde55da90517c5daac38747..f1e323924f1272ca3eea8546bdefb26613837559 100644 (file)
@@ -1022,7 +1022,7 @@ static int rpmsg_remove_device(struct device *dev, void *data)
        return 0;
 }
 
-static void __devexit rpmsg_remove(struct virtio_device *vdev)
+static void rpmsg_remove(struct virtio_device *vdev)
 {
        struct virtproc_info *vrp = vdev->priv;
        int ret;
@@ -1063,7 +1063,7 @@ static struct virtio_driver virtio_ipc_driver = {
        .driver.owner   = THIS_MODULE,
        .id_table       = id_table,
        .probe          = rpmsg_probe,
-       .remove         = __devexit_p(rpmsg_remove),
+       .remove         = rpmsg_remove,
 };
 
 static int __init rpmsg_init(void)
index d0cea02b5dfc5b58ca4ee3751f1c5737b221739d..5e44eaabf45753f11cbfecb87d72627d56985606 100644 (file)
@@ -20,14 +20,24 @@ if RTC_CLASS
 config RTC_HCTOSYS
        bool "Set system time from RTC on startup and resume"
        default y
+       depends on !ALWAYS_USE_PERSISTENT_CLOCK
        help
          If you say yes here, the system time (wall clock) will be set using
          the value read from a specified RTC device. This is useful to avoid
          unnecessary fsck runs at boot time, and to network better.
 
+config RTC_SYSTOHC
+       bool "Set the RTC time based on NTP synchronization"
+       default y
+       depends on !ALWAYS_USE_PERSISTENT_CLOCK
+       help
+         If you say yes here, the system time (wall clock) will be stored
+         in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11
+         minutes if userspace reports synchronized NTP status.
+
 config RTC_HCTOSYS_DEVICE
        string "RTC used to set the system time"
-       depends on RTC_HCTOSYS = y
+       depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y
        default "rtc0"
        help
          The RTC device that will be used to (re)initialize the system
@@ -352,6 +362,14 @@ config RTC_DRV_TWL4030
          This driver can also be built as a module. If so, the module
          will be called rtc-twl.
 
+config RTC_DRV_TPS6586X
+       tristate "TI TPS6586X RTC driver"
+       depends on MFD_TPS6586X
+       help
+         TI Power Managment IC TPS6586X supports RTC functionality
+         along with alarm. This driver supports the RTC driver for
+         the TPS6586X RTC module.
+
 config RTC_DRV_TPS65910
        tristate "TI TPS65910 RTC driver"
        depends on RTC_CLASS && MFD_TPS65910
index c3f62c80dc062687b435f24cc3dcbf8d4fd89794..ec2988b00a44cb8aa4f271f9d79d5c7a6c9551a8 100644 (file)
@@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG)     := -DDEBUG
 
 obj-$(CONFIG_RTC_LIB)          += rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)      += hctosys.o
+obj-$(CONFIG_RTC_SYSTOHC)      += systohc.o
 obj-$(CONFIG_RTC_CLASS)                += rtc-core.o
 rtc-core-y                     := class.o interface.o
 
@@ -111,6 +112,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
 obj-$(CONFIG_RTC_DRV_TEST)     += rtc-test.o
 obj-$(CONFIG_RTC_DRV_TILE)     += rtc-tile.o
 obj-$(CONFIG_RTC_DRV_TWL4030)  += rtc-twl.o
+obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
 obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
 obj-$(CONFIG_RTC_DRV_TX4939)   += rtc-tx4939.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
index f8a0aab218cbcd2777ea93b9e74aa96494e729fe..26388f1825941329b28168a36b338c7405a6a4f7 100644 (file)
@@ -50,6 +50,10 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg)
        struct rtc_device       *rtc = to_rtc_device(dev);
        struct rtc_time         tm;
        struct timespec         delta, delta_delta;
+
+       if (has_persistent_clock())
+               return 0;
+
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
                return 0;
 
@@ -88,6 +92,9 @@ static int rtc_resume(struct device *dev)
        struct timespec         new_system, new_rtc;
        struct timespec         sleep_time;
 
+       if (has_persistent_clock())
+               return 0;
+
        rtc_hctosys_ret = -ENODEV;
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
                return 0;
@@ -244,7 +251,6 @@ void rtc_device_unregister(struct rtc_device *rtc)
                rtc_proc_del_device(rtc);
                device_unregister(&rtc->dev);
                rtc->ops = NULL;
-               ida_simple_remove(&rtc_ida, rtc->id);
                mutex_unlock(&rtc->ops_lock);
                put_device(&rtc->dev);
        }
index 6367984e05653f8a3b6f7b24040123f31d7ade15..63b17ebe90e8c2c3f568160b95090343cfbb46d8 100644 (file)
@@ -248,7 +248,7 @@ static int pm80x_rtc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);
 
-static int __devinit pm80x_rtc_probe(struct platform_device *pdev)
+static int pm80x_rtc_probe(struct platform_device *pdev)
 {
        struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm80x_platform_data *pm80x_pdata;
@@ -342,7 +342,7 @@ out:
        return ret;
 }
 
-static int __devexit pm80x_rtc_remove(struct platform_device *pdev)
+static int pm80x_rtc_remove(struct platform_device *pdev)
 {
        struct pm80x_rtc_info *info = platform_get_drvdata(pdev);
        platform_set_drvdata(pdev, NULL);
@@ -358,7 +358,7 @@ static struct platform_driver pm80x_rtc_driver = {
                   .pm = &pm80x_rtc_pm_ops,
                   },
        .probe = pm80x_rtc_probe,
-       .remove = __devexit_p(pm80x_rtc_remove),
+       .remove = pm80x_rtc_remove,
 };
 
 module_platform_driver(pm80x_rtc_driver);
index de9e854b326ac9a06b0c2f3fea0c19b9bf78980e..f663746f46039dba5dfde86f50ad9c31f11cca31 100644 (file)
@@ -286,8 +286,8 @@ out:
 #endif
 
 #ifdef CONFIG_OF
-static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev,
-                                       struct pm860x_rtc_info *info)
+static int pm860x_rtc_dt_init(struct platform_device *pdev,
+                             struct pm860x_rtc_info *info)
 {
        struct device_node *np = pdev->dev.parent->of_node;
        int ret;
@@ -307,7 +307,7 @@ static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev,
 #define pm860x_rtc_dt_init(x, y)       (-1)
 #endif
 
-static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
+static int pm860x_rtc_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm860x_rtc_pdata *pdata = NULL;
@@ -412,7 +412,7 @@ out:
        return ret;
 }
 
-static int __devexit pm860x_rtc_remove(struct platform_device *pdev)
+static int pm860x_rtc_remove(struct platform_device *pdev)
 {
        struct pm860x_rtc_info *info = platform_get_drvdata(pdev);
 
@@ -459,7 +459,7 @@ static struct platform_driver pm860x_rtc_driver = {
                .pm     = &pm860x_rtc_pm_ops,
        },
        .probe          = pm860x_rtc_probe,
-       .remove         = __devexit_p(pm860x_rtc_remove),
+       .remove         = pm860x_rtc_remove,
 };
 
 module_platform_driver(pm860x_rtc_driver);
index 2e5970fe9eebccc97fc385460d9e0c365f0515e0..57cde2b061e6b9878c5ccf8052719d5e801b02ab 100644 (file)
@@ -389,7 +389,7 @@ static const struct rtc_class_ops ab8500_rtc_ops = {
        .alarm_irq_enable       = ab8500_rtc_irq_enable,
 };
 
-static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
+static int ab8500_rtc_probe(struct platform_device *pdev)
 {
        int err;
        struct rtc_device *rtc;
@@ -448,7 +448,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
+static int ab8500_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata(pdev);
        int irq = platform_get_irq_byname(pdev, "ALARM");
@@ -468,7 +468,7 @@ static struct platform_driver ab8500_rtc_driver = {
                .owner = THIS_MODULE,
        },
        .probe  = ab8500_rtc_probe,
-       .remove = __devexit_p(ab8500_rtc_remove),
+       .remove = ab8500_rtc_remove,
 };
 
 module_platform_driver(ab8500_rtc_driver);
index e981798e9a9b55707d5326b576abc6af5a207e55..39cfd2ee0042528b4efb34ef4aae5776178cbd16 100644 (file)
@@ -289,7 +289,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 /*
  * Initialize and install RTC driver
  */
-static int __devinit at91_rtc_probe(struct platform_device *pdev)
+static int at91_rtc_probe(struct platform_device *pdev)
 {
        struct resource *r, *r_gpbr;
        struct sam9_rtc *rtc;
@@ -387,7 +387,7 @@ fail:
 /*
  * Disable and remove the RTC driver
  */
-static int __devexit at91_rtc_remove(struct platform_device *pdev)
+static int at91_rtc_remove(struct platform_device *pdev)
 {
        struct sam9_rtc *rtc = platform_get_drvdata(pdev);
        u32             mr = rtt_readl(rtc, MR);
@@ -463,7 +463,7 @@ static int at91_rtc_resume(struct platform_device *pdev)
 
 static struct platform_driver at91_rtc_driver = {
        .probe          = at91_rtc_probe,
-       .remove         = __devexit_p(at91_rtc_remove),
+       .remove         = at91_rtc_remove,
        .shutdown       = at91_rtc_shutdown,
        .suspend        = at91_rtc_suspend,
        .resume         = at91_rtc_resume,
index 979ed0406ce9141557bb4eaba23daca9b1fb1f32..b309da4ec7455207af724a39dc1d38d3cec0ad30 100644 (file)
@@ -62,7 +62,7 @@ static struct rtc_class_ops au1xtoy_rtc_ops = {
        .set_time       = au1xtoy_rtc_set_time,
 };
 
-static int __devinit au1xtoy_rtc_probe(struct platform_device *pdev)
+static int au1xtoy_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtcdev;
        unsigned long t;
@@ -116,7 +116,7 @@ out_err:
        return ret;
 }
 
-static int __devexit au1xtoy_rtc_remove(struct platform_device *pdev)
+static int au1xtoy_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtcdev = platform_get_drvdata(pdev);
 
@@ -131,7 +131,7 @@ static struct platform_driver au1xrtc_driver = {
                .name   = "rtc-au1xxx",
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(au1xtoy_rtc_remove),
+       .remove         = au1xtoy_rtc_remove,
 };
 
 static int __init au1xtoy_rtc_init(void)
index abfc1a0c07d9cfb0c6e6f7c46249c1283d10afca..4ec614b0954d8f8c9b67ee68626b91b299c55cb2 100644 (file)
@@ -342,7 +342,7 @@ static struct rtc_class_ops bfin_rtc_ops = {
        .alarm_irq_enable = bfin_rtc_alarm_irq_enable,
 };
 
-static int __devinit bfin_rtc_probe(struct platform_device *pdev)
+static int bfin_rtc_probe(struct platform_device *pdev)
 {
        struct bfin_rtc *rtc;
        struct device *dev = &pdev->dev;
@@ -388,7 +388,7 @@ err:
        return ret;
 }
 
-static int __devexit bfin_rtc_remove(struct platform_device *pdev)
+static int bfin_rtc_remove(struct platform_device *pdev)
 {
        struct bfin_rtc *rtc = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -451,7 +451,7 @@ static struct platform_driver bfin_rtc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = bfin_rtc_probe,
-       .remove         = __devexit_p(bfin_rtc_remove),
+       .remove         = bfin_rtc_remove,
        .suspend        = bfin_rtc_suspend,
        .resume         = bfin_rtc_resume,
 };
index f090159dce4a77005d8fc6a314b7de106877c6cb..036cb89f81882c5864e5b0cf43b8e995d4d63d1a 100644 (file)
@@ -163,7 +163,7 @@ static int bq32k_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit bq32k_remove(struct i2c_client *client)
+static int bq32k_remove(struct i2c_client *client)
 {
        struct rtc_device *rtc = i2c_get_clientdata(client);
 
@@ -183,7 +183,7 @@ static struct i2c_driver bq32k_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = bq32k_probe,
-       .remove         = __devexit_p(bq32k_remove),
+       .remove         = bq32k_remove,
        .id_table       = bq32k_id,
 };
 
index bf612ef229417730a8146f62d3a9270daba67d28..693be71b5b188be04f64219d862c70b5d1b2a227 100644 (file)
@@ -140,7 +140,7 @@ static const struct rtc_class_ops bq4802_ops = {
        .set_time       = bq4802_set_time,
 };
 
-static int __devinit bq4802_probe(struct platform_device *pdev)
+static int bq4802_probe(struct platform_device *pdev)
 {
        struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL);
        int err = -ENOMEM;
@@ -191,7 +191,7 @@ out_free:
        goto out;
 }
 
-static int __devexit bq4802_remove(struct platform_device *pdev)
+static int bq4802_remove(struct platform_device *pdev)
 {
        struct bq4802 *p = platform_get_drvdata(pdev);
 
@@ -215,7 +215,7 @@ static struct platform_driver bq4802_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = bq4802_probe,
-       .remove         = __devexit_p(bq4802_remove),
+       .remove         = bq4802_remove,
 };
 
 module_platform_driver(bq4802_driver);
index 4267789ca9959413e90df5ea053154e07481d3ce..16630aa87f45d181d37576fa2e71576196f1da53 100644 (file)
@@ -947,8 +947,7 @@ static void rtc_wake_off(struct device *dev)
  */
 static struct cmos_rtc_board_info acpi_rtc_info;
 
-static void __devinit
-cmos_wake_setup(struct device *dev)
+static void cmos_wake_setup(struct device *dev)
 {
        if (acpi_disabled)
                return;
@@ -980,8 +979,7 @@ cmos_wake_setup(struct device *dev)
 
 #else
 
-static void __devinit
-cmos_wake_setup(struct device *dev)
+static void cmos_wake_setup(struct device *dev)
 {
 }
 
@@ -991,8 +989,7 @@ cmos_wake_setup(struct device *dev)
 
 #include <linux/pnp.h>
 
-static int __devinit
-cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
+static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        cmos_wake_setup(&pnp->dev);
 
index 78070255bd3f834d7aa8efa937e5ca552c07f4d1..60b826e520e2e2c2c04a8d18328853a27d5c81b0 100644 (file)
@@ -228,7 +228,7 @@ static const struct rtc_class_ops da9052_rtc_ops = {
        .alarm_irq_enable = da9052_rtc_alarm_irq_enable,
 };
 
-static int __devinit da9052_rtc_probe(struct platform_device *pdev)
+static int da9052_rtc_probe(struct platform_device *pdev)
 {
        struct da9052_rtc *rtc;
        int ret;
@@ -262,7 +262,7 @@ err_free_irq:
        return ret;
 }
 
-static int __devexit da9052_rtc_remove(struct platform_device *pdev)
+static int da9052_rtc_remove(struct platform_device *pdev)
 {
        struct da9052_rtc *rtc = pdev->dev.platform_data;
 
@@ -275,7 +275,7 @@ static int __devexit da9052_rtc_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_rtc_driver = {
        .probe  = da9052_rtc_probe,
-       .remove = __devexit_p(da9052_rtc_remove),
+       .remove = da9052_rtc_remove,
        .driver = {
                .name   = "da9052-rtc",
                .owner  = THIS_MODULE,
index 96bafc5c3bf87c2426892cdc0ffa46756e7baf36..8f0dcfedb83cdfb9c613083574e8e591826beaf5 100644 (file)
@@ -227,7 +227,7 @@ static const struct rtc_class_ops da9055_rtc_ops = {
        .alarm_irq_enable = da9055_rtc_alarm_irq_enable,
 };
 
-static int __init da9055_rtc_device_init(struct da9055 *da9055,
+static int da9055_rtc_device_init(struct da9055 *da9055,
                                        struct da9055_pdata *pdata)
 {
        int ret;
index 07cd03eae60605f1c993ce585182ad0dd5f33c96..5f7982f7c1b5ab6ff589f8ce535c2cb10bf65afa 100644 (file)
@@ -567,7 +567,7 @@ fail2:
        return ret;
 }
 
-static int __devexit davinci_rtc_remove(struct platform_device *pdev)
+static int davinci_rtc_remove(struct platform_device *pdev)
 {
        struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev);
 
@@ -589,7 +589,7 @@ static int __devexit davinci_rtc_remove(struct platform_device *pdev)
 
 static struct platform_driver davinci_rtc_driver = {
        .probe          = davinci_rtc_probe,
-       .remove         = __devexit_p(davinci_rtc_remove),
+       .remove         = davinci_rtc_remove,
        .driver         = {
                .name = "rtc_davinci",
                .owner = THIS_MODULE,
index d4457afcba8910892f85e90fa72309104fd73db5..b2ed2c94b081b12f88a2e7f43e3541103a3c72ca 100644 (file)
@@ -123,7 +123,7 @@ static struct rtc_class_ops dm355evm_rtc_ops = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)
+static int dm355evm_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
 
@@ -139,7 +139,7 @@ static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)
+static int dm355evm_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
@@ -154,7 +154,7 @@ static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)
  */
 static struct platform_driver rtc_dm355evm_driver = {
        .probe          = dm355evm_rtc_probe,
-       .remove         = __devexit_p(dm355evm_rtc_remove),
+       .remove         = dm355evm_rtc_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "rtc-dm355evm",
index 990c3ff489bf1fff947c854d747121b16c0de36c..d989412a348ab99911dbc0bd6889e5ae27ffc923 100644 (file)
@@ -329,7 +329,7 @@ static const struct rtc_class_ops ds1286_ops = {
        .alarm_irq_enable = ds1286_alarm_irq_enable,
 };
 
-static int __devinit ds1286_probe(struct platform_device *pdev)
+static int ds1286_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -376,7 +376,7 @@ out:
        return ret;
 }
 
-static int __devexit ds1286_remove(struct platform_device *pdev)
+static int ds1286_remove(struct platform_device *pdev)
 {
        struct ds1286_priv *priv = platform_get_drvdata(pdev);
 
@@ -393,7 +393,7 @@ static struct platform_driver ds1286_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ds1286_probe,
-       .remove         = __devexit_p(ds1286_remove),
+       .remove         = ds1286_remove,
 };
 
 module_platform_driver(ds1286_platform_driver);
index f0d63892264410b23e19753885868cca81071eda..fdbcdb289d605d21e26f7bb0006db8bd7709bbf4 100644 (file)
@@ -234,7 +234,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ds1302_rtc_remove(struct platform_device *pdev)
+static int ds1302_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
@@ -249,7 +249,7 @@ static struct platform_driver ds1302_platform_driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(ds1302_rtc_remove),
+       .remove         = ds1302_rtc_remove,
 };
 
 static int __init ds1302_rtc_init(void)
index 686a865913e19c9f1bbc896074aa253e6da5b3f0..d578773f5ce21c18f0660114ad72fe5afd646f9b 100644 (file)
@@ -601,7 +601,7 @@ static struct bin_attribute nvram = {
  * Interface to SPI stack
  */
 
-static int __devinit ds1305_probe(struct spi_device *spi)
+static int ds1305_probe(struct spi_device *spi)
 {
        struct ds1305                   *ds1305;
        int                             status;
@@ -787,7 +787,7 @@ fail0:
        return status;
 }
 
-static int __devexit ds1305_remove(struct spi_device *spi)
+static int ds1305_remove(struct spi_device *spi)
 {
        struct ds1305 *ds1305 = spi_get_drvdata(spi);
 
@@ -810,7 +810,7 @@ static struct spi_driver ds1305_driver = {
        .driver.name    = "rtc-ds1305",
        .driver.owner   = THIS_MODULE,
        .probe          = ds1305_probe,
-       .remove         = __devexit_p(ds1305_remove),
+       .remove         = ds1305_remove,
        /* REVISIT add suspend/resume */
 };
 
index 836710ce750e703ae06f8761aca9d00b64bd84f9..e0d0ba4de03f34d84b7454b7201050ee66e0317a 100644 (file)
@@ -617,8 +617,8 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit ds1307_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int ds1307_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct ds1307           *ds1307;
        int                     err = -ENODEV;
@@ -938,7 +938,7 @@ exit_free:
        return err;
 }
 
-static int __devexit ds1307_remove(struct i2c_client *client)
+static int ds1307_remove(struct i2c_client *client)
 {
        struct ds1307 *ds1307 = i2c_get_clientdata(client);
 
@@ -963,7 +963,7 @@ static struct i2c_driver ds1307_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ds1307_probe,
-       .remove         = __devexit_p(ds1307_remove),
+       .remove         = ds1307_remove,
        .id_table       = ds1307_id,
 };
 
index 966316088b7f8979e9b7e2cd3eff7f52c703c080..fef76868aae069e1112c16619c502dd30fdc967a 100644 (file)
@@ -391,7 +391,7 @@ out_free:
        return ret;
 }
 
-static int __devexit ds1374_remove(struct i2c_client *client)
+static int ds1374_remove(struct i2c_client *client)
 {
        struct ds1374 *ds1374 = i2c_get_clientdata(client);
 
@@ -442,7 +442,7 @@ static struct i2c_driver ds1374_driver = {
                .pm = DS1374_PM,
        },
        .probe = ds1374_probe,
-       .remove = __devexit_p(ds1374_remove),
+       .remove = ds1374_remove,
        .id_table = ds1374_id,
 };
 
index b0a99e1b25be96684d821351312da7aa0e025c8b..f994257981a043569cbb8ac88a0a090d7c597458 100644 (file)
@@ -121,7 +121,7 @@ static const struct rtc_class_ops ds1390_rtc_ops = {
        .set_time       = ds1390_set_time,
 };
 
-static int __devinit ds1390_probe(struct spi_device *spi)
+static int ds1390_probe(struct spi_device *spi)
 {
        unsigned char tmp;
        struct ds1390 *chip;
@@ -156,7 +156,7 @@ static int __devinit ds1390_probe(struct spi_device *spi)
        return res;
 }
 
-static int __devexit ds1390_remove(struct spi_device *spi)
+static int ds1390_remove(struct spi_device *spi)
 {
        struct ds1390 *chip = spi_get_drvdata(spi);
 
@@ -172,7 +172,7 @@ static struct spi_driver ds1390_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = ds1390_probe,
-       .remove = __devexit_p(ds1390_remove),
+       .remove = ds1390_remove,
 };
 
 module_spi_driver(ds1390_driver);
index 1f675f5294f5844c6ef04ee33bc594c754a821c8..6a3fcfe3b0e7379f88d8901a4d68b9c38c9261f9 100644 (file)
@@ -476,8 +476,7 @@ static struct bin_attribute ds1511_nvram_attr = {
        .write = ds1511_nvram_write,
 };
 
- static int __devinit
-ds1511_rtc_probe(struct platform_device *pdev)
+static int ds1511_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -551,8 +550,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
        return ret;
 }
 
- static int __devexit
-ds1511_rtc_remove(struct platform_device *pdev)
+static int ds1511_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
@@ -573,7 +571,7 @@ MODULE_ALIAS("platform:ds1511");
 
 static struct platform_driver ds1511_rtc_driver = {
        .probe          = ds1511_rtc_probe,
-       .remove         = __devexit_p(ds1511_rtc_remove),
+       .remove         = ds1511_rtc_remove,
        .driver         = {
                .name   = "ds1511",
                .owner  = THIS_MODULE,
index 6ccedbbf923c5ce0cb183504bf64968f06869609..25ce0621ade994bd5a070ad16ac30c50291d2a6f 100644 (file)
@@ -276,7 +276,7 @@ static struct bin_attribute ds1553_nvram_attr = {
        .write = ds1553_nvram_write,
 };
 
-static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
+static int ds1553_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -338,7 +338,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
+static int ds1553_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
@@ -354,7 +354,7 @@ MODULE_ALIAS("platform:rtc-ds1553");
 
 static struct platform_driver ds1553_rtc_driver = {
        .probe          = ds1553_rtc_probe,
-       .remove         = __devexit_p(ds1553_rtc_remove),
+       .remove         = ds1553_rtc_remove,
        .driver         = {
                .name   = "rtc-ds1553",
                .owner  = THIS_MODULE,
index 76112667c5078103c8bc4f64dd1b30201a5f1fde..609c870e2cc5b88cb243255e651aed4ec6d1b253 100644 (file)
@@ -159,7 +159,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
        return count;
 }
 
-static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
+static int ds1742_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -222,7 +222,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
+static int ds1742_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
@@ -233,7 +233,7 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
 
 static struct platform_driver ds1742_rtc_driver = {
        .probe          = ds1742_rtc_probe,
-       .remove         = __devexit_p(ds1742_rtc_remove),
+       .remove         = ds1742_rtc_remove,
        .driver         = {
                .name   = "rtc-ds1742",
                .owner  = THIS_MODULE,
index e1945095814e9acd9d920f0d7fd31f242de58f97..db0ca08db315e155089003e7043268bce63fba02 100644 (file)
@@ -391,8 +391,8 @@ static const struct rtc_class_ops ds3232_rtc_ops = {
        .alarm_irq_enable = ds3232_alarm_irq_enable,
 };
 
-static int __devinit ds3232_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int ds3232_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct ds3232 *ds3232;
        int ret;
@@ -439,7 +439,7 @@ out_free:
        return ret;
 }
 
-static int __devexit ds3232_remove(struct i2c_client *client)
+static int ds3232_remove(struct i2c_client *client)
 {
        struct ds3232 *ds3232 = i2c_get_clientdata(client);
 
@@ -469,7 +469,7 @@ static struct i2c_driver ds3232_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ds3232_probe,
-       .remove = __devexit_p(ds3232_remove),
+       .remove = ds3232_remove,
        .id_table = ds3232_id,
 };
 
index fda707926f022b26646342369db135d04e32e9ec..7a4495ef1c39846eb2615cb6cb48d0377c3becc0 100644 (file)
@@ -105,7 +105,7 @@ static const struct rtc_class_ops ds3234_rtc_ops = {
        .set_time       = ds3234_set_time,
 };
 
-static int __devinit ds3234_probe(struct spi_device *spi)
+static int ds3234_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        unsigned char tmp;
@@ -156,7 +156,7 @@ static int __devinit ds3234_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit ds3234_remove(struct spi_device *spi)
+static int ds3234_remove(struct spi_device *spi)
 {
        struct rtc_device *rtc = spi_get_drvdata(spi);
 
@@ -170,7 +170,7 @@ static struct spi_driver ds3234_driver = {
                .owner  = THIS_MODULE,
        },
        .probe   = ds3234_probe,
-       .remove = __devexit_p(ds3234_remove),
+       .remove = ds3234_remove,
 };
 
 module_spi_driver(ds3234_driver);
index 9602278ff988df3affbb58b03d88dd7908508447..1a4e5e4a70cddcd4eba6fa9f304184a25532374a 100644 (file)
@@ -127,7 +127,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {
        .attrs  = ep93xx_rtc_attrs,
 };
 
-static int __devinit ep93xx_rtc_probe(struct platform_device *pdev)
+static int ep93xx_rtc_probe(struct platform_device *pdev)
 {
        struct ep93xx_rtc *ep93xx_rtc;
        struct resource *res;
@@ -174,7 +174,7 @@ exit:
        return err;
 }
 
-static int __devexit ep93xx_rtc_remove(struct platform_device *pdev)
+static int ep93xx_rtc_remove(struct platform_device *pdev)
 {
        struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
 
@@ -192,7 +192,7 @@ static struct platform_driver ep93xx_rtc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ep93xx_rtc_probe,
-       .remove         = __devexit_p(ep93xx_rtc_remove),
+       .remove         = ep93xx_rtc_remove,
 };
 
 module_platform_driver(ep93xx_rtc_driver);
index 86b6ecce99f00c58b26d08987778fb63eb149755..04e93c6597f8905b5cfeae366fc0e874f697973a 100644 (file)
@@ -361,8 +361,8 @@ static const struct rtc_class_ops fm3130_rtc_ops = {
 
 static struct i2c_driver fm3130_driver;
 
-static int __devinit fm3130_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int fm3130_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct fm3130           *fm3130;
        int                     err = -ENODEV;
@@ -546,7 +546,7 @@ exit_free:
        return err;
 }
 
-static int __devexit fm3130_remove(struct i2c_client *client)
+static int fm3130_remove(struct i2c_client *client)
 {
        struct fm3130 *fm3130 = i2c_get_clientdata(client);
 
@@ -561,7 +561,7 @@ static struct i2c_driver fm3130_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = fm3130_probe,
-       .remove         = __devexit_p(fm3130_remove),
+       .remove         = fm3130_remove,
        .id_table       = fm3130_id,
 };
 
index 18a4f0dd78a32cd9d2ff3a2c322cd22fa72113b0..75d307ab37f47ee67c1d8f3815ceced1a9ac4d20 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
 
@@ -479,7 +480,7 @@ err:
        return rc;
 }
 
-static int __devexit dryice_rtc_remove(struct platform_device *pdev)
+static int dryice_rtc_remove(struct platform_device *pdev)
 {
        struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
 
@@ -511,7 +512,7 @@ static struct platform_driver dryice_rtc_driver = {
                   .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(dryice_dt_ids),
                   },
-       .remove = __devexit_p(dryice_rtc_remove),
+       .remove = dryice_rtc_remove,
 };
 
 static int __init dryice_rtc_init(void)
index afb7cfa85ccc04ac637268ee0bba4240f05c12d3..c016ad81767a9d1be4697c267072a124f4398fc6 100644 (file)
@@ -506,6 +506,7 @@ isl1208_rtc_interrupt(int irq, void *data)
 {
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        struct i2c_client *client = data;
+       struct rtc_device *rtc = i2c_get_clientdata(client);
        int handled = 0, sr, err;
 
        /*
@@ -528,6 +529,8 @@ isl1208_rtc_interrupt(int irq, void *data)
        if (sr & ISL1208_REG_SR_ALM) {
                dev_dbg(&client->dev, "alarm!\n");
 
+               rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+
                /* Clear the alarm */
                sr &= ~ISL1208_REG_SR_ALM;
                sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
index 1224182d3eabb165892aeb3350c1914bf590c9a1..1e48686ca6d22c9b54de8394cd9dced5c80b9c20 100644 (file)
@@ -210,7 +210,7 @@ void jz4740_rtc_poweroff(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff);
 
-static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
+static int jz4740_rtc_probe(struct platform_device *pdev)
 {
        int ret;
        struct jz4740_rtc *rtc;
@@ -297,7 +297,7 @@ err_free:
        return ret;
 }
 
-static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
+static int jz4740_rtc_remove(struct platform_device *pdev)
 {
        struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
 
@@ -347,7 +347,7 @@ static const struct dev_pm_ops jz4740_pm_ops = {
 
 static struct platform_driver jz4740_rtc_driver = {
        .probe   = jz4740_rtc_probe,
-       .remove  = __devexit_p(jz4740_rtc_remove),
+       .remove  = jz4740_rtc_remove,
        .driver  = {
                .name  = "jz4740-rtc",
                .owner = THIS_MODULE,
index d5218553741ff54f871799f51b5969d74eabe85c..40a598332bacc83fa1371a385fb178a5b1b78d24 100644 (file)
@@ -197,7 +197,7 @@ static const struct rtc_class_ops lpc32xx_rtc_ops = {
        .alarm_irq_enable       = lpc32xx_rtc_alarm_irq_enable,
 };
 
-static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev)
+static int lpc32xx_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct lpc32xx_rtc *rtc;
@@ -299,7 +299,7 @@ static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev)
+static int lpc32xx_rtc_remove(struct platform_device *pdev)
 {
        struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
 
@@ -397,7 +397,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match);
 
 static struct platform_driver lpc32xx_rtc_driver = {
        .probe          = lpc32xx_rtc_probe,
-       .remove         = __devexit_p(lpc32xx_rtc_remove),
+       .remove         = lpc32xx_rtc_remove,
        .driver = {
                .name   = RTC_NAME,
                .owner  = THIS_MODULE,
index 07e81c5f8247246d9ffade03a94d92adf47c1b7d..f59b6349551affbc0c235c4366420f8070fb5f05 100644 (file)
@@ -143,7 +143,7 @@ static struct rtc_class_ops  ls1x_rtc_ops = {
        .set_time       = ls1x_rtc_set_time,
 };
 
-static int __devinit ls1x_rtc_probe(struct platform_device *pdev)
+static int ls1x_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtcdev;
        unsigned long v;
@@ -185,7 +185,7 @@ err:
        return ret;
 }
 
-static int __devexit ls1x_rtc_remove(struct platform_device *pdev)
+static int ls1x_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtcdev = platform_get_drvdata(pdev);
 
@@ -200,7 +200,7 @@ static struct platform_driver  ls1x_rtc_driver = {
                .name   = "ls1x-rtc",
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(ls1x_rtc_remove),
+       .remove         = ls1x_rtc_remove,
        .probe          = ls1x_rtc_probe,
 };
 
index efab3d48cb153314e8fdbf600da18eb6289dd5fe..49169680786e5005a4154befca38ba8dd2decdba 100644 (file)
@@ -170,7 +170,7 @@ static const struct rtc_class_ops m41t93_rtc_ops = {
 
 static struct spi_driver m41t93_driver;
 
-static int __devinit m41t93_probe(struct spi_device *spi)
+static int m41t93_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        int res;
@@ -195,7 +195,7 @@ static int __devinit m41t93_probe(struct spi_device *spi)
 }
 
 
-static int __devexit m41t93_remove(struct spi_device *spi)
+static int m41t93_remove(struct spi_device *spi)
 {
        struct rtc_device *rtc = spi_get_drvdata(spi);
 
@@ -211,7 +211,7 @@ static struct spi_driver m41t93_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = m41t93_probe,
-       .remove = __devexit_p(m41t93_remove),
+       .remove = m41t93_remove,
 };
 
 module_spi_driver(m41t93_driver);
index 6e78193e026b8b2c38599d62cde552a2ba7864b4..89266c6764bc0915bdf0d1b78cfa065fa699f20f 100644 (file)
@@ -110,7 +110,7 @@ static const struct rtc_class_ops m41t94_rtc_ops = {
 
 static struct spi_driver m41t94_driver;
 
-static int __devinit m41t94_probe(struct spi_device *spi)
+static int m41t94_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        int res;
@@ -134,7 +134,7 @@ static int __devinit m41t94_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit m41t94_remove(struct spi_device *spi)
+static int m41t94_remove(struct spi_device *spi)
 {
        struct rtc_device *rtc = spi_get_drvdata(spi);
 
@@ -150,7 +150,7 @@ static struct spi_driver m41t94_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = m41t94_probe,
-       .remove = __devexit_p(m41t94_remove),
+       .remove = m41t94_remove,
 };
 
 module_spi_driver(m41t94_driver);
index f9e3b3583733a21a296a0a2ec32bbfe8daf4f699..31c9190a1fcb7ee0331d8de58a2922501db85f35 100644 (file)
@@ -141,7 +141,7 @@ static const struct rtc_class_ops m48t35_ops = {
        .set_time       = m48t35_set_time,
 };
 
-static int __devinit m48t35_probe(struct platform_device *pdev)
+static int m48t35_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct m48t35_priv *priv;
@@ -194,7 +194,7 @@ out:
        return ret;
 }
 
-static int __devexit m48t35_remove(struct platform_device *pdev)
+static int m48t35_remove(struct platform_device *pdev)
 {
        struct m48t35_priv *priv = platform_get_drvdata(pdev);
 
@@ -213,7 +213,7 @@ static struct platform_driver m48t35_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = m48t35_probe,
-       .remove         = __devexit_p(m48t35_remove),
+       .remove         = m48t35_remove,
 };
 
 module_platform_driver(m48t35_platform_driver);
index 30ebfec9fd2b84a6bdd819bc3a736bdea86218c7..130f29af3869c974160c896d41ce890a6a64e217 100644 (file)
@@ -383,7 +383,7 @@ static struct bin_attribute m48t59_nvram_attr = {
        .write = m48t59_nvram_write,
 };
 
-static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
+static int m48t59_rtc_probe(struct platform_device *pdev)
 {
        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
        struct m48t59_private *m48t59 = NULL;
@@ -501,7 +501,7 @@ out:
        return ret;
 }
 
-static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
+static int m48t59_rtc_remove(struct platform_device *pdev)
 {
        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
@@ -527,7 +527,7 @@ static struct platform_driver m48t59_rtc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = m48t59_rtc_probe,
-       .remove         = __devexit_p(m48t59_rtc_remove),
+       .remove         = m48t59_rtc_remove,
 };
 
 module_platform_driver(m48t59_rtc_driver);
index 863fb3363aa6da503a5e0d66f1b1e7e853a97dca..2ffbcacd243917c7f879cfa4c8555cef3892a77d 100644 (file)
@@ -144,7 +144,7 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
        .proc           = m48t86_rtc_proc,
 };
 
-static int __devinit m48t86_rtc_probe(struct platform_device *dev)
+static int m48t86_rtc_probe(struct platform_device *dev)
 {
        unsigned char reg;
        struct m48t86_ops *ops = dev->dev.platform_data;
@@ -164,7 +164,7 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit m48t86_rtc_remove(struct platform_device *dev)
+static int m48t86_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -182,7 +182,7 @@ static struct platform_driver m48t86_rtc_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = m48t86_rtc_probe,
-       .remove         = __devexit_p(m48t86_rtc_remove),
+       .remove         = m48t86_rtc_remove,
 };
 
 module_platform_driver(m48t86_rtc_platform_driver);
index 36c74d22e8b50a490082745b435aa284e37a4eb7..7d0bf698b79ed1f5bd6a95f4fc0f4910d11a1639 100644 (file)
@@ -120,7 +120,7 @@ static const struct rtc_class_ops max6902_rtc_ops = {
        .set_time       = max6902_set_time,
 };
 
-static int __devinit max6902_probe(struct spi_device *spi)
+static int max6902_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        unsigned char tmp;
@@ -143,7 +143,7 @@ static int __devinit max6902_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit max6902_remove(struct spi_device *spi)
+static int max6902_remove(struct spi_device *spi)
 {
        struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
 
@@ -157,7 +157,7 @@ static struct spi_driver max6902_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = max6902_probe,
-       .remove = __devexit_p(max6902_remove),
+       .remove = max6902_remove,
 };
 
 module_spi_driver(max6902_driver);
index e094ffa434f827eb3cce26aa470f3a5a9f11c300..1d049da16c8527e0e5a44dc03bd82c983c9d1e9a 100644 (file)
@@ -176,7 +176,7 @@ static const struct rtc_class_ops max8907_rtc_ops = {
        .set_alarm      = max8907_rtc_set_alarm,
 };
 
-static int __devinit max8907_rtc_probe(struct platform_device *pdev)
+static int max8907_rtc_probe(struct platform_device *pdev)
 {
        struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
        struct max8907_rtc *rtc;
@@ -220,7 +220,7 @@ err_unregister:
        return ret;
 }
 
-static int __devexit max8907_rtc_remove(struct platform_device *pdev)
+static int max8907_rtc_remove(struct platform_device *pdev)
 {
        struct max8907_rtc *rtc = platform_get_drvdata(pdev);
 
@@ -236,7 +236,7 @@ static struct platform_driver max8907_rtc_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8907_rtc_probe,
-       .remove = __devexit_p(max8907_rtc_remove),
+       .remove = max8907_rtc_remove,
 };
 module_platform_driver(max8907_rtc_driver);
 
index 34e4349611dbdd6302a33d7b2917f1144a7ef306..a0c8265646d246981d51e8779706e924b8ad344c 100644 (file)
@@ -247,7 +247,7 @@ static const struct rtc_class_ops max8925_rtc_ops = {
        .set_alarm      = max8925_rtc_set_alarm,
 };
 
-static int __devinit max8925_rtc_probe(struct platform_device *pdev)
+static int max8925_rtc_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct max8925_rtc_info *info;
@@ -292,7 +292,7 @@ out_irq:
        return ret;
 }
 
-static int __devexit max8925_rtc_remove(struct platform_device *pdev)
+static int max8925_rtc_remove(struct platform_device *pdev)
 {
        struct max8925_rtc_info *info = platform_get_drvdata(pdev);
 
@@ -334,7 +334,7 @@ static struct platform_driver max8925_rtc_driver = {
                .pm     = &max8925_rtc_pm_ops,
        },
        .probe          = max8925_rtc_probe,
-       .remove         = __devexit_p(max8925_rtc_remove),
+       .remove         = max8925_rtc_remove,
 };
 
 module_platform_driver(max8925_rtc_driver);
index 7196f438c0895707233a4e9b0814c680e7821722..8f234a075e8fe38f5e76ebf5d463089f1e479ff5 100644 (file)
@@ -249,7 +249,7 @@ static const struct rtc_class_ops max8998_rtc_ops = {
        .alarm_irq_enable = max8998_rtc_alarm_irq_enable,
 };
 
-static int __devinit max8998_rtc_probe(struct platform_device *pdev)
+static int max8998_rtc_probe(struct platform_device *pdev)
 {
        struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent);
        struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev);
@@ -298,7 +298,7 @@ out_rtc:
        return ret;
 }
 
-static int __devexit max8998_rtc_remove(struct platform_device *pdev)
+static int max8998_rtc_remove(struct platform_device *pdev)
 {
        struct max8998_rtc_info *info = platform_get_drvdata(pdev);
 
@@ -323,7 +323,7 @@ static struct platform_driver max8998_rtc_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = max8998_rtc_probe,
-       .remove         = __devexit_p(max8998_rtc_remove),
+       .remove         = max8998_rtc_remove,
        .id_table       = max8998_rtc_id,
 };
 
index 029e421baaed49b7f62c58c0ef89454d2fa2053b..bec10be96f84222a7d50d9742c8d84f920b37170 100644 (file)
@@ -306,7 +306,7 @@ static const struct rtc_class_ops mpc5200_rtc_ops = {
        .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
 };
 
-static int __devinit mpc5121_rtc_probe(struct platform_device *op)
+static int mpc5121_rtc_probe(struct platform_device *op)
 {
        struct mpc5121_rtc_data *rtc;
        int err = 0;
@@ -382,7 +382,7 @@ out_free:
        return err;
 }
 
-static int __devexit mpc5121_rtc_remove(struct platform_device *op)
+static int mpc5121_rtc_remove(struct platform_device *op)
 {
        struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev);
        struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
@@ -403,7 +403,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
+static struct of_device_id mpc5121_rtc_match[] = {
        { .compatible = "fsl,mpc5121-rtc", },
        { .compatible = "fsl,mpc5200-rtc", },
        {},
@@ -416,7 +416,7 @@ static struct platform_driver mpc5121_rtc_driver = {
                .of_match_table = mpc5121_rtc_match,
        },
        .probe = mpc5121_rtc_probe,
-       .remove = __devexit_p(mpc5121_rtc_remove),
+       .remove = mpc5121_rtc_remove,
 };
 
 module_platform_driver(mpc5121_rtc_driver);
index f51719bf4a758dd1576df26227f60c30c3bd6eb9..578baf9d9725cf3bbfdb91669af5cda56ff9d7ef 100644 (file)
@@ -322,8 +322,8 @@ static irqreturn_t mrst_rtc_irq(int irq, void *p)
        return IRQ_NONE;
 }
 
-static int __devinit
-vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
+static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
+                             int rtc_irq)
 {
        int retval = 0;
        unsigned char rtc_control;
@@ -394,7 +394,7 @@ static void rtc_mrst_do_shutdown(void)
        spin_unlock_irq(&rtc_lock);
 }
 
-static void __devexit rtc_mrst_do_remove(struct device *dev)
+static void rtc_mrst_do_remove(struct device *dev)
 {
        struct mrst_rtc *mrst = dev_get_drvdata(dev);
        struct resource *iomem;
@@ -503,14 +503,14 @@ static inline int mrst_poweroff(struct device *dev)
 
 #endif
 
-static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev)
+static int vrtc_mrst_platform_probe(struct platform_device *pdev)
 {
        return vrtc_mrst_do_probe(&pdev->dev,
                        platform_get_resource(pdev, IORESOURCE_MEM, 0),
                        platform_get_irq(pdev, 0));
 }
 
-static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev)
+static int vrtc_mrst_platform_remove(struct platform_device *pdev)
 {
        rtc_mrst_do_remove(&pdev->dev);
        return 0;
@@ -528,7 +528,7 @@ MODULE_ALIAS("platform:vrtc_mrst");
 
 static struct platform_driver vrtc_mrst_platform_driver = {
        .probe          = vrtc_mrst_platform_probe,
-       .remove         = __devexit_p(vrtc_mrst_platform_remove),
+       .remove         = vrtc_mrst_platform_remove,
        .shutdown       = vrtc_mrst_platform_shutdown,
        .driver = {
                .name           = (char *) driver_name,
index ebc1649d45d61ef068792d479bdc7deb438ad5c8..57233c8859989d15a2a6ce5b041c1363d07374c2 100644 (file)
@@ -215,7 +215,7 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = {
        .alarm_irq_enable = mv_rtc_alarm_irq_enable,
 };
 
-static int __devinit mv_rtc_probe(struct platform_device *pdev)
+static int mv_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct rtc_plat_data *pdata;
index 7304139934aaff357cde2f88b0b5db49d9095d43..1c3ef72895659c5142435e9cd87055f46e02ead1 100644 (file)
@@ -368,7 +368,7 @@ static struct rtc_class_ops mxc_rtc_ops = {
        .alarm_irq_enable       = mxc_rtc_alarm_irq_enable,
 };
 
-static int __devinit mxc_rtc_probe(struct platform_device *pdev)
+static int mxc_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct rtc_device *rtc;
@@ -460,7 +460,7 @@ exit_free_pdata:
        return ret;
 }
 
-static int __devexit mxc_rtc_remove(struct platform_device *pdev)
+static int mxc_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
@@ -509,7 +509,7 @@ static struct platform_driver mxc_rtc_driver = {
        },
        .id_table = imx_rtc_devtype,
        .probe = mxc_rtc_probe,
-       .remove = __devexit_p(mxc_rtc_remove),
+       .remove = mxc_rtc_remove,
 };
 
 module_platform_driver(mxc_rtc_driver)
index b79010987d1e6383d52b6cbd2792deadcda9c555..a63680850fef248f1015c44702d2c6eccd640610 100644 (file)
@@ -222,7 +222,7 @@ static struct rtc_class_ops nuc900_rtc_ops = {
        .alarm_irq_enable = nuc900_alarm_irq_enable,
 };
 
-static int __devinit nuc900_rtc_probe(struct platform_device *pdev)
+static int nuc900_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct nuc900_rtc *nuc900_rtc;
@@ -284,7 +284,7 @@ fail1:      kfree(nuc900_rtc);
        return err;
 }
 
-static int __devexit nuc900_rtc_remove(struct platform_device *pdev)
+static int nuc900_rtc_remove(struct platform_device *pdev)
 {
        struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev);
        struct resource *res;
@@ -304,7 +304,7 @@ static int __devexit nuc900_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver nuc900_rtc_driver = {
-       .remove         = __devexit_p(nuc900_rtc_remove),
+       .remove         = nuc900_rtc_remove,
        .driver         = {
                .name   = "nuc900-rtc",
                .owner  = THIS_MODULE,
index cd4f198cc2eff921b364eaa1d66ae8b97e7cf5a1..e0019cd0bf710a6cca6ed139471272c6cc1d1d24 100644 (file)
@@ -139,7 +139,7 @@ static const struct rtc_class_ops pcap_rtc_ops = {
        .alarm_irq_enable = pcap_rtc_alarm_irq_enable,
 };
 
-static int __devinit pcap_rtc_probe(struct platform_device *pdev)
+static int pcap_rtc_probe(struct platform_device *pdev)
 {
        struct pcap_rtc *pcap_rtc;
        int timer_irq, alarm_irq;
@@ -183,7 +183,7 @@ fail_rtc:
        return err;
 }
 
-static int __devexit pcap_rtc_remove(struct platform_device *pdev)
+static int pcap_rtc_remove(struct platform_device *pdev)
 {
        struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
 
@@ -196,7 +196,7 @@ static int __devexit pcap_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver pcap_rtc_driver = {
-       .remove = __devexit_p(pcap_rtc_remove),
+       .remove = pcap_rtc_remove,
        .driver = {
                .name  = "pcap-rtc",
                .owner = THIS_MODULE,
index 13e4df63974fa27e7d7acf97c7b94e57ff9722ac..02b742afa761649b0737ab00da9cf69b8526feb8 100644 (file)
@@ -219,7 +219,7 @@ static const struct rtc_class_ops pcf2123_rtc_ops = {
        .set_time       = pcf2123_rtc_set_time,
 };
 
-static int __devinit pcf2123_probe(struct spi_device *spi)
+static int pcf2123_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        struct pcf2123_plat_data *pdata;
@@ -319,7 +319,7 @@ kfree_exit:
        return ret;
 }
 
-static int __devexit pcf2123_remove(struct spi_device *spi)
+static int pcf2123_remove(struct spi_device *spi)
 {
        struct pcf2123_plat_data *pdata = spi->dev.platform_data;
        int i;
@@ -345,7 +345,7 @@ static struct spi_driver pcf2123_driver = {
                        .owner  = THIS_MODULE,
        },
        .probe  = pcf2123_probe,
-       .remove = __devexit_p(pcf2123_remove),
+       .remove = pcf2123_remove,
 };
 
 module_spi_driver(pcf2123_driver);
index a20202f9ee577d5ec477630c4a8073b7ed8abee0..e9f3135d305ff35eb4594dd6e35dfaee93a5c35a 100644 (file)
@@ -248,7 +248,7 @@ static void pcf50633_rtc_irq(int irq, void *data)
        rtc->alarm_pending = 1;
 }
 
-static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
+static int pcf50633_rtc_probe(struct platform_device *pdev)
 {
        struct pcf50633_rtc *rtc;
 
@@ -272,7 +272,7 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
+static int pcf50633_rtc_remove(struct platform_device *pdev)
 {
        struct pcf50633_rtc *rtc;
 
@@ -291,7 +291,7 @@ static struct platform_driver pcf50633_rtc_driver = {
                .name = "pcf50633-rtc",
        },
        .probe = pcf50633_rtc_probe,
-       .remove = __devexit_p(pcf50633_rtc_remove),
+       .remove = pcf50633_rtc_remove,
 };
 
 module_platform_driver(pcf50633_rtc_driver);
index 98e3a2b681e6f7957c830e5dca4292c4b5fe73b0..7098ee89bd29fcb5b6d9285e6047dd799d2dd5b9 100644 (file)
@@ -296,7 +296,7 @@ static const struct i2c_device_id pcf8563_id[] = {
 MODULE_DEVICE_TABLE(i2c, pcf8563_id);
 
 #ifdef CONFIG_OF
-static const struct of_device_id pcf8563_of_match[] __devinitconst = {
+static const struct of_device_id pcf8563_of_match[] = {
        { .compatible = "nxp,pcf8563" },
        {}
 };
index 019ff357116856ecf14ebbdbfb8af4834b7a5d0c..3415b8f185557d5da7a021a2a0535161feed9047 100644 (file)
@@ -294,7 +294,7 @@ exit_kfree:
        return err;
 }
 
-static int __devexit pcf8583_remove(struct i2c_client *client)
+static int pcf8583_remove(struct i2c_client *client)
 {
        struct pcf8583 *pcf8583 = i2c_get_clientdata(client);
 
@@ -316,7 +316,7 @@ static struct i2c_driver pcf8583_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pcf8583_probe,
-       .remove         = __devexit_p(pcf8583_remove),
+       .remove         = pcf8583_remove,
        .id_table       = pcf8583_id,
 };
 
index 08378e3cc21cf8209796d50876ee64ae5c0a4aaa..81c5077feff32af9724da4e81f674b4d29c524e5 100644 (file)
@@ -44,6 +44,7 @@
 #define RTC_YMR                0x34    /* Year match register */
 #define RTC_YLR                0x38    /* Year data load register */
 
+#define RTC_CR_EN      (1 << 0)        /* counter enable bit */
 #define RTC_CR_CWEN    (1 << 26)       /* Clockwatch enable bit */
 
 #define RTC_TCR_EN     (1 << 1) /* Periodic timer enable bit */
@@ -320,7 +321,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
        struct pl031_local *ldata;
        struct pl031_vendor_data *vendor = id->data;
        struct rtc_class_ops *ops = &vendor->ops;
-       unsigned long time;
+       unsigned long time, data;
 
        ret = amba_request_regions(adev, NULL);
        if (ret)
@@ -345,10 +346,13 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
        dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
        dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
 
+       data = readl(ldata->base + RTC_CR);
        /* Enable the clockwatch on ST Variants */
        if (vendor->clockwatch)
-               writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
-                      ldata->base + RTC_CR);
+               data |= RTC_CR_CWEN;
+       else
+               data |= RTC_CR_EN;
+       writel(data, ldata->base + RTC_CR);
 
        /*
         * On ST PL031 variants, the RTC reset value does not provide correct
index d00bd24342a311555cb35f444296cddfb27bf408..f1a6557261f39c36a0dda30e68e5bd143e2a06e6 100644 (file)
@@ -382,7 +382,7 @@ rtc_alarm_handled:
        return IRQ_HANDLED;
 }
 
-static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev)
+static int pm8xxx_rtc_probe(struct platform_device *pdev)
 {
        int rc;
        u8 ctrl_reg;
@@ -485,7 +485,7 @@ fail_rtc_enable:
        return rc;
 }
 
-static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
+static int pm8xxx_rtc_remove(struct platform_device *pdev)
 {
        struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
 
@@ -524,7 +524,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resum
 
 static struct platform_driver pm8xxx_rtc_driver = {
        .probe          = pm8xxx_rtc_probe,
-       .remove         = __devexit_p(pm8xxx_rtc_remove),
+       .remove         = pm8xxx_rtc_remove,
        .driver = {
                .name   = PM8XXX_RTC_DEV_NAME,
                .owner  = THIS_MODULE,
index ab0acaeb23719bfc055fe97cfb1efe7a051df756..0407e13d4de4771b6768e696ea88c04b6ddc3a90 100644 (file)
@@ -220,7 +220,7 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en)
        }
 }
 
-static int __devexit puv3_rtc_remove(struct platform_device *dev)
+static int puv3_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -236,7 +236,7 @@ static int __devexit puv3_rtc_remove(struct platform_device *dev)
        return 0;
 }
 
-static int __devinit puv3_rtc_probe(struct platform_device *pdev)
+static int puv3_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
@@ -328,7 +328,7 @@ static int puv3_rtc_resume(struct platform_device *pdev)
 
 static struct platform_driver puv3_rtc_driver = {
        .probe          = puv3_rtc_probe,
-       .remove         = __devexit_p(puv3_rtc_remove),
+       .remove         = puv3_rtc_remove,
        .suspend        = puv3_rtc_suspend,
        .resume         = puv3_rtc_resume,
        .driver         = {
index 2c183ebff715f7acc277a82558544af53083ef4b..7726f4a4f2d051882f74a8a074834988cbad0a4c 100644 (file)
@@ -119,7 +119,7 @@ static const struct rtc_class_ops r9701_rtc_ops = {
        .set_time       = r9701_set_datetime,
 };
 
-static int __devinit r9701_probe(struct spi_device *spi)
+static int r9701_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
        struct rtc_time dt;
@@ -164,7 +164,7 @@ static int __devinit r9701_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit r9701_remove(struct spi_device *spi)
+static int r9701_remove(struct spi_device *spi)
 {
        struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
 
@@ -178,7 +178,7 @@ static struct spi_driver r9701_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = r9701_probe,
-       .remove = __devexit_p(r9701_remove),
+       .remove = r9701_remove,
 };
 
 module_spi_driver(r9701_driver);
index cdb140c29c56bdc43a2a8cf2ebc14a06d82815a5..eb3194d664a8b7c03b378701a9840e3024bc6ad8 100644 (file)
@@ -211,7 +211,7 @@ static const struct rtc_class_ops rc5t583_rtc_ops = {
        .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,
 };
 
-static int __devinit rc5t583_rtc_probe(struct platform_device *pdev)
+static int rc5t583_rtc_probe(struct platform_device *pdev)
 {
        struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
        struct rc5t583_rtc *ricoh_rtc;
@@ -271,7 +271,7 @@ static int __devinit rc5t583_rtc_probe(struct platform_device *pdev)
  * Disable rc5t583 RTC interrupts.
  * Sets status flag to free.
  */
-static int __devexit rc5t583_rtc_remove(struct platform_device *pdev)
+static int rc5t583_rtc_remove(struct platform_device *pdev)
 {
        struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev);
 
@@ -317,7 +317,7 @@ static const struct dev_pm_ops rc5t583_rtc_pm_ops = {
 
 static struct platform_driver rc5t583_rtc_driver = {
        .probe          = rc5t583_rtc_probe,
-       .remove         = __devexit_p(rc5t583_rtc_remove),
+       .remove         = rc5t583_rtc_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "rtc-rc5t583",
index e3ff179b99ca23da32527a0f13ca42d855564748..d1aee793ecc8a971e5130a2806b20fdfb48acc25 100644 (file)
@@ -377,7 +377,7 @@ static int rs5c313_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit rs5c313_rtc_remove(struct platform_device *pdev)
+static int rs5c313_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata( pdev );
 
@@ -392,7 +392,7 @@ static struct platform_driver rs5c313_rtc_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = rs5c313_rtc_probe,
-       .remove = __devexit_p( rs5c313_rtc_remove ),
+       .remove = rs5c313_rtc_remove,
 };
 
 static int __init rs5c313_rtc_init(void)
index fd5c7af04ae5a7d7c1ba30a5822396e6780adc5f..72ef10be86624948ac2adc8348134af32ec26811 100644 (file)
@@ -152,7 +152,7 @@ static const struct rtc_class_ops rs5c348_rtc_ops = {
 
 static struct spi_driver rs5c348_driver;
 
-static int __devinit rs5c348_probe(struct spi_device *spi)
+static int rs5c348_probe(struct spi_device *spi)
 {
        int ret;
        struct rtc_device *rtc;
@@ -218,7 +218,7 @@ static int __devinit rs5c348_probe(struct spi_device *spi)
        return ret;
 }
 
-static int __devexit rs5c348_remove(struct spi_device *spi)
+static int rs5c348_remove(struct spi_device *spi)
 {
        struct rs5c348_plat_data *pdata = spi->dev.platform_data;
        struct rtc_device *rtc = pdata->rtc;
@@ -235,7 +235,7 @@ static struct spi_driver rs5c348_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = rs5c348_probe,
-       .remove = __devexit_p(rs5c348_remove),
+       .remove = rs5c348_remove,
 };
 
 module_spi_driver(rs5c348_driver);
index 0fbe57b2f6d21313b162c5c13f3aadfe1c6a8068..f8ee8ad7825e25d0d69612d47fdaf928201f1d29 100644 (file)
@@ -385,8 +385,8 @@ static struct i2c_device_id rv3029c2_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rv3029c2_id);
 
-static int __devinit
-rv3029c2_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int rv3029c2_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct rtc_device *rtc;
        int rc = 0;
@@ -418,7 +418,7 @@ exit_unregister:
        return rc;
 }
 
-static int __devexit rv3029c2_remove(struct i2c_client *client)
+static int rv3029c2_remove(struct i2c_client *client)
 {
        struct rtc_device *rtc = i2c_get_clientdata(client);
 
@@ -432,7 +432,7 @@ static struct i2c_driver rv3029c2_driver = {
                .name = "rtc-rv3029c2",
        },
        .probe = rv3029c2_probe,
-       .remove = __devexit_p(rv3029c2_remove),
+       .remove = rv3029c2_remove,
        .id_table = rv3029c2_id,
 };
 
index 0de902dc1cd5c9cdd5bc40b4f0cb09e8ada1ff14..0722d36b9c9adcdb5e112105baa0eb77a95c1ac7 100644 (file)
@@ -534,8 +534,8 @@ static void rx8025_sysfs_unregister(struct device *dev)
        device_remove_file(dev, &dev_attr_clock_adjust_ppb);
 }
 
-static int __devinit rx8025_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int rx8025_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct rx8025_data *rx8025;
@@ -614,7 +614,7 @@ errout:
        return err;
 }
 
-static int __devexit rx8025_remove(struct i2c_client *client)
+static int rx8025_remove(struct i2c_client *client)
 {
        struct rx8025_data *rx8025 = i2c_get_clientdata(client);
        struct mutex *lock = &rx8025->rtc->ops_lock;
@@ -640,7 +640,7 @@ static struct i2c_driver rx8025_driver = {
                .owner = THIS_MODULE,
        },
        .probe          = rx8025_probe,
-       .remove         = __devexit_p(rx8025_remove),
+       .remove         = rx8025_remove,
        .id_table       = rx8025_id,
 };
 
index d84825124a7ae19428233b8871827c5d2f3052db..b0c272658fa27cd3effbf0de14abbfa691aa62c6 100644 (file)
@@ -228,8 +228,8 @@ static const struct rtc_class_ops rx8581_rtc_ops = {
        .set_time       = rx8581_rtc_set_time,
 };
 
-static int __devinit rx8581_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int rx8581_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct rtc_device *rtc;
 
@@ -251,7 +251,7 @@ static int __devinit rx8581_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit rx8581_remove(struct i2c_client *client)
+static int rx8581_remove(struct i2c_client *client)
 {
        struct rtc_device *rtc = i2c_get_clientdata(client);
 
@@ -272,7 +272,7 @@ static struct i2c_driver rx8581_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rx8581_probe,
-       .remove         = __devexit_p(rx8581_remove),
+       .remove         = rx8581_remove,
        .id_table       = rx8581_id,
 };
 
index 4bd9414aee650e2b08449323a5840497a5b9c48c..404651464d4545f09800fa898d2638f70a17d460 100644 (file)
@@ -421,7 +421,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
        clk_disable(rtc_clk);
 }
 
-static int __devexit s3c_rtc_remove(struct platform_device *dev)
+static int s3c_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -451,7 +451,7 @@ static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
        return platform_get_device_id(pdev)->driver_data;
 }
 
-static int __devinit s3c_rtc_probe(struct platform_device *pdev)
+static int s3c_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct rtc_time rtc_tm;
@@ -686,7 +686,7 @@ MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
 
 static struct platform_driver s3c_rtc_driver = {
        .probe          = s3c_rtc_probe,
-       .remove         = __devexit_p(s3c_rtc_remove),
+       .remove         = s3c_rtc_remove,
        .suspend        = s3c_rtc_suspend,
        .resume         = s3c_rtc_resume,
        .id_table       = s3c_rtc_driver_ids,
index 3c0da333f4658265af23f96c1b5d12cdab71d634..d5ec7854a65123b1eb5ae49c5f55ccbdd0d2deee 100644 (file)
@@ -241,7 +241,7 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
        return events ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int __devinit snvs_rtc_probe(struct platform_device *pdev)
+static int snvs_rtc_probe(struct platform_device *pdev)
 {
        struct snvs_rtc_data *data;
        struct resource *res;
@@ -294,7 +294,7 @@ static int __devinit snvs_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit snvs_rtc_remove(struct platform_device *pdev)
+static int snvs_rtc_remove(struct platform_device *pdev)
 {
        struct snvs_rtc_data *data = platform_get_drvdata(pdev);
 
@@ -327,7 +327,7 @@ static int snvs_rtc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume);
 
-static const struct of_device_id __devinitconst snvs_dt_ids[] = {
+static const struct of_device_id snvs_dt_ids[] = {
        { .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
        { /* sentinel */ }
 };
@@ -341,7 +341,7 @@ static struct platform_driver snvs_rtc_driver = {
                .of_match_table = snvs_dt_ids,
        },
        .probe          = snvs_rtc_probe,
-       .remove         = __devexit_p(snvs_rtc_remove),
+       .remove         = snvs_rtc_remove,
 };
 module_platform_driver(snvs_rtc_driver);
 
index 141fc945295f0796a46f2f4cb79d1535bbfe7bf7..c2121b5a01f21825f24d99120f76771a83e6b2fa 100644 (file)
@@ -351,7 +351,7 @@ static struct rtc_class_ops spear_rtc_ops = {
        .alarm_irq_enable = spear_alarm_irq_enable,
 };
 
-static int __devinit spear_rtc_probe(struct platform_device *pdev)
+static int spear_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct spear_rtc_config *config;
@@ -425,7 +425,7 @@ err_disable_clock:
        return status;
 }
 
-static int __devexit spear_rtc_remove(struct platform_device *pdev)
+static int spear_rtc_remove(struct platform_device *pdev)
 {
        struct spear_rtc_config *config = platform_get_drvdata(pdev);
 
@@ -499,7 +499,7 @@ MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
 
 static struct platform_driver spear_rtc_driver = {
        .probe = spear_rtc_probe,
-       .remove = __devexit_p(spear_rtc_remove),
+       .remove = spear_rtc_remove,
        .suspend = spear_rtc_suspend,
        .resume = spear_rtc_resume,
        .shutdown = spear_rtc_shutdown,
index 279f5cfa691a7ff30ec4642c8599ffdbb063d684..7e4a6f65cb91433293d9b097a9323354fad1a263 100644 (file)
@@ -285,7 +285,7 @@ static struct bin_attribute stk17ta8_nvram_attr = {
        .write = stk17ta8_nvram_write,
 };
 
-static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev)
+static int stk17ta8_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        unsigned int cal;
@@ -347,7 +347,7 @@ static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev)
+static int stk17ta8_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
@@ -363,7 +363,7 @@ MODULE_ALIAS("platform:stk17ta8");
 
 static struct platform_driver stk17ta8_rtc_driver = {
        .probe          = stk17ta8_rtc_probe,
-       .remove         = __devexit_p(stk17ta8_rtc_remove),
+       .remove         = stk17ta8_rtc_remove,
        .driver         = {
                .name   = "stk17ta8",
                .owner  = THIS_MODULE,
index c006025cecc809ac3b00d1abbe59a3f4e3527254..c84ea6659f497fb32d67a8ec02f70e38a57055ce 100644 (file)
@@ -303,7 +303,13 @@ static struct rtc_class_ops tegra_rtc_ops = {
        .alarm_irq_enable = tegra_rtc_alarm_irq_enable,
 };
 
-static int __devinit tegra_rtc_probe(struct platform_device *pdev)
+static const struct of_device_id tegra_rtc_dt_match[] = {
+       { .compatible = "nvidia,tegra20-rtc", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
+
+static int tegra_rtc_probe(struct platform_device *pdev)
 {
        struct tegra_rtc_info *info;
        struct resource *res;
@@ -375,7 +381,7 @@ err_dev_unreg:
        return ret;
 }
 
-static int __devexit tegra_rtc_remove(struct platform_device *pdev)
+static int tegra_rtc_remove(struct platform_device *pdev)
 {
        struct tegra_rtc_info *info = platform_get_drvdata(pdev);
 
@@ -435,11 +441,12 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:tegra_rtc");
 static struct platform_driver tegra_rtc_driver = {
-       .remove         = __devexit_p(tegra_rtc_remove),
+       .remove         = tegra_rtc_remove,
        .shutdown       = tegra_rtc_shutdown,
        .driver         = {
                .name   = "tegra_rtc",
                .owner  = THIS_MODULE,
+               .of_match_table = tegra_rtc_dt_match,
        },
 #ifdef CONFIG_PM
        .suspend        = tegra_rtc_suspend,
index 974b9ae252ab5f116d9fa6faa21d587029a3f18a..b92e0f6383e6bac3549e45310d1c78478216205e 100644 (file)
@@ -119,7 +119,7 @@ err:
        return err;
 }
 
-static int __devexit test_remove(struct platform_device *plat_dev)
+static int test_remove(struct platform_device *plat_dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
@@ -131,7 +131,7 @@ static int __devexit test_remove(struct platform_device *plat_dev)
 
 static struct platform_driver test_driver = {
        .probe  = test_probe,
-       .remove = __devexit_p(test_remove),
+       .remove = test_remove,
        .driver = {
                .name = "rtc-test",
                .owner = THIS_MODULE,
index eb65dafee66ed147654e2d6f4dc2780c6b300feb..62db4841078b93cbc5441990fb31410321aeb44e 100644 (file)
@@ -76,7 +76,7 @@ static const struct rtc_class_ops tile_rtc_ops = {
 /*
  * Device probe routine.
  */
-static int __devinit tile_rtc_probe(struct platform_device *dev)
+static int tile_rtc_probe(struct platform_device *dev)
 {
        struct rtc_device *rtc;
 
@@ -94,7 +94,7 @@ static int __devinit tile_rtc_probe(struct platform_device *dev)
 /*
  * Device cleanup routine.
  */
-static int __devexit tile_rtc_remove(struct platform_device *dev)
+static int tile_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -112,7 +112,7 @@ static struct platform_driver tile_rtc_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tile_rtc_probe,
-       .remove         = __devexit_p(tile_rtc_remove),
+       .remove         = tile_rtc_remove,
 };
 
 /*
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
new file mode 100644 (file)
index 0000000..70f61b8
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps6586x.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+#define RTC_CTRL                       0xc0
+#define POR_RESET_N                    BIT(7)
+#define OSC_SRC_SEL                    BIT(6)
+#define RTC_ENABLE                     BIT(5)  /* enables alarm */
+#define RTC_BUF_ENABLE                 BIT(4)  /* 32 KHz buffer enable */
+#define PRE_BYPASS                     BIT(3)  /* 0=1KHz or 1=32KHz updates */
+#define CL_SEL_MASK                    (BIT(2)|BIT(1))
+#define CL_SEL_POS                     1
+#define RTC_ALARM1_HI                  0xc1
+#define RTC_COUNT4                     0xc6
+
+/* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */
+#define RTC_COUNT4_DUMMYREAD           0xc5
+
+/*only 14-bits width in second*/
+#define ALM1_VALID_RANGE_IN_SEC                0x3FFF
+
+#define TPS6586X_RTC_CL_SEL_1_5PF      0x0
+#define TPS6586X_RTC_CL_SEL_6_5PF      0x1
+#define TPS6586X_RTC_CL_SEL_7_5PF      0x2
+#define TPS6586X_RTC_CL_SEL_12_5PF     0x3
+
+struct tps6586x_rtc {
+       struct device           *dev;
+       struct rtc_device       *rtc;
+       int                     irq;
+       bool                    irq_en;
+       unsigned long long      epoch_start;
+};
+
+static inline struct device *to_tps6586x_dev(struct device *dev)
+{
+       return dev->parent;
+}
+
+static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+       struct device *tps_dev = to_tps6586x_dev(dev);
+       unsigned long long ticks = 0;
+       unsigned long seconds;
+       u8 buff[6];
+       int ret;
+       int i;
+
+       ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(buff), buff);
+       if (ret < 0) {
+               dev_err(dev, "read counter failed with err %d\n", ret);
+               return ret;
+       }
+
+       for (i = 1; i < sizeof(buff); i++) {
+               ticks <<= 8;
+               ticks |= buff[i];
+       }
+
+       seconds = ticks >> 10;
+       seconds += rtc->epoch_start;
+       rtc_time_to_tm(seconds, tm);
+       return rtc_valid_tm(tm);
+}
+
+static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+       struct device *tps_dev = to_tps6586x_dev(dev);
+       unsigned long long ticks;
+       unsigned long seconds;
+       u8 buff[5];
+       int ret;
+
+       rtc_tm_to_time(tm, &seconds);
+       if (seconds < rtc->epoch_start) {
+               dev_err(dev, "requested time unsupported\n");
+               return -EINVAL;
+       }
+       seconds -= rtc->epoch_start;
+
+       ticks = (unsigned long long)seconds << 10;
+       buff[0] = (ticks >> 32) & 0xff;
+       buff[1] = (ticks >> 24) & 0xff;
+       buff[2] = (ticks >> 16) & 0xff;
+       buff[3] = (ticks >> 8) & 0xff;
+       buff[4] = ticks & 0xff;
+
+       /* Disable RTC before changing time */
+       ret = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
+       if (ret < 0) {
+               dev_err(dev, "failed to clear RTC_ENABLE\n");
+               return ret;
+       }
+
+       ret = tps6586x_writes(tps_dev, RTC_COUNT4, sizeof(buff), buff);
+       if (ret < 0) {
+               dev_err(dev, "failed to program new time\n");
+               return ret;
+       }
+
+       /* Enable RTC */
+       ret = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
+       if (ret < 0) {
+               dev_err(dev, "failed to set RTC_ENABLE\n");
+               return ret;
+       }
+       return 0;
+}
+
+static int tps6586x_rtc_alarm_irq_enable(struct device *dev,
+                        unsigned int enabled)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+
+       if (enabled && !rtc->irq_en) {
+               enable_irq(rtc->irq);
+               rtc->irq_en = true;
+       } else if (!enabled && rtc->irq_en)  {
+               disable_irq(rtc->irq);
+               rtc->irq_en = false;
+       }
+       return 0;
+}
+
+static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+       struct device *tps_dev = to_tps6586x_dev(dev);
+       unsigned long seconds;
+       unsigned long ticks;
+       unsigned long rtc_current_time;
+       unsigned long long rticks = 0;
+       u8 buff[3];
+       u8 rbuff[6];
+       int ret;
+       int i;
+
+       rtc_tm_to_time(&alrm->time, &seconds);
+
+       if (alrm->enabled && (seconds < rtc->epoch_start)) {
+               dev_err(dev, "can't set alarm to requested time\n");
+               return -EINVAL;
+       }
+
+       ret = tps6586x_rtc_alarm_irq_enable(dev, alrm->enabled);
+       if (ret < 0) {
+               dev_err(dev, "can't set alarm irq, err %d\n", ret);
+               return ret;
+       }
+
+       seconds -= rtc->epoch_start;
+       ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD,
+                       sizeof(rbuff), rbuff);
+       if (ret < 0) {
+               dev_err(dev, "read counter failed with err %d\n", ret);
+               return ret;
+       }
+
+       for (i = 1; i < sizeof(rbuff); i++) {
+               rticks <<= 8;
+               rticks |= rbuff[i];
+       }
+
+       rtc_current_time = rticks >> 10;
+       if ((seconds - rtc_current_time) > ALM1_VALID_RANGE_IN_SEC)
+               seconds = rtc_current_time - 1;
+
+       ticks = (unsigned long long)seconds << 10;
+       buff[0] = (ticks >> 16) & 0xff;
+       buff[1] = (ticks >> 8) & 0xff;
+       buff[2] = ticks & 0xff;
+
+       ret = tps6586x_writes(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff);
+       if (ret)
+               dev_err(dev, "programming alarm failed with err %d\n", ret);
+
+       return ret;
+}
+
+static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+       struct device *tps_dev = to_tps6586x_dev(dev);
+       unsigned long ticks;
+       unsigned long seconds;
+       u8 buff[3];
+       int ret;
+
+       ret = tps6586x_reads(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff);
+       if (ret) {
+               dev_err(dev, "read RTC_ALARM1_HI failed with err %d\n", ret);
+               return ret;
+       }
+
+       ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2];
+       seconds = ticks >> 10;
+       seconds += rtc->epoch_start;
+
+       rtc_time_to_tm(seconds, &alrm->time);
+       return 0;
+}
+
+static const struct rtc_class_ops tps6586x_rtc_ops = {
+       .read_time      = tps6586x_rtc_read_time,
+       .set_time       = tps6586x_rtc_set_time,
+       .set_alarm      = tps6586x_rtc_set_alarm,
+       .read_alarm     = tps6586x_rtc_read_alarm,
+       .alarm_irq_enable = tps6586x_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t tps6586x_rtc_irq(int irq, void *data)
+{
+       struct tps6586x_rtc *rtc = data;
+
+       rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
+       return IRQ_HANDLED;
+}
+
+static int tps6586x_rtc_probe(struct platform_device *pdev)
+{
+       struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
+       struct tps6586x_rtc *rtc;
+       int ret;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+
+       rtc->dev = &pdev->dev;
+       rtc->irq = platform_get_irq(pdev, 0);
+
+       /* Set epoch start as 00:00:00:01:01:2009 */
+       rtc->epoch_start = mktime(2009, 1, 1, 0, 0, 0);
+
+       /* 1 kHz tick mode, enable tick counting */
+       ret = tps6586x_update(tps_dev, RTC_CTRL,
+               RTC_ENABLE | OSC_SRC_SEL |
+               ((TPS6586X_RTC_CL_SEL_1_5PF << CL_SEL_POS) & CL_SEL_MASK),
+               RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to start counter\n");
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, rtc);
+       rtc->rtc = rtc_device_register(dev_name(&pdev->dev), &pdev->dev,
+                                      &tps6586x_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc)) {
+               ret = PTR_ERR(rtc->rtc);
+               dev_err(&pdev->dev, "RTC device register: ret %d\n", ret);
+               goto fail_rtc_register;
+       }
+
+       ret = request_threaded_irq(rtc->irq, NULL, tps6586x_rtc_irq,
+                               IRQF_ONESHOT | IRQF_EARLY_RESUME,
+                               dev_name(&pdev->dev), rtc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",
+                               rtc->irq, ret);
+               goto fail_req_irq;
+       }
+       disable_irq(rtc->irq);
+       device_set_wakeup_capable(&pdev->dev, 1);
+       return 0;
+
+fail_req_irq:
+       rtc_device_unregister(rtc->rtc);
+
+fail_rtc_register:
+       tps6586x_update(tps_dev, RTC_CTRL, 0,
+               RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
+       return ret;
+};
+
+static int tps6586x_rtc_remove(struct platform_device *pdev)
+{
+       struct tps6586x_rtc *rtc = platform_get_drvdata(pdev);
+       struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
+
+       tps6586x_update(tps_dev, RTC_CTRL, 0,
+               RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
+       rtc_device_unregister(rtc->rtc);
+       free_irq(rtc->irq, rtc);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tps6586x_rtc_suspend(struct device *dev)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(rtc->irq);
+       return 0;
+}
+
+static int tps6586x_rtc_resume(struct device *dev)
+{
+       struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(rtc->irq);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops tps6586x_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(tps6586x_rtc_suspend, tps6586x_rtc_resume)
+};
+
+static struct platform_driver tps6586x_rtc_driver = {
+       .driver = {
+               .name   = "tps6586x-rtc",
+               .owner  = THIS_MODULE,
+               .pm     = &tps6586x_pm_ops,
+       },
+       .probe  = tps6586x_rtc_probe,
+       .remove = tps6586x_rtc_remove,
+};
+module_platform_driver(tps6586x_rtc_driver);
+
+MODULE_ALIAS("platform:rtc-tps6586x");
+MODULE_DESCRIPTION("TI TPS6586x RTC driver");
+MODULE_AUTHOR("Laxman dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index 22eb4ebfa1a64cf295b80b02cb09339de15c56ab..e5fef141a0e21f4dfefa977596e05c5873b486c1 100644 (file)
@@ -222,7 +222,7 @@ static const struct rtc_class_ops tps65910_rtc_ops = {
        .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
 };
 
-static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
+static int tps65910_rtc_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = NULL;
        struct tps65910_rtc *tps_rtc = NULL;
@@ -292,7 +292,7 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
  * Disable tps65910 RTC interrupts.
  * Sets status flag to free.
  */
-static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
+static int tps65910_rtc_remove(struct platform_device *pdev)
 {
        /* leave rtc running, but disable irqs */
        struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);
@@ -342,7 +342,7 @@ static const struct dev_pm_ops tps65910_rtc_pm_ops = {
 
 static struct platform_driver tps65910_rtc_driver = {
        .probe          = tps65910_rtc_probe,
-       .remove         = __devexit_p(tps65910_rtc_remove),
+       .remove         = tps65910_rtc_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "tps65910-rtc",
index 8b7464c8b5cf2beab97568bbc04cd3495db18b9e..ccd4ad370b32fc2a2685c4103ed9902f137ee50b 100644 (file)
@@ -458,7 +458,7 @@ static struct rtc_class_ops twl_rtc_ops = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit twl_rtc_probe(struct platform_device *pdev)
+static int twl_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        int ret = -EINVAL;
@@ -535,7 +535,7 @@ out1:
  * Disable all TWL RTC module interrupts.
  * Sets status flag to free.
  */
-static int __devexit twl_rtc_remove(struct platform_device *pdev)
+static int twl_rtc_remove(struct platform_device *pdev)
 {
        /* leave rtc running, but disable irqs */
        struct rtc_device *rtc = platform_get_drvdata(pdev);
@@ -597,7 +597,7 @@ MODULE_ALIAS("platform:twl_rtc");
 
 static struct platform_driver twl4030rtc_driver = {
        .probe          = twl_rtc_probe,
-       .remove         = __devexit_p(twl_rtc_remove),
+       .remove         = twl_rtc_remove,
        .shutdown       = twl_rtc_shutdown,
        .suspend        = twl_rtc_suspend,
        .resume         = twl_rtc_resume,
index 5f60a7c6a15575d832b66c03a8c3ee72297514e1..6c3774cf5a2461fdfb7168885fbf55f783df79b2 100644 (file)
@@ -280,7 +280,7 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
        .set_alarm      = vr41xx_rtc_set_alarm,
 };
 
-static int __devinit rtc_probe(struct platform_device *pdev)
+static int rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct rtc_device *rtc;
@@ -373,7 +373,7 @@ err_rtc1_iounmap:
        return retval;
 }
 
-static int __devexit rtc_remove(struct platform_device *pdev)
+static int rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
 
@@ -398,7 +398,7 @@ MODULE_ALIAS("platform:RTC");
 
 static struct platform_driver rtc_platform_driver = {
        .probe          = rtc_probe,
-       .remove         = __devexit_p(rtc_remove),
+       .remove         = rtc_remove,
        .driver         = {
                .name   = rtc_name,
                .owner  = THIS_MODULE,
index 14e2d8cfcc83de0e55ba39cc2630da0d12e30b1e..2730533e2d2df2da9417882fb6891b5a65a17a1f 100644 (file)
@@ -70,7 +70,7 @@
                                | ALARM_SEC_BIT)
 
 #define VT8500_RTC_CR_ENABLE   (1 << 0)        /* Enable RTC */
-#define VT8500_RTC_CR_24H      (1 << 1)        /* 24h time format */
+#define VT8500_RTC_CR_12H      (1 << 1)        /* 12h time format */
 #define VT8500_RTC_CR_SM_ENABLE        (1 << 2)        /* Enable periodic irqs */
 #define VT8500_RTC_CR_SM_SEC   (1 << 3)        /* 0: 1Hz/60, 1: 1Hz */
 #define VT8500_RTC_CR_CALIB    (1 << 4)        /* Enable calibration */
@@ -119,7 +119,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
        tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);
        tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);
        tm->tm_mday = bcd2bin(date & DATE_DAY_MASK);
-       tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S);
+       tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1;
        tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S)
                        + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100);
        tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S;
@@ -137,9 +137,10 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S)
-               | (bin2bcd(tm->tm_mon) << DATE_MONTH_S)
-               | (bin2bcd(tm->tm_mday)),
+       writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S)
+               | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)
+               | (bin2bcd(tm->tm_mday))
+               | ((tm->tm_year >= 200) << DATE_CENTURY_S),
                vt8500_rtc->regbase + VT8500_RTC_DS);
        writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)
                | (bin2bcd(tm->tm_hour) << TIME_HOUR_S)
@@ -205,7 +206,7 @@ static const struct rtc_class_ops vt8500_rtc_ops = {
        .alarm_irq_enable = vt8500_alarm_irq_enable,
 };
 
-static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
+static int vt8500_rtc_probe(struct platform_device *pdev)
 {
        struct vt8500_rtc *vt8500_rtc;
        int ret;
@@ -247,7 +248,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
        }
 
        /* Enable RTC and set it to 24-hour mode */
-       writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H,
+       writel(VT8500_RTC_CR_ENABLE,
               vt8500_rtc->regbase + VT8500_RTC_CR);
 
        vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
@@ -279,7 +280,7 @@ err_release:
        return ret;
 }
 
-static int __devexit vt8500_rtc_remove(struct platform_device *pdev)
+static int vt8500_rtc_remove(struct platform_device *pdev)
 {
        struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);
 
@@ -305,7 +306,7 @@ static const struct of_device_id wmt_dt_ids[] = {
 
 static struct platform_driver vt8500_rtc_driver = {
        .probe          = vt8500_rtc_probe,
-       .remove         = __devexit_p(vt8500_rtc_remove),
+       .remove         = vt8500_rtc_remove,
        .driver         = {
                .name   = "vt8500-rtc",
                .owner  = THIS_MODULE,
index ea5c6f857ca5db35ebbfd3c581b0d5e7e32050d4..1b0affbe26591cd9ab9794266a2ade8bdd85db36 100644 (file)
@@ -459,7 +459,7 @@ err:
        return ret;
 }
 
-static int __devexit wm831x_rtc_remove(struct platform_device *pdev)
+static int wm831x_rtc_remove(struct platform_device *pdev)
 {
        struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev);
        int alm_irq = platform_get_irq_byname(pdev, "ALM");
@@ -483,7 +483,7 @@ static const struct dev_pm_ops wm831x_rtc_pm_ops = {
 
 static struct platform_driver wm831x_rtc_driver = {
        .probe = wm831x_rtc_probe,
-       .remove = __devexit_p(wm831x_rtc_remove),
+       .remove = wm831x_rtc_remove,
        .driver = {
                .name = "wm831x-rtc",
                .pm = &wm831x_rtc_pm_ops,
index c2e52d15abb295f0de5b0ae08afebf62c77ad009..8ad86ae0d30f8209cabb446eb35b5a2b84e5aa29 100644 (file)
@@ -459,7 +459,7 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit wm8350_rtc_remove(struct platform_device *pdev)
+static int wm8350_rtc_remove(struct platform_device *pdev)
 {
        struct wm8350 *wm8350 = platform_get_drvdata(pdev);
        struct wm8350_rtc *wm_rtc = &wm8350->rtc;
@@ -479,7 +479,7 @@ static struct dev_pm_ops wm8350_rtc_pm_ops = {
 
 static struct platform_driver wm8350_rtc_driver = {
        .probe = wm8350_rtc_probe,
-       .remove = __devexit_p(wm8350_rtc_remove),
+       .remove = wm8350_rtc_remove,
        .driver = {
                .name = "wm8350-rtc",
                .pm = &wm8350_rtc_pm_ops,
diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c
new file mode 100644 (file)
index 0000000..bf3e242
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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/rtc.h>
+#include <linux/time.h>
+
+/**
+ * rtc_set_ntp_time - Save NTP synchronized time to the RTC
+ * @now: Current time of day
+ *
+ * Replacement for the NTP platform function update_persistent_clock
+ * that stores time for later retrieval by rtc_hctosys.
+ *
+ * Returns 0 on successful RTC update, -ENODEV if a RTC update is not
+ * possible at all, and various other -errno for specific temporary failure
+ * cases.
+ *
+ * If temporary failure is indicated the caller should try again 'soon'
+ */
+int rtc_set_ntp_time(struct timespec now)
+{
+       struct rtc_device *rtc;
+       struct rtc_time tm;
+       int err = -ENODEV;
+
+       if (now.tv_nsec < (NSEC_PER_SEC >> 1))
+               rtc_time_to_tm(now.tv_sec, &tm);
+       else
+               rtc_time_to_tm(now.tv_sec + 1, &tm);
+
+       rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+       if (rtc) {
+               /* rtc_hctosys exclusively uses UTC, so we call set_time here,
+                * not set_mmss. */
+               if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss))
+                       err = rtc_set_time(rtc, &tm);
+               rtc_class_close(rtc);
+       }
+
+       return err;
+}
index 9bd5da36f99eb2d3a36642b05508d5578f473846..704488d0f819e70a762e7bda9eef25e9067bc2bc 100644 (file)
@@ -248,7 +248,7 @@ static void dasd_ext_handler(struct ext_code ext_code,
        default:
                return;
        }
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
+       inc_irq_stat(IRQEXT_DSD);
        if (!ip) {              /* no intparm: unsolicited interrupt */
                DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
                              "interrupt");
index 806fe912d6e779ad7456b35f175269352f56e8d6..e37bc1620d143dd12d390d489f76fb127aec059f 100644 (file)
@@ -4274,7 +4274,7 @@ static struct ccw_driver dasd_eckd_driver = {
        .thaw        = dasd_generic_restore_device,
        .restore     = dasd_generic_restore_device,
        .uc_handler  = dasd_generic_uc_handler,
-       .int_class   = IOINT_DAS,
+       .int_class   = IRQIO_DAS,
 };
 
 /*
index eb748507c7fac2b81f7d3d2028a2f11c47aaa854..4146985843444d46da0db635edc357e9076dede4 100644 (file)
@@ -78,7 +78,7 @@ static struct ccw_driver dasd_fba_driver = {
        .freeze      = dasd_generic_pm_freeze,
        .thaw        = dasd_generic_restore_device,
        .restore     = dasd_generic_restore_device,
-       .int_class   = IOINT_DAS,
+       .int_class   = IRQIO_DAS,
 };
 
 static void
index 40084501c31b7a28d2a436353a16e906c5d3640f..33b7141a182f6ef369ef9475f1a9f5293561cd2c 100644 (file)
@@ -44,6 +44,7 @@
 #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 */
@@ -630,7 +631,8 @@ static void raw3215_shutdown(struct raw3215_info *raw)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
 
-       if (!(raw->port.flags & ASYNC_INITIALIZED))
+       if (!(raw->port.flags & ASYNC_INITIALIZED) ||
+           (raw->flags & RAW3215_FIXED))
                return;
        /* Wait for outstanding requests, then free irq */
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -805,7 +807,7 @@ static struct ccw_driver raw3215_ccw_driver = {
        .freeze         = &raw3215_pm_stop,
        .thaw           = &raw3215_pm_start,
        .restore        = &raw3215_pm_start,
-       .int_class      = IOINT_C15,
+       .int_class      = IRQIO_C15,
 };
 
 #ifdef CONFIG_TN3215_CONSOLE
@@ -927,6 +929,8 @@ 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 f3b8bb84faf295013c03c1d4e539ee967015fa2a..9a6c140c5f072133c7f70281387236428f506d7d 100644 (file)
@@ -1396,7 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = {
        .freeze         = &raw3270_pm_stop,
        .thaw           = &raw3270_pm_start,
        .restore        = &raw3270_pm_start,
-       .int_class      = IOINT_C70,
+       .int_class      = IRQIO_C70,
 };
 
 static int
index 4fa21f7e23085aafbdef58ce7d4805e07418118c..12c16a65dd25ee778e693a36d31d54f782e2ea3a 100644 (file)
@@ -400,7 +400,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code,
        u32 finished_sccb;
        u32 evbuf_pending;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
+       inc_irq_stat(IRQEXT_SCP);
        spin_lock(&sclp_lock);
        finished_sccb = param32 & 0xfffffff8;
        evbuf_pending = param32 & 0x3;
@@ -813,7 +813,7 @@ static void sclp_check_handler(struct ext_code ext_code,
 {
        u32 finished_sccb;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
+       inc_irq_stat(IRQEXT_SCP);
        finished_sccb = param32 & 0xfffffff8;
        /* Is this the interrupt we are waiting for? */
        if (finished_sccb == 0)
index 6ae929c024ae3bf811ecabe4986301ac6b9a807b..9aa79702b3707a26ef0b4d370c54bf86b51251de 100644 (file)
@@ -1193,7 +1193,7 @@ static struct ccw_driver tape_34xx_driver = {
        .set_online = tape_34xx_online,
        .set_offline = tape_generic_offline,
        .freeze = tape_generic_pm_suspend,
-       .int_class = IOINT_TAP,
+       .int_class = IRQIO_TAP,
 };
 
 static int
index 1b0eb49f739c72413c5cdd43835c54141c2464e6..327cb19ad0b0c4df56dfe253a0eb0dd989c5a91c 100644 (file)
@@ -1656,7 +1656,7 @@ static struct ccw_driver tape_3590_driver = {
        .set_offline = tape_generic_offline,
        .set_online = tape_3590_online,
        .freeze = tape_generic_pm_suspend,
-       .int_class = IOINT_TAP,
+       .int_class = IRQIO_TAP,
 };
 
 /*
index 73bef0bd394cab2df006f64bf5e3c25ecce7bb3f..483f72ba030da670acb261774364f2cf0b896400 100644 (file)
@@ -74,7 +74,7 @@ static struct ccw_driver ur_driver = {
        .set_online     = ur_set_online,
        .set_offline    = ur_set_offline,
        .freeze         = ur_pm_suspend,
-       .int_class      = IOINT_VMR,
+       .int_class      = IRQIO_VMR,
 };
 
 static DEFINE_MUTEX(vmur_mutex);
index 68e80e2734a4be89763ca466a48621911570bce4..10729bbceceda4f49432e5eb647e04ae9d1399c4 100644 (file)
@@ -283,7 +283,7 @@ struct chsc_sei_nt2_area {
        u8  ccdf[PAGE_SIZE - 24 - 56];  /* content-code dependent field */
 } __packed;
 
-#define CHSC_SEI_NT0   0ULL
+#define CHSC_SEI_NT0   (1ULL << 63)
 #define CHSC_SEI_NT2   (1ULL << 61)
 
 struct chsc_sei {
@@ -291,7 +291,8 @@ struct chsc_sei {
        u32 reserved1;
        u64 ntsm;                       /* notification type mask */
        struct chsc_header response;
-       u32 reserved2;
+       u32 :24;
+       u8 nt;
        union {
                struct chsc_sei_nt0_area nt0_area;
                struct chsc_sei_nt2_area nt2_area;
@@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm)
                                css_schedule_eval_all();
                        }
 
-                       switch (sei->ntsm) {
-                       case CHSC_SEI_NT0:
+                       switch (sei->nt) {
+                       case 0:
                                chsc_process_sei_nt0(&sei->u.nt0_area);
-                               return 1;
-                       case CHSC_SEI_NT2:
+                               break;
+                       case 2:
                                chsc_process_sei_nt2(&sei->u.nt2_area);
-                               return 1;
+                               break;
                        default:
-                               CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n",
-                                             sei->ntsm);
-                               return 0;
+                               CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n",
+                                             sei->nt);
+                               break;
                        }
                } else {
                        CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
@@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
        sei = sei_page;
 
        CIO_TRACE_EVENT(2, "prcss");
-
-       /*
-        * The ntsm does not allow to select NT0 and NT2 together. We need to
-        * first check for NT2, than additionally for NT0...
-        */
-#ifdef CONFIG_PCI
-       if (!__chsc_process_crw(sei, CHSC_SEI_NT2))
-#endif
-               __chsc_process_crw(sei, CHSC_SEI_NT0);
+       __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2);
 }
 
 void chsc_chp_online(struct chp_id chpid)
index 8f9a1a384496eb396ce2b0cbcec28327ddb48d3f..facdf809113f22a6fe9e070b3f8938942bbaf480 100644 (file)
@@ -58,7 +58,7 @@ static void chsc_subchannel_irq(struct subchannel *sch)
 
        CHSC_LOG(4, "irb");
        CHSC_LOG_HEX(4, irb, sizeof(*irb));
-       kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++;
+       inc_irq_stat(IRQIO_CSC);
 
        /* Copy irb to provided request and set done. */
        if (!request) {
index 8e927b9f285f25de6ba520bf04f07661a02e51aa..c8faf6230b0f332010678f5c4aced898cb20b66d 100644 (file)
@@ -611,7 +611,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
        tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
        irb = (struct irb *)&S390_lowcore.irb;
        do {
-               kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
+               kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
                if (tpi_info->adapter_IO) {
                        do_adapter_IO(tpi_info->isc);
                        continue;
@@ -619,7 +619,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
                sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
                if (!sch) {
                        /* Clear pending interrupt condition. */
-                       kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+                       inc_irq_stat(IRQIO_CIO);
                        tsch(tpi_info->schid, irb);
                        continue;
                }
@@ -633,9 +633,9 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
                        if (sch->driver && sch->driver->irq)
                                sch->driver->irq(sch);
                        else
-                               kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+                               inc_irq_stat(IRQIO_CIO);
                } else
-                       kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+                       inc_irq_stat(IRQIO_CIO);
                spin_unlock(sch->lock);
                /*
                 * Are more interrupts pending?
@@ -678,7 +678,7 @@ static void cio_tsch(struct subchannel *sch)
        if (sch->driver && sch->driver->irq)
                sch->driver->irq(sch);
        else
-               kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+               inc_irq_stat(IRQIO_CIO);
        if (!irq_context) {
                irq_exit();
                _local_bh_enable();
index 6995cff44636a23dfe857098c2faca86670311fe..7cd5c6812ac7ce4d50f2068782f4426f546009df 100644 (file)
@@ -758,7 +758,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
                                        struct ccw_device *cdev)
 {
        cdev->private->cdev = cdev;
-       cdev->private->int_class = IOINT_CIO;
+       cdev->private->int_class = IRQIO_CIO;
        atomic_set(&cdev->private->onoff, 0);
        cdev->dev.parent = &sch->dev;
        cdev->dev.release = ccw_device_release;
@@ -1023,7 +1023,7 @@ static void io_subchannel_irq(struct subchannel *sch)
        if (cdev)
                dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
        else
-               kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+               inc_irq_stat(IRQIO_CIO);
 }
 
 void io_subchannel_init_config(struct subchannel *sch)
@@ -1634,7 +1634,7 @@ ccw_device_probe_console(void)
        memset(&console_private, 0, sizeof(struct ccw_device_private));
        console_cdev.private = &console_private;
        console_private.cdev = &console_cdev;
-       console_private.int_class = IOINT_CIO;
+       console_private.int_class = IRQIO_CIO;
        ret = ccw_device_console_enable(&console_cdev, sch);
        if (ret) {
                cio_release_console();
@@ -1715,13 +1715,13 @@ ccw_device_probe (struct device *dev)
        if (cdrv->int_class != 0)
                cdev->private->int_class = cdrv->int_class;
        else
-               cdev->private->int_class = IOINT_CIO;
+               cdev->private->int_class = IRQIO_CIO;
 
        ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
 
        if (ret) {
                cdev->drv = NULL;
-               cdev->private->int_class = IOINT_CIO;
+               cdev->private->int_class = IRQIO_CIO;
                return ret;
        }
 
@@ -1755,7 +1755,7 @@ ccw_device_remove (struct device *dev)
        }
        ccw_device_set_timeout(cdev, 0);
        cdev->drv = NULL;
-       cdev->private->int_class = IOINT_CIO;
+       cdev->private->int_class = IRQIO_CIO;
        return 0;
 }
 
index 2e575cff984549bbc90478663d6fcf3a23b10410..7d4ecb65db00cfab037ff4e4d6684570fcdf54e7 100644 (file)
@@ -61,11 +61,10 @@ dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event)
 
        if (dev_event == DEV_EVENT_INTERRUPT) {
                if (state == DEV_STATE_ONLINE)
-                       kstat_cpu(smp_processor_id()).
-                               irqs[cdev->private->int_class]++;
+                       inc_irq_stat(cdev->private->int_class);
                else if (state != DEV_STATE_CMFCHANGE &&
                         state != DEV_STATE_CMFUPDATE)
-                       kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+                       inc_irq_stat(IRQIO_CIO);
        }
        dev_jumptable[state][dev_event](cdev, dev_event);
 }
index 6c9673400464fdc89b3a462e21820961f1de049a..d9eddcba7e884d788a9d8c1f3dad14bc3d71cf77 100644 (file)
@@ -139,7 +139,7 @@ static void eadm_subchannel_irq(struct subchannel *sch)
        EADM_LOG(6, "irq");
        EADM_LOG_HEX(6, irb, sizeof(*irb));
 
-       kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++;
+       inc_irq_stat(IRQIO_ADM);
 
        if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))
            && scsw->eswf == 1 && irb->esw.eadm.erw.r)
index bdb394b066fcff56aac5588119c5ecc64efddf1f..bde5255200dc3864687fa955e69440503bd46b4b 100644 (file)
@@ -182,7 +182,7 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
        struct qdio_q *q;
 
        last_ai_time = S390_lowcore.int_clock;
-       kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++;
+       inc_irq_stat(IRQIO_QAI);
 
        /* protect tiq_list entries, only changed in activate or shutdown */
        rcu_read_lock();
index 7b865a7300e6a7da366762bf7b3882986fc462b3..b8b340ac53321f1028366d1a0cd18446050ed034 100644 (file)
@@ -1272,7 +1272,7 @@ out:
 
 static void ap_interrupt_handler(void *unused1, void *unused2)
 {
-       kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
+       inc_irq_stat(IRQIO_APB);
        tasklet_schedule(&ap_tasklet);
 }
 
index 7dabef624da394e6b90a2e04c787f74a4ffaa98d..8491111aec12d45b780243a907f71bb86adbfe17 100644 (file)
@@ -392,7 +392,7 @@ static void kvm_extint_handler(struct ext_code ext_code,
 
        if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64)
                return;
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
+       inc_irq_stat(IRQEXT_VRT);
 
        /* The LSB might be overloaded, we have to mask it */
        vq = (struct virtqueue *)(param64 & ~1UL);
index 5c70a6599578d6940faff2e1791e89ef4d4b769b..83bc9c5fa0c190885656955458b342d2265362f9 100644 (file)
@@ -282,7 +282,7 @@ static struct ccw_driver claw_ccw_driver = {
        .ids    = claw_ids,
        .probe  = ccwgroup_probe_ccwdev,
        .remove = ccwgroup_remove_ccwdev,
-       .int_class = IOINT_CLW,
+       .int_class = IRQIO_CLW,
 };
 
 static ssize_t claw_driver_group_store(struct device_driver *ddrv,
index 817b68925dddbd5c097129e6da6be7f41c77bdc8..676f12049a3693056d58ba216b0f1c3eeacdf92c 100644 (file)
@@ -1755,7 +1755,7 @@ static struct ccw_driver ctcm_ccw_driver = {
        .ids    = ctcm_ids,
        .probe  = ccwgroup_probe_ccwdev,
        .remove = ccwgroup_remove_ccwdev,
-       .int_class = IOINT_CTC,
+       .int_class = IRQIO_CTC,
 };
 
 static struct ccwgroup_driver ctcm_group_driver = {
index 2ca0f1dd7a00b857211348cf28d2c9e4a9df161a..c645dc9e98af83359d13b4975221a4d609ace853 100644 (file)
@@ -2384,7 +2384,7 @@ static struct ccw_driver lcs_ccw_driver = {
        .ids    = lcs_ids,
        .probe  = ccwgroup_probe_ccwdev,
        .remove = ccwgroup_remove_ccwdev,
-       .int_class = IOINT_LCS,
+       .int_class = IRQIO_LCS,
 };
 
 /**
index 542668292900fa9fe2e5afca92215f46104e0520..1a9d1e3ce64cc94aa36581fd29cefb6084f3502f 100644 (file)
@@ -355,7 +355,7 @@ fail:
 extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
 extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
 
-static int __devinit bbc_i2c_probe(struct platform_device *op)
+static int bbc_i2c_probe(struct platform_device *op)
 {
        struct bbc_i2c_bus *bp;
        int err, index = 0;
@@ -379,7 +379,7 @@ static int __devinit bbc_i2c_probe(struct platform_device *op)
        return err;
 }
 
-static int __devexit bbc_i2c_remove(struct platform_device *op)
+static int bbc_i2c_remove(struct platform_device *op)
 {
        struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev);
 
@@ -413,7 +413,7 @@ static struct platform_driver bbc_i2c_driver = {
                .of_match_table = bbc_i2c_match,
        },
        .probe          = bbc_i2c_probe,
-       .remove         = __devexit_p(bbc_i2c_remove),
+       .remove         = bbc_i2c_remove,
 };
 
 module_platform_driver(bbc_i2c_driver);
index b160073e54b65e76baa876f06720d4ab92ae160e..e85c803b30cdfd0362940a281f054d4d1b9644d6 100644 (file)
@@ -171,7 +171,7 @@ static struct miscdevice d7s_miscdev = {
        .fops           = &d7s_fops
 };
 
-static int __devinit d7s_probe(struct platform_device *op)
+static int d7s_probe(struct platform_device *op)
 {
        struct device_node *opts;
        int err = -EINVAL;
@@ -236,7 +236,7 @@ out_free:
        goto out;
 }
 
-static int __devexit d7s_remove(struct platform_device *op)
+static int d7s_remove(struct platform_device *op)
 {
        struct d7s *p = dev_get_drvdata(&op->dev);
        u8 regs = readb(p->regs);
@@ -272,7 +272,7 @@ static struct platform_driver d7s_driver = {
                .of_match_table = d7s_match,
        },
        .probe          = d7s_probe,
-       .remove         = __devexit_p(d7s_remove),
+       .remove         = d7s_remove,
 };
 
 module_platform_driver(d7s_driver);
index 0bc18569f9c0afe35c908ea2676cf59973538dae..ddbe5a9e713dfba93218ad886e5df1f49b9fd19c 100644 (file)
@@ -1028,7 +1028,7 @@ static int kenvctrld(void *__unused)
        return 0;
 }
 
-static int __devinit envctrl_probe(struct platform_device *op)
+static int envctrl_probe(struct platform_device *op)
 {
        struct device_node *dp;
        int index, err;
@@ -1104,7 +1104,7 @@ out_iounmap:
        return err;
 }
 
-static int __devexit envctrl_remove(struct platform_device *op)
+static int envctrl_remove(struct platform_device *op)
 {
        int index;
 
@@ -1135,7 +1135,7 @@ static struct platform_driver envctrl_driver = {
                .of_match_table = envctrl_match,
        },
        .probe          = envctrl_probe,
-       .remove         = __devexit_p(envctrl_remove),
+       .remove         = envctrl_remove,
 };
 
 module_platform_driver(envctrl_driver);
index 327657e2e2648ca79b8030e1c1218972076f8e90..d9f268f237749df06e63f11cec4c19c69326f995 100644 (file)
@@ -159,7 +159,7 @@ static const struct file_operations flash_fops = {
 
 static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
 
-static int __devinit flash_probe(struct platform_device *op)
+static int flash_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct device_node *parent;
@@ -190,7 +190,7 @@ static int __devinit flash_probe(struct platform_device *op)
        return misc_register(&flash_dev);
 }
 
-static int __devexit flash_remove(struct platform_device *op)
+static int flash_remove(struct platform_device *op)
 {
        misc_deregister(&flash_dev);
 
@@ -212,7 +212,7 @@ static struct platform_driver flash_driver = {
                .of_match_table = flash_match,
        },
        .probe          = flash_probe,
-       .remove         = __devexit_p(flash_remove),
+       .remove         = flash_remove,
 };
 
 module_platform_driver(flash_driver);
index a9e468cc1caca686f82459341fcaa13f71addbeb..b0aae0536d588441aee8409e200ba417a6080b39 100644 (file)
@@ -347,7 +347,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver)
        
 }
 
-static int __devinit uctrl_probe(struct platform_device *op)
+static int uctrl_probe(struct platform_device *op)
 {
        struct uctrl_driver *p;
        int err = -ENOMEM;
@@ -402,7 +402,7 @@ out_free:
        goto out;
 }
 
-static int __devexit uctrl_remove(struct platform_device *op)
+static int uctrl_remove(struct platform_device *op)
 {
        struct uctrl_driver *p = dev_get_drvdata(&op->dev);
 
@@ -430,7 +430,7 @@ static struct platform_driver uctrl_driver = {
                .of_match_table = uctrl_match,
        },
        .probe          = uctrl_probe,
-       .remove         = __devexit_p(uctrl_remove),
+       .remove         = uctrl_remove,
 };
 
 
index 3868ab2397c6bcb3418d7f2b8663739438e86809..d1f0120cdb98228bcea7ef0b638c6ee900c75233 100644 (file)
@@ -2029,7 +2029,7 @@ static struct scsi_host_template driver_template = {
 };
 
 /* This function will probe and initialize a card */
-static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
 {
        struct Scsi_Host *host = NULL;
        TW_Device_Extension *tw_dev;
@@ -2305,7 +2305,7 @@ out_disable_device:
 #endif
 
 /* PCI Devices supported by this driver */
-static struct pci_device_id twa_pci_tbl[] __devinitdata = {
+static struct pci_device_id twa_pci_tbl[] = {
        { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
index 13e39e1fdfe288b88e9aded1305e21240debc48e..52a2f0580d97502bfababc11ac7a30f36d8bf100 100644 (file)
@@ -1604,7 +1604,7 @@ static struct scsi_host_template driver_template = {
 };
 
 /* This function will probe and initialize a card */
-static int __devinit twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
 {
        struct Scsi_Host *host = NULL;
        TW_Device_Extension *tw_dev;
@@ -1893,7 +1893,7 @@ out_disable_device:
 #endif
 
 /* PCI Devices supported by this driver */
-static struct pci_device_id twl_pci_tbl[] __devinitdata = {
+static struct pci_device_id twl_pci_tbl[] = {
        { PCI_VDEVICE(3WARE, PCI_DEVICE_ID_3WARE_9750) },
        { }
 };
index 7fe96ff60c581c324a4eaecbf79d8c2e083bf7f8..62071d2fc1ce3a4e457edce2862b5d5da0bbf41f 100644 (file)
@@ -2281,7 +2281,7 @@ static struct scsi_host_template driver_template = {
 };
 
 /* This function will probe and initialize a card */
-static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
 {
        struct Scsi_Host *host = NULL;
        TW_Device_Extension *tw_dev;
@@ -2422,7 +2422,7 @@ static void tw_remove(struct pci_dev *pdev)
 } /* End tw_remove() */
 
 /* PCI Devices supported by this driver */
-static struct pci_device_id tw_pci_tbl[] __devinitdata = {
+static struct pci_device_id tw_pci_tbl[] = {
        { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_1000,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_7000,
index d4da3708763b7612ef5e7574578245c5e4534c1f..d7ca247efa35b3125fa2f3d0e67b967a600c4d15 100644 (file)
@@ -3615,7 +3615,7 @@ static void __exit BusLogic_exit(void)
 __setup("BusLogic=", BusLogic_Setup);
 
 #ifdef MODULE
-static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
+static struct pci_device_id BusLogic_pci_tbl[] = {
        { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
index 165e4dd865d9c025393a24ad8a349173952f290f..450353e04dde8b6ed03ad594b57f65705790bd48 100644 (file)
@@ -814,7 +814,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
  *     Locks: interrupts must be enabled when we are called 
  */
 
-static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
+static int NCR5380_init(struct Scsi_Host *instance, int flags)
 {
        NCR5380_local_declare();
        int i, pass;
index 8647256ad66df3540e0fee4c264c202ef9bc0eca..b39a2409a50716d3a554f3570363d2f8cd895cf1 100644 (file)
@@ -114,7 +114,7 @@ MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
 MODULE_LICENSE("GPL");
 module_param(NCR_D700, charp, 0);
 
-static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
+static __u8 id_array[2*(MCA_MAX_SLOT_NR + 1)] =
        { [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
 
 #ifdef MODULE
@@ -173,7 +173,7 @@ struct NCR_D700_private {
        char                    pad;
 };
 
-static int __devinit
+static int
 NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
                   int slot, u32 region, int differential)
 {
@@ -243,7 +243,7 @@ NCR_D700_intr(int irq, void *data)
  * essentially connectecd to the MCA bus independently, it is easier
  * to set them up as two separate host adapters, rather than one
  * adapter with two channels */
-static int __devinit
+static int
 NCR_D700_probe(struct device *dev)
 {
        struct NCR_D700_private *p;
@@ -349,7 +349,7 @@ NCR_D700_probe(struct device *dev)
        return 0;
 }
 
-static void __devexit
+static void
 NCR_D700_remove_one(struct Scsi_Host *host)
 {
        scsi_remove_host(host);
@@ -359,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
        release_region(host->base, 64);
 }
 
-static int __devexit
+static int
 NCR_D700_remove(struct device *dev)
 {
        struct NCR_D700_private *p = dev_get_drvdata(dev);
@@ -380,7 +380,7 @@ static struct mca_driver NCR_D700_driver = {
                .name           = "NCR_D700",
                .bus            = &mca_bus_type,
                .probe          = NCR_D700_probe,
-               .remove         = __devexit_p(NCR_D700_remove),
+               .remove         = NCR_D700_remove,
        },
 };
 
index afdbb9addf18aec48ba703152ce24e258de74129..05835bf1bf9cf271bdb1190a411b1d3378f08e80 100644 (file)
@@ -351,7 +351,7 @@ static struct mca_driver NCR_Q720_driver = {
                .name           = "NCR_Q720",
                .bus            = &mca_bus_type,
                .probe          = NCR_Q720_probe,
-               .remove         = __devexit_p(NCR_Q720_remove),
+               .remove         = NCR_Q720_remove,
        },
 };
 
index a391090a17c5ba73efa23384e360deba12733354..0163457c12bba0abe5859ddc67a99a3dc55338f4 100644 (file)
@@ -1082,8 +1082,8 @@ static struct scsi_host_template inia100_template = {
        .use_clustering         = ENABLE_CLUSTERING,
 };
 
-static int __devinit inia100_probe_one(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int inia100_probe_one(struct pci_dev *pdev,
+                            const struct pci_device_id *id)
 {
        struct Scsi_Host *shost;
        struct orc_host *host;
@@ -1197,7 +1197,7 @@ out:
        return error;
 }
 
-static void __devexit inia100_remove_one(struct pci_dev *pdev)
+static void inia100_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct orc_host *host = (struct orc_host *)shost->hostdata;
@@ -1224,7 +1224,7 @@ static struct pci_driver inia100_pci_driver = {
        .name           = "inia100",
        .id_table       = inia100_pci_tbl,
        .probe          = inia100_probe_one,
-       .remove         = __devexit_p(inia100_remove_one),
+       .remove         = inia100_remove_one,
 };
 
 static int __init inia100_init(void)
index 79a30633d4aa1d9af1cf69f5ae27c2ee666e4d87..3e09aa21c1ca787141aa7f02d08a4aa50dfce7a3 100644 (file)
@@ -179,8 +179,7 @@ static struct scsi_host_template a2091_scsi_template = {
        .use_clustering         = DISABLE_CLUSTERING
 };
 
-static int __devinit a2091_probe(struct zorro_dev *z,
-                                const struct zorro_device_id *ent)
+static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
 {
        struct Scsi_Host *instance;
        int error;
@@ -239,7 +238,7 @@ fail_alloc:
        return error;
 }
 
-static void __devexit a2091_remove(struct zorro_dev *z)
+static void a2091_remove(struct zorro_dev *z)
 {
        struct Scsi_Host *instance = zorro_get_drvdata(z);
        struct a2091_hostdata *hdata = shost_priv(instance);
@@ -251,7 +250,7 @@ static void __devexit a2091_remove(struct zorro_dev *z)
        release_mem_region(z->resource.start, 256);
 }
 
-static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id a2091_zorro_tbl[] = {
        { ZORRO_PROD_CBM_A590_A2091_1 },
        { ZORRO_PROD_CBM_A590_A2091_2 },
        { 0 }
@@ -262,7 +261,7 @@ static struct zorro_driver a2091_driver = {
        .name           = "a2091",
        .id_table       = a2091_zorro_tbl,
        .probe          = a2091_probe,
-       .remove         = __devexit_p(a2091_remove),
+       .remove         = a2091_remove,
 };
 
 static int __init a2091_init(void)
index cb7f1582a6d158ebc41e1ca1e6dcb4b390d098ba..408a42ef787a32b6d8fece98c717376ce93c1270 100644 (file)
@@ -88,13 +88,7 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
  *
  * Note: The last field is used to index into aac_drivers below.
  */
-#ifdef DECLARE_PCI_DEVICE_TABLE
-static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
-#elif defined(__devinitconst)
-static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
-#else
-static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
-#endif
+static const struct pci_device_id aac_pci_tbl[] = {
        { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
        { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
        { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */
@@ -1107,8 +1101,7 @@ static void __aac_shutdown(struct aac_dev * aac)
                pci_disable_msi(aac->pdev);
 }
 
-static int __devinit aac_probe_one(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        unsigned index = id->driver_data;
        struct Scsi_Host *shost;
@@ -1310,7 +1303,7 @@ static void aac_shutdown(struct pci_dev *dev)
        __aac_shutdown((struct aac_dev *)shost->hostdata);
 }
 
-static void __devexit aac_remove_one(struct pci_dev *pdev)
+static void aac_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
@@ -1341,7 +1334,7 @@ static struct pci_driver aac_pci_driver = {
        .name           = AAC_DRIVERNAME,
        .id_table       = aac_pci_tbl,
        .probe          = aac_probe_one,
-       .remove         = __devexit_p(aac_remove_one),
+       .remove         = aac_remove_one,
        .shutdown       = aac_shutdown,
 };
 
index 374c4edf4fcbc2a62f82d30e0b38bb2313a471ab..dcfaee66a8b932eed7457e25b0932cbbad7405f5 100644 (file)
@@ -9526,7 +9526,7 @@ advansys_queuecommand_lck(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *
 
 static DEF_SCSI_QCMD(advansys_queuecommand)
 
-static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
+static ushort AscGetEisaChipCfg(PortAddr iop_base)
 {
        PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
            (PortAddr) (ASC_EISA_CFG_IOP_MASK);
@@ -9537,8 +9537,8 @@ static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
  */
-static unsigned short __devinit
-AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
+static unsigned short AscGetChipBiosAddress(PortAddr iop_base,
+                                           unsigned short bus_type)
 {
        unsigned short cfg_lsw;
        unsigned short bios_addr;
@@ -9569,7 +9569,7 @@ AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
        return bios_addr;
 }
 
-static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
+static uchar AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
 {
        ushort cfg_lsw;
 
@@ -9583,7 +9583,7 @@ static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
        return (AscGetChipScsiID(iop_base));
 }
 
-static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
+static unsigned char AscGetChipScsiCtrl(PortAddr iop_base)
 {
        unsigned char sc;
 
@@ -9593,8 +9593,8 @@ static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
        return sc;
 }
 
-static unsigned char __devinit
-AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
+static unsigned char AscGetChipVersion(PortAddr iop_base,
+                                      unsigned short bus_type)
 {
        if (bus_type & ASC_IS_EISA) {
                PortAddr eisa_iop;
@@ -9608,7 +9608,7 @@ AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
 }
 
 #ifdef CONFIG_ISA
-static void __devinit AscEnableIsaDma(uchar dma_channel)
+static void AscEnableIsaDma(uchar dma_channel)
 {
        if (dma_channel < 4) {
                outp(0x000B, (ushort)(0xC0 | dma_channel));
@@ -9638,7 +9638,7 @@ static int AscStopQueueExe(PortAddr iop_base)
        return (0);
 }
 
-static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
+static ASC_DCNT AscGetMaxDmaCount(ushort bus_type)
 {
        if (bus_type & ASC_IS_ISA)
                return ASC_MAX_ISA_DMA_COUNT;
@@ -9648,7 +9648,7 @@ static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
 }
 
 #ifdef CONFIG_ISA
-static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
+static ushort AscGetIsaDmaChannel(PortAddr iop_base)
 {
        ushort channel;
 
@@ -9660,7 +9660,7 @@ static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
        return (channel + 4);
 }
 
-static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
+static ushort AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
 {
        ushort cfg_lsw;
        uchar value;
@@ -9678,7 +9678,7 @@ static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channe
        return 0;
 }
 
-static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
+static uchar AscGetIsaDmaSpeed(PortAddr iop_base)
 {
        uchar speed_value;
 
@@ -9689,7 +9689,7 @@ static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
        return speed_value;
 }
 
-static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
+static uchar AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
 {
        speed_value &= 0x07;
        AscSetBank(iop_base, 1);
@@ -9699,7 +9699,7 @@ static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
 }
 #endif /* CONFIG_ISA */
 
-static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
+static ushort AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
 {
        int i;
        PortAddr iop_base;
@@ -9786,7 +9786,7 @@ static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
        return warn_code;
 }
 
-static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
+static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
 {
        int retry;
 
@@ -9801,12 +9801,12 @@ static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
        return 0;
 }
 
-static void __devinit AscWaitEEPRead(void)
+static void AscWaitEEPRead(void)
 {
        mdelay(1);
 }
 
-static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
+static ushort AscReadEEPWord(PortAddr iop_base, uchar addr)
 {
        ushort read_wval;
        uchar cmd_reg;
@@ -9821,8 +9821,8 @@ static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
        return read_wval;
 }
 
-static ushort __devinit
-AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static ushort AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+                             ushort bus_type)
 {
        ushort wval;
        ushort sum;
@@ -9868,7 +9868,7 @@ AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
        return sum;
 }
 
-static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
+static int AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
 {
        PortAddr iop_base;
        ushort q_addr;
@@ -9890,12 +9890,12 @@ static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
        return (sta);
 }
 
-static void __devinit AscWaitEEPWrite(void)
+static void AscWaitEEPWrite(void)
 {
        mdelay(20);
 }
 
-static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
+static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
 {
        ushort read_back;
        int retry;
@@ -9914,8 +9914,7 @@ static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
        }
 }
 
-static ushort __devinit
-AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
+static ushort AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
 {
        ushort read_wval;
 
@@ -9935,8 +9934,8 @@ AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
        return (read_wval);
 }
 
-static int __devinit
-AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static int AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+                              ushort bus_type)
 {
        int n_error;
        ushort *wbuf;
@@ -10031,8 +10030,8 @@ AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
        return n_error;
 }
 
-static int __devinit
-AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
+static int AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf,
+                          ushort bus_type)
 {
        int retry;
        int n_error;
@@ -10050,7 +10049,7 @@ AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
        return n_error;
 }
 
-static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
+static ushort AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
 {
        ASCEEP_CONFIG eep_config_buf;
        ASCEEP_CONFIG *eep_config;
@@ -10215,7 +10214,7 @@ static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
        return (warn_code);
 }
 
-static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
+static int AscInitGetConfig(struct Scsi_Host *shost)
 {
        struct asc_board *board = shost_priv(shost);
        ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
@@ -10269,7 +10268,7 @@ static int __devinit AscInitGetConfig(struct Scsi_Host *shost)
        return asc_dvc->err_code;
 }
 
-static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
+static int AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
 {
        struct asc_board *board = shost_priv(shost);
        ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var;
@@ -10383,7 +10382,7 @@ static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *sh
  * on big-endian platforms so char fields read as words are actually being
  * unswapped on big-endian platforms.
  */
-static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config = {
        ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
        0x0000,                 /* cfg_msw */
        0xFFFF,                 /* disc_enable */
@@ -10421,7 +10420,7 @@ static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
        0                       /* num_of_err */
 };
 
-static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
+static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar = {
        0,                      /* cfg_lsw */
        0,                      /* cfg_msw */
        0,                      /* -disc_enable */
@@ -10459,7 +10458,7 @@ static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
        0                       /* num_of_err */
 };
 
-static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config = {
        ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
        0x0000,                 /* 01 cfg_msw */
        0xFFFF,                 /* 02 disc_enable */
@@ -10524,7 +10523,7 @@ static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
        0                       /* 63 reserved */
 };
 
-static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
+static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar = {
        0,                      /* 00 cfg_lsw */
        0,                      /* 01 cfg_msw */
        0,                      /* 02 disc_enable */
@@ -10589,7 +10588,7 @@ static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata =
        0                       /* 63 reserved */
 };
 
-static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config = {
        ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
        0x0000,                 /* 01 cfg_msw */
        0xFFFF,                 /* 02 disc_enable */
@@ -10654,7 +10653,7 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
        0                       /* 63 reserved */
 };
 
-static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
+static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar = {
        0,                      /* 00 cfg_lsw */
        0,                      /* 01 cfg_msw */
        0,                      /* 02 disc_enable */
@@ -10723,7 +10722,7 @@ static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata =
 /*
  * Wait for EEPROM command to complete
  */
-static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
+static void AdvWaitEEPCmd(AdvPortAddr iop_base)
 {
        int eep_delay_ms;
 
@@ -10742,7 +10741,7 @@ static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
 /*
  * Read the EEPROM from specified location
  */
-static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
+static ushort AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
 {
        AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
                             ASC_EEP_CMD_READ | eep_word_addr);
@@ -10753,8 +10752,8 @@ static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-static void __devinit
-AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+static void AdvSet3550EEPConfig(AdvPortAddr iop_base,
+                               ADVEEP_3550_CONFIG *cfg_buf)
 {
        ushort *wbuf;
        ushort addr, chksum;
@@ -10820,8 +10819,8 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-static void __devinit
-AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
+static void AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
+                                  ADVEEP_38C0800_CONFIG *cfg_buf)
 {
        ushort *wbuf;
        ushort *charfields;
@@ -10887,8 +10886,8 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-static void __devinit
-AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+static void AdvSet38C1600EEPConfig(AdvPortAddr iop_base,
+                                  ADVEEP_38C1600_CONFIG *cfg_buf)
 {
        ushort *wbuf;
        ushort *charfields;
@@ -10956,8 +10955,8 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-static ushort __devinit
-AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
+static ushort AdvGet3550EEPConfig(AdvPortAddr iop_base,
+                                 ADVEEP_3550_CONFIG *cfg_buf)
 {
        ushort wval, chksum;
        ushort *wbuf;
@@ -10999,8 +10998,8 @@ AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-static ushort __devinit
-AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
+static ushort AdvGet38C0800EEPConfig(AdvPortAddr iop_base,
+                                    ADVEEP_38C0800_CONFIG *cfg_buf)
 {
        ushort wval, chksum;
        ushort *wbuf;
@@ -11042,8 +11041,8 @@ AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-static ushort __devinit
-AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
+static ushort AdvGet38C1600EEPConfig(AdvPortAddr iop_base,
+                                    ADVEEP_38C1600_CONFIG *cfg_buf)
 {
        ushort wval, chksum;
        ushort *wbuf;
@@ -11092,7 +11091,7 @@ AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
  *
  * Note: Chip is stopped on entry.
  */
-static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
 {
        AdvPortAddr iop_base;
        ushort warn_code;
@@ -11242,7 +11241,7 @@ static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
  *
  * Note: Chip is stopped on entry.
  */
-static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
 {
        AdvPortAddr iop_base;
        ushort warn_code;
@@ -11441,7 +11440,7 @@ static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
  *
  * Note: Chip is stopped on entry.
  */
-static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
+static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
 {
        AdvPortAddr iop_base;
        ushort warn_code;
@@ -11661,8 +11660,7 @@ static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
  * For a non-fatal error return a warning code. If there are no warnings
  * then 0 is returned.
  */
-static int __devinit
-AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
+static int AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost)
 {
        struct asc_board *board = shost_priv(shost);
        ADV_DVC_VAR *asc_dvc = &board->dvc_var.adv_dvc_var;
@@ -11769,7 +11767,7 @@ static struct scsi_host_template advansys_template = {
        .use_clustering = ENABLE_CLUSTERING,
 };
 
-static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost)
+static int advansys_wide_init_chip(struct Scsi_Host *shost)
 {
        struct asc_board *board = shost_priv(shost);
        struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
@@ -11882,8 +11880,8 @@ static void advansys_wide_free_mem(struct asc_board *board)
        }
 }
 
-static int __devinit advansys_board_found(struct Scsi_Host *shost,
-                                         unsigned int iop, int bus_type)
+static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
+                               int bus_type)
 {
        struct pci_dev *pdev;
        struct asc_board *boardp = shost_priv(shost);
@@ -12428,7 +12426,7 @@ static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] = {
  * 10: 12
  * 11: 15
  */
-static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
+static unsigned int advansys_isa_irq_no(PortAddr iop_base)
 {
        unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
        unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10;
@@ -12437,7 +12435,7 @@ static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base)
        return chip_irq;
 }
 
-static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
+static int advansys_isa_probe(struct device *dev, unsigned int id)
 {
        int err = -ENODEV;
        PortAddr iop_base = _asc_def_iop_base[id];
@@ -12477,7 +12475,7 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
        return err;
 }
 
-static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
+static int advansys_isa_remove(struct device *dev, unsigned int id)
 {
        int ioport = _asc_def_iop_base[id];
        advansys_release(dev_get_drvdata(dev));
@@ -12487,7 +12485,7 @@ static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
 
 static struct isa_driver advansys_isa_driver = {
        .probe          = advansys_isa_probe,
-       .remove         = __devexit_p(advansys_isa_remove),
+       .remove         = advansys_isa_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = DRV_NAME,
@@ -12505,7 +12503,7 @@ static struct isa_driver advansys_isa_driver = {
  * 110: 15
  * 111: invalid
  */
-static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
+static unsigned int advansys_vlb_irq_no(PortAddr iop_base)
 {
        unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base);
        unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9;
@@ -12514,7 +12512,7 @@ static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base)
        return chip_irq;
 }
 
-static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
+static int advansys_vlb_probe(struct device *dev, unsigned int id)
 {
        int err = -ENODEV;
        PortAddr iop_base = _asc_def_iop_base[id];
@@ -12561,14 +12559,14 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
 
 static struct isa_driver advansys_vlb_driver = {
        .probe          = advansys_vlb_probe,
-       .remove         = __devexit_p(advansys_isa_remove),
+       .remove         = advansys_isa_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "advansys_vlb",
        },
 };
 
-static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
+static struct eisa_device_id advansys_eisa_table[] = {
        { "ABP7401" },
        { "ABP7501" },
        { "" }
@@ -12595,7 +12593,7 @@ struct eisa_scsi_data {
  * 110: invalid
  * 111: invalid
  */
-static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
+static unsigned int advansys_eisa_irq_no(struct eisa_device *edev)
 {
        unsigned short cfg_lsw = inw(edev->base_addr + 0xc86);
        unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10;
@@ -12604,7 +12602,7 @@ static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev)
        return chip_irq;
 }
 
-static int __devinit advansys_eisa_probe(struct device *dev)
+static int advansys_eisa_probe(struct device *dev)
 {
        int i, ioport, irq = 0;
        int err;
@@ -12677,7 +12675,7 @@ static int __devinit advansys_eisa_probe(struct device *dev)
        return err;
 }
 
-static __devexit int advansys_eisa_remove(struct device *dev)
+static int advansys_eisa_remove(struct device *dev)
 {
        int i;
        struct eisa_scsi_data *data = dev_get_drvdata(dev);
@@ -12701,12 +12699,12 @@ static struct eisa_driver advansys_eisa_driver = {
        .driver = {
                .name =         DRV_NAME,
                .probe =        advansys_eisa_probe,
-               .remove =       __devexit_p(advansys_eisa_remove),
+               .remove =       advansys_eisa_remove,
        }
 };
 
 /* PCI Devices supported by this driver */
-static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
+static struct pci_device_id advansys_pci_tbl[] = {
        {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
@@ -12724,7 +12722,7 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
 
-static void __devinit advansys_set_latency(struct pci_dev *pdev)
+static void advansys_set_latency(struct pci_dev *pdev)
 {
        if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
            (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
@@ -12737,8 +12735,8 @@ static void __devinit advansys_set_latency(struct pci_dev *pdev)
        }
 }
 
-static int __devinit
-advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int advansys_pci_probe(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        int err, ioport;
        struct Scsi_Host *shost;
@@ -12791,7 +12789,7 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return err;
 }
 
-static void __devexit advansys_pci_remove(struct pci_dev *pdev)
+static void advansys_pci_remove(struct pci_dev *pdev)
 {
        advansys_release(pci_get_drvdata(pdev));
        pci_release_regions(pdev);
@@ -12802,7 +12800,7 @@ static struct pci_driver advansys_pci_driver = {
        .name =         DRV_NAME,
        .id_table =     advansys_pci_tbl,
        .probe =        advansys_pci_probe,
-       .remove =       __devexit_p(advansys_pci_remove),
+       .remove =       advansys_pci_remove,
 };
 
 static int __init advansys_init(void)
index dd4547bf688122b4775428ee5c01539b936f9259..a284be17699f32ce37e7315adbc56d512d75b19e 100644 (file)
@@ -420,7 +420,7 @@ MODULE_PARM_DESC(aha152x1, "parameters for second controller");
 #endif /* MODULE */
 
 #ifdef __ISAPNP__
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
        { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
        { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
        { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
index a3e6ed353917f9018f2613db4095101199eb6fae..df775e6ba5796c6cc8be7ed53a50fd4f269e73ac 100644 (file)
@@ -646,7 +646,7 @@ static int aha1740_probe (struct device *dev)
        return -ENODEV;
 }
 
-static __devexit int aha1740_remove (struct device *dev)
+static int aha1740_remove (struct device *dev)
 {
        struct Scsi_Host *shpnt = dev_get_drvdata(dev);
        struct aha1740_hostdata *host = HOSTDATA (shpnt);
@@ -677,7 +677,7 @@ static struct eisa_driver aha1740_driver = {
        .driver   = {
                .name    = "aha1740",
                .probe   = aha1740_probe,
-               .remove  = __devexit_p (aha1740_remove),
+               .remove  = aha1740_remove,
        },
 };
 
index 1c4120c3db41f622fc4277c6d7e549c71a3a18b5..c56741fc4b994ad38138261b63444d28f22c3fc8 100644 (file)
@@ -85,7 +85,7 @@ static struct scsi_host_template aic94xx_sht = {
        .ioctl                  = sas_ioctl,
 };
 
-static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
+static int asd_map_memio(struct asd_ha_struct *asd_ha)
 {
        int err, i;
        struct asd_ha_addrspace *io_handle;
@@ -146,7 +146,7 @@ static void asd_unmap_memio(struct asd_ha_struct *asd_ha)
        pci_release_region(asd_ha->pcidev, 0);
 }
 
-static int __devinit asd_map_ioport(struct asd_ha_struct *asd_ha)
+static int asd_map_ioport(struct asd_ha_struct *asd_ha)
 {
        int i = PCI_IOBAR_OFFSET, err;
        struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];
@@ -175,7 +175,7 @@ static void asd_unmap_ioport(struct asd_ha_struct *asd_ha)
        pci_release_region(asd_ha->pcidev, PCI_IOBAR_OFFSET);
 }
 
-static int __devinit asd_map_ha(struct asd_ha_struct *asd_ha)
+static int asd_map_ha(struct asd_ha_struct *asd_ha)
 {
        int err;
        u16 cmd_reg;
@@ -221,7 +221,7 @@ static const char *asd_dev_rev[30] = {
        [8] = "B0",
 };
 
-static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha)
+static int asd_common_setup(struct asd_ha_struct *asd_ha)
 {
        int err, i;
 
@@ -257,7 +257,7 @@ Err:
        return err;
 }
 
-static int __devinit asd_aic9410_setup(struct asd_ha_struct *asd_ha)
+static int asd_aic9410_setup(struct asd_ha_struct *asd_ha)
 {
        int err = asd_common_setup(asd_ha);
 
@@ -272,7 +272,7 @@ static int __devinit asd_aic9410_setup(struct asd_ha_struct *asd_ha)
        return 0;
 }
 
-static int __devinit asd_aic9405_setup(struct asd_ha_struct *asd_ha)
+static int asd_aic9405_setup(struct asd_ha_struct *asd_ha)
 {
        int err = asd_common_setup(asd_ha);
 
@@ -531,7 +531,7 @@ static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
 static const struct asd_pcidev_struct {
        const char * name;
        int (*setup)(struct asd_ha_struct *asd_ha);
-} asd_pcidev_data[] __devinitconst = {
+} asd_pcidev_data[] = {
        /* Id 0 is used for dynamic ids. */
        { .name  = "Adaptec AIC-94xx SAS/SATA Host Adapter",
          .setup = asd_aic9410_setup
@@ -731,8 +731,7 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
        return err;
 }
 
-static int __devinit asd_pci_probe(struct pci_dev *dev,
-                                  const struct pci_device_id *id)
+static int asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        const struct asd_pcidev_struct *asd_dev;
        unsigned asd_id = (unsigned) id->driver_data;
@@ -924,7 +923,7 @@ static void asd_turn_off_leds(struct asd_ha_struct *asd_ha)
        }
 }
 
-static void __devexit asd_pci_remove(struct pci_dev *dev)
+static void asd_pci_remove(struct pci_dev *dev)
 {
        struct asd_ha_struct *asd_ha = pci_get_drvdata(dev);
 
@@ -1012,7 +1011,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
        .lldd_ata_set_dmamode   = asd_set_dmamode,
 };
 
-static const struct pci_device_id aic94xx_pci_table[] __devinitconst = {
+static const struct pci_device_id aic94xx_pci_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},
@@ -1031,7 +1030,7 @@ static struct pci_driver aic94xx_pci_driver = {
        .name           = ASD_DRIVER_NAME,
        .id_table       = aic94xx_pci_table,
        .probe          = asd_pci_probe,
-       .remove         = __devexit_p(asd_pci_remove),
+       .remove         = asd_pci_remove,
 };
 
 static int __init aic94xx_init(void)
index b330438ac662631bdc720426fdb7cad5a539cd4c..3e1172adb37b0a9d012c6afba811bcbb033fb80b 100644 (file)
@@ -2965,8 +2965,7 @@ static struct scsi_host_template acornscsi_template = {
        .proc_name              = "acornscsi",
 };
 
-static int __devinit
-acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        AS_Host *ashost;
@@ -3032,7 +3031,7 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit acornscsi_remove(struct expansion_card *ec)
+static void acornscsi_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
        AS_Host *ashost = (AS_Host *)host->hostdata;
@@ -3063,7 +3062,7 @@ static const struct ecard_id acornscsi_cids[] = {
 
 static struct ecard_driver acornscsi_driver = {
        .probe          = acornscsi_probe,
-       .remove         = __devexit_p(acornscsi_remove),
+       .remove         = acornscsi_remove,
        .id_table       = acornscsi_cids,
        .drv = {
                .name           = "acornscsi",
index 2a28b4ad1975b8f66bb846f41f5928bfdaf880d3..9274510294acaf74c72e9980d2147863000c7303 100644 (file)
@@ -276,8 +276,7 @@ static struct scsi_host_template arxescsi_template = {
        .proc_name                      = "arxescsi",
 };
 
-static int __devinit
-arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        struct arxescsi_info *info;
@@ -340,7 +339,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit arxescsi_remove(struct expansion_card *ec)
+static void arxescsi_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
 
@@ -359,7 +358,7 @@ static const struct ecard_id arxescsi_cids[] = {
 
 static struct ecard_driver arxescsi_driver = {
        .probe          = arxescsi_probe,
-       .remove         = __devexit_p(arxescsi_remove),
+       .remove         = arxescsi_remove,
        .id_table       = arxescsi_cids,
        .drv = {
                .name           = "arxescsi",
index c3b99c93637aaa1ec958fe0dde1c2b9998226ccb..c93938b246d59c29ec2414b05c1749b216b5b128 100644 (file)
@@ -225,8 +225,8 @@ static struct scsi_host_template cumanascsi_template = {
        .proc_name              = "CumanaSCSI-1",
 };
 
-static int __devinit
-cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int cumanascsi1_probe(struct expansion_card *ec,
+                            const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        int ret;
@@ -298,7 +298,7 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit cumanascsi1_remove(struct expansion_card *ec)
+static void cumanascsi1_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
 
@@ -320,7 +320,7 @@ static const struct ecard_id cumanascsi1_cids[] = {
 
 static struct ecard_driver cumanascsi1_driver = {
        .probe          = cumanascsi1_probe,
-       .remove         = __devexit_p(cumanascsi1_remove),
+       .remove         = cumanascsi1_remove,
        .id_table       = cumanascsi1_cids,
        .drv = {
                .name           = "cumanascsi1",
index 547987b86384e9fa693e43c0e5b27f23f52ae8b1..e3bae93c3c22c3a82efa0d337b3eea9a7a650b60 100644 (file)
@@ -397,8 +397,8 @@ static struct scsi_host_template cumanascsi2_template = {
        .proc_name                      = "cumanascsi2",
 };
 
-static int __devinit
-cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int cumanascsi2_probe(struct expansion_card *ec,
+                            const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        struct cumanascsi2_info *info;
@@ -495,7 +495,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit cumanascsi2_remove(struct expansion_card *ec)
+static void cumanascsi2_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
        struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
@@ -519,7 +519,7 @@ static const struct ecard_id cumanascsi2_cids[] = {
 
 static struct ecard_driver cumanascsi2_driver = {
        .probe          = cumanascsi2_probe,
-       .remove         = __devexit_p(cumanascsi2_remove),
+       .remove         = cumanascsi2_remove,
        .id_table       = cumanascsi2_cids,
        .drv = {
                .name           = "cumanascsi2",
index 968d08358d20684a0d23253ba008ecadf5e0a3b6..8e36908415ec3eecaf6743890e9656303376357c 100644 (file)
@@ -515,8 +515,7 @@ static struct scsi_host_template eesox_template = {
        .proc_name                      = "eesox",
 };
 
-static int __devinit
-eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        struct eesoxscsi_info *info;
@@ -617,7 +616,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit eesoxscsi_remove(struct expansion_card *ec)
+static void eesoxscsi_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
        struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
@@ -643,7 +642,7 @@ static const struct ecard_id eesoxscsi_cids[] = {
 
 static struct ecard_driver eesoxscsi_driver = {
        .probe          = eesoxscsi_probe,
-       .remove         = __devexit_p(eesoxscsi_remove),
+       .remove         = eesoxscsi_remove,
        .id_table       = eesoxscsi_cids,
        .drv = {
                .name           = "eesoxscsi",
index fc6a5aabf66eadf9a90d2e6c11e2cc45018d6f8a..48facdc18002d6e7a2e9eb27e30bfa79807d5eec 100644 (file)
@@ -129,8 +129,7 @@ static struct scsi_host_template oakscsi_template = {
        .proc_name              = "oakscsi",
 };
 
-static int __devinit
-oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        int ret = -ENOMEM;
@@ -182,7 +181,7 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit oakscsi_remove(struct expansion_card *ec)
+static void oakscsi_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
 
@@ -202,7 +201,7 @@ static const struct ecard_id oakscsi_cids[] = {
 
 static struct ecard_driver oakscsi_driver = {
        .probe          = oakscsi_probe,
-       .remove         = __devexit_p(oakscsi_remove),
+       .remove         = oakscsi_remove,
        .id_table       = oakscsi_cids,
        .drv = {
                .name           = "oakscsi",
index 9274c0677b9c1d38c8334a6a69c7dc66c2dd581b..246600b935550a450cf7c6d24ce91962ac61af8e 100644 (file)
@@ -309,8 +309,8 @@ static struct scsi_host_template powertecscsi_template = {
        .proc_name                      = "powertec",
 };
 
-static int __devinit
-powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
+static int powertecscsi_probe(struct expansion_card *ec,
+                             const struct ecard_id *id)
 {
        struct Scsi_Host *host;
        struct powertec_info *info;
@@ -409,7 +409,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit powertecscsi_remove(struct expansion_card *ec)
+static void powertecscsi_remove(struct expansion_card *ec)
 {
        struct Scsi_Host *host = ecard_get_drvdata(ec);
        struct powertec_info *info = (struct powertec_info *)host->hostdata;
@@ -435,7 +435,7 @@ static const struct ecard_id powertecscsi_cids[] = {
 
 static struct ecard_driver powertecscsi_driver = {
        .probe          = powertecscsi_probe,
-       .remove         = __devexit_p(powertecscsi_remove),
+       .remove         = powertecscsi_remove,
        .id_table       = powertecscsi_cids,
        .drv = {
                .name           = "powertecscsi",
index a540162ac59c1483bfd71c43a2384df4a1525529..cfc73041f102968198a2a858bbaf5478caf5b43e 100644 (file)
@@ -3210,7 +3210,7 @@ static struct pci_driver atp870u_driver = {
        .id_table       = atp870u_id_table,
        .name           = "atp870u",
        .probe          = atp870u_probe,
-       .remove         = __devexit_p(atp870u_remove),
+       .remove         = atp870u_remove,
 };
 
 static int __init atp870u_init(void)
index 48d37dded8f16fbd64290aa599b187d54b9baef3..4e2733d2300365761e7dba5df79e3a1b606c67e2 100644 (file)
@@ -4790,8 +4790,8 @@ beiscsi_hw_health_check(struct work_struct *work)
                              msecs_to_jiffies(1000));
 }
 
-static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
-                               const struct pci_device_id *id)
+static int beiscsi_dev_probe(struct pci_dev *pcidev,
+                            const struct pci_device_id *id)
 {
        struct beiscsi_hba *phba = NULL;
        struct hwi_controller *phwi_ctrlr;
index 895b0e516e07cfb6d724ae39bdb6fe2992583b79..e6bf12675db8d363f2f94a9483c2a3770e165ad9 100644 (file)
@@ -1739,7 +1739,7 @@ static struct pci_driver bfad_pci_driver = {
        .name = BFAD_DRIVER_NAME,
        .id_table = bfad_id_table,
        .probe = bfad_pci_probe,
-       .remove = __devexit_p(bfad_pci_remove),
+       .remove = bfad_pci_remove,
        .err_handler = &bfad_err_handler,
 };
 
index e0558656c6462ed30b3ef1b67816b128f4a4f584..70ecd953a5793e2990d4f9e32715e2ada15d22cb 100644 (file)
@@ -25,7 +25,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 #define DRV_MODULE_RELDATE     "Jun 04, 2012"
 
 
-static char version[] __devinitdata =
+static char version[] =
                "Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
                " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
index ee009e4ad097949785c677b9b343f3eeb8abbc7a..50fef6963a811baa61b1fbec94e250a4e7457179 100644 (file)
@@ -21,7 +21,7 @@ static u32 adapter_count;
 #define DRV_MODULE_VERSION     "2.7.2.2"
 #define DRV_MODULE_RELDATE     "Apr 25, 2012"
 
-static char version[] __devinitdata =
+static char version[] =
                "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
                " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
index d40ea2f5be106374a71d037b17eb7c91263b5e88..1e3f96adf9da9f6ab752211a5e54d7e0b0a2c1e8 100644 (file)
@@ -34,7 +34,7 @@ static struct scsi_host_template bvme6000_scsi_driver_template = {
 
 static struct platform_device *bvme6000_scsi_device;
 
-static __devinit int
+static int
 bvme6000_probe(struct platform_device *dev)
 {
        struct Scsi_Host *host;
@@ -88,7 +88,7 @@ bvme6000_probe(struct platform_device *dev)
        return -ENODEV;
 }
 
-static __devexit int
+static int
 bvme6000_device_remove(struct platform_device *dev)
 {
        struct Scsi_Host *host = platform_get_drvdata(dev);
@@ -108,7 +108,7 @@ static struct platform_driver bvme6000_scsi_driver = {
                .owner          = THIS_MODULE,
        },
        .probe          = bvme6000_probe,
-       .remove         = __devexit_p(bvme6000_device_remove),
+       .remove         = bvme6000_device_remove,
 };
 
 static int __init bvme6000_scsi_init(void)
index fdd408ff80ad9fb0681100b27c297a2fc143b24d..b42cbbd3d92dc3887ee809818825ed3a562262a0 100644 (file)
@@ -115,9 +115,8 @@ static const struct file_operations csio_mem_debugfs_fops = {
        .llseek  = default_llseek,
 };
 
-static void __devinit
-csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
-                    unsigned int idx, unsigned int size_mb)
+static void csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
+                                unsigned int idx, unsigned int size_mb)
 {
        struct dentry *de;
 
@@ -127,8 +126,7 @@ csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
                de->d_inode->i_size = size_mb << 20;
 }
 
-static int __devinit
-csio_setup_debugfs(struct csio_hw *hw)
+static int csio_setup_debugfs(struct csio_hw *hw)
 {
        int i;
 
@@ -531,8 +529,7 @@ csio_resource_free(struct csio_hw *hw)
  * Allocates HW structure, DMA, memory resources, maps BARS to
  * host memory and initializes HW module.
  */
-static struct csio_hw * __devinit
-csio_hw_alloc(struct pci_dev *pdev)
+static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev)
 {
        struct csio_hw *hw;
 
@@ -956,8 +953,7 @@ csio_lnode_init_post(struct csio_lnode *ln)
  * - Once hardware is ready, initiated scan of the host via
  *   scsi_scan_host.
  */
-static int __devinit
-csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int rv;
        int bars;
@@ -1036,8 +1032,7 @@ err:
  *
  * Used during hotplug operation.
  */
-static void __devexit
-csio_remove_one(struct pci_dev *pdev)
+static void csio_remove_one(struct pci_dev *pdev)
 {
        struct csio_hw *hw = pci_get_drvdata(pdev);
        int bars = pci_select_bars(pdev, IORESOURCE_MEM);
index 1223e0d5fc07d44a07719a1abe08116db06b9b2b..097e52c0f8e1da9c7d0c924dd154c4a8302d20fb 100644 (file)
  *   R E T U R N   V A L U E S
  ********************************/
 
-enum fw_retval {
-       FW_SUCCESS              = 0,    /* completed sucessfully */
-       FW_EPERM                = 1,    /* operation not permitted */
-       FW_ENOENT               = 2,    /* no such file or directory */
-       FW_EIO                  = 5,    /* input/output error; hw bad */
-       FW_ENOEXEC              = 8,    /* exec format error; inv microcode */
-       FW_EAGAIN               = 11,   /* try again */
-       FW_ENOMEM               = 12,   /* out of memory */
-       FW_EFAULT               = 14,   /* bad address; fw bad */
-       FW_EBUSY                = 16,   /* resource busy */
-       FW_EEXIST               = 17,   /* file exists */
-       FW_EINVAL               = 22,   /* invalid argument */
-       FW_ENOSPC               = 28,   /* no space left on device */
-       FW_ENOSYS               = 38,   /* functionality not implemented */
-       FW_EPROTO               = 71,   /* protocol error */
-       FW_EADDRINUSE           = 98,   /* address already in use */
-       FW_EADDRNOTAVAIL        = 99,   /* cannot assigned requested address */
-       FW_ENETDOWN             = 100,  /* network is down */
-       FW_ENETUNREACH          = 101,  /* network is unreachable */
-       FW_ENOBUFS              = 105,  /* no buffer space available */
-       FW_ETIMEDOUT            = 110,  /* timeout */
-       FW_EINPROGRESS          = 115,  /* fw internal */
-       FW_SCSI_ABORT_REQUESTED = 128,  /* */
-       FW_SCSI_ABORT_TIMEDOUT  = 129,  /* */
-       FW_SCSI_ABORTED         = 130,  /* */
-       FW_SCSI_CLOSE_REQUESTED = 131,  /* */
-       FW_ERR_LINK_DOWN        = 132,  /* */
-       FW_RDEV_NOT_READY       = 133,  /* */
-       FW_ERR_RDEV_LOST        = 134,  /* */
-       FW_ERR_RDEV_LOGO        = 135,  /* */
-       FW_FCOE_NO_XCHG         = 136,  /* */
-       FW_SCSI_RSP_ERR         = 137,  /* */
-       FW_ERR_RDEV_IMPL_LOGO   = 138,  /* */
-       FW_SCSI_UNDER_FLOW_ERR  = 139,  /* */
-       FW_SCSI_OVER_FLOW_ERR   = 140,  /* */
-       FW_SCSI_DDP_ERR         = 141,  /* DDP error*/
-       FW_SCSI_TASK_ERR        = 142,  /* No SCSI tasks available */
-};
-
 enum fw_fcoe_link_sub_op {
        FCOE_LINK_DOWN  = 0x0,
        FCOE_LINK_UP    = 0x1,
index 13aeca3d51f24919ddf10406e941fd04b25c00bc..865c64fa923c1483804b48469bb962689742b84c 100644 (file)
@@ -489,7 +489,7 @@ struct ParameterData {
        int def;                /* default value */
        int safe;               /* safe value */
 };
-static struct ParameterData __devinitdata cfg_data[] = {
+static struct ParameterData cfg_data[] = {
        { /* adapter id */
                CFG_PARAM_UNSET,
                0,
@@ -574,7 +574,7 @@ MODULE_PARM_DESC(reset_delay, "Reset delay in seconds. Default 1 (0-180)");
  * set_safe_settings - if the use_safe_settings option is set then
  * set all values to the safe and slow values.
  **/
-static void __devinit set_safe_settings(void)
+static void set_safe_settings(void)
 {
        if (use_safe_settings)
        {
@@ -593,7 +593,7 @@ static void __devinit set_safe_settings(void)
  * fix_settings - reset any boot parameters which are out of range
  * back to the default values.
  **/
-static void __devinit fix_settings(void)
+static void fix_settings(void)
 {
        int i;
 
@@ -620,7 +620,7 @@ static void __devinit fix_settings(void)
  * Mapping from the eeprom delay index value (index into this array)
  * to the number of actual seconds that the delay should be for.
  */
-static char __devinitdata eeprom_index_to_delay_map[] = 
+static char eeprom_index_to_delay_map[] =
        { 1, 3, 5, 10, 16, 30, 60, 120 };
 
 
@@ -630,7 +630,7 @@ static char __devinitdata eeprom_index_to_delay_map[] =
  *
  * @eeprom: The eeprom structure in which we find the delay index to map.
  **/
-static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
+static void eeprom_index_to_delay(struct NvRamType *eeprom)
 {
        eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time];
 }
@@ -643,7 +643,7 @@ static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
  *
  * @delay: The delay, in seconds, to find the eeprom index for.
  **/
-static int __devinit delay_to_eeprom_index(int delay)
+static int delay_to_eeprom_index(int delay)
 {
        u8 idx = 0;
        while (idx < 7 && eeprom_index_to_delay_map[idx] < delay)
@@ -659,7 +659,7 @@ static int __devinit delay_to_eeprom_index(int delay)
  *
  * @eeprom: The eeprom data to override with command line options.
  **/
-static void __devinit eeprom_override(struct NvRamType *eeprom)
+static void eeprom_override(struct NvRamType *eeprom)
 {
        u8 id;
 
@@ -3938,7 +3938,7 @@ static void dc395x_slave_destroy(struct scsi_device *scsi_device)
  *
  * @io_port: base I/O address
  **/
-static void __devinit trms1040_wait_30us(unsigned long io_port)
+static void trms1040_wait_30us(unsigned long io_port)
 {
        /* ScsiPortStallExecution(30); wait 30 us */
        outb(5, io_port + TRM_S1040_GEN_TIMER);
@@ -3955,7 +3955,7 @@ static void __devinit trms1040_wait_30us(unsigned long io_port)
  * @cmd:       SB + op code (command) to send
  * @addr:      address to send
  **/
-static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
+static void trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
 {
        int i;
        u8 send_data;
@@ -4000,7 +4000,7 @@ static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
  * @addr:      offset into EEPROM
  * @byte:      bytes to write
  **/
-static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
+static void trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
 {
        int i;
        u8 send_data;
@@ -4054,7 +4054,7 @@ static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
  * @eeprom:    the data to write
  * @io_port:   the base io port
  **/
-static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
+static void trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
 {
        u8 *b_eeprom = (u8 *)eeprom;
        u8 addr;
@@ -4094,7 +4094,7 @@ static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long
  *
  * Returns the byte read.
  **/
-static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
+static u8 trms1040_get_data(unsigned long io_port, u8 addr)
 {
        int i;
        u8 read_byte;
@@ -4132,7 +4132,7 @@ static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
  * @eeprom:    where to store the data
  * @io_port:   the base io port
  **/
-static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
+static void trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
 {
        u8 *b_eeprom = (u8 *)eeprom;
        u8 addr;
@@ -4162,7 +4162,7 @@ static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long
  * @eeprom:    caller allocated strcuture to read the eeprom data into
  * @io_port:   io port to read from
  **/
-static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
+static void check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
 {
        u16 *w_eeprom = (u16 *)eeprom;
        u16 w_addr;
@@ -4232,7 +4232,7 @@ static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_po
  *
  * @eeprom: The eeprom data strucutre to show details for.
  **/
-static void __devinit print_eeprom_settings(struct NvRamType *eeprom)
+static void print_eeprom_settings(struct NvRamType *eeprom)
 {
        dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
                eeprom->scsi_id,
@@ -4260,7 +4260,7 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
 /*
  * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
  * should never cross a page boundary */
-static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
+static int adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
 {
        const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
                                    *SEGMENTX_LEN;
@@ -4306,7 +4306,7 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
  *
  * @acb: The adapter to print the information for.
  **/
-static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
+static void adapter_print_config(struct AdapterCtlBlk *acb)
 {
        u8 bval;
 
@@ -4350,7 +4350,7 @@ static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
  *
  * @acb: The adapter to initialize.
  **/
-static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
+static void adapter_init_params(struct AdapterCtlBlk *acb)
 {
        struct NvRamType *eeprom = &acb->eeprom;
        int i;
@@ -4412,7 +4412,7 @@ static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
  *
  * @host: The scsi host instance to fill in the values for.
  **/
-static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
+static void adapter_init_scsi_host(struct Scsi_Host *host)
 {
         struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
        struct NvRamType *eeprom = &acb->eeprom;
@@ -4453,7 +4453,7 @@ static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
  *
  * @acb: The adapter which we are to init.
  **/
-static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
+static void adapter_init_chip(struct AdapterCtlBlk *acb)
 {
         struct NvRamType *eeprom = &acb->eeprom;
         
@@ -4506,8 +4506,8 @@ static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
  * Returns 0 if the initialization succeeds, any other value on
  * failure.
  **/
-static int __devinit adapter_init(struct AdapterCtlBlk *acb,
-       unsigned long io_port, u32 io_port_len, unsigned int irq)
+static int adapter_init(struct AdapterCtlBlk *acb, unsigned long io_port,
+                       u32 io_port_len, unsigned int irq)
 {
        if (!request_region(io_port, io_port_len, DC395X_NAME)) {
                dprintkl(KERN_ERR, "Failed to reserve IO region 0x%lx\n", io_port);
@@ -4794,8 +4794,7 @@ static void banner_display(void)
  *
  * Returns 0 on success, or an error code (-ve) on failure.
  **/
-static int __devinit dc395x_init_one(struct pci_dev *dev,
-               const struct pci_device_id *id)
+static int dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct Scsi_Host *scsi_host = NULL;
        struct AdapterCtlBlk *acb = NULL;
@@ -4861,7 +4860,7 @@ fail:
  *
  * @dev: The PCI device to initialize.
  **/
-static void __devexit dc395x_remove_one(struct pci_dev *dev)
+static void dc395x_remove_one(struct pci_dev *dev)
 {
        struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
        struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata);
@@ -4892,7 +4891,7 @@ static struct pci_driver dc395x_driver = {
        .name           = DC395X_NAME,
        .id_table       = dc395x_pci_table,
        .probe          = dc395x_init_one,
-       .remove         = __devexit_p(dc395x_remove_one),
+       .remove         = dc395x_remove_one,
 };
 
 
index 207352cc70ccbb43c1a9945653554faf5de187d4..4b0dd8c567077e53583a0d59b85a2aa8db7e93b7 100644 (file)
@@ -68,8 +68,8 @@ static struct scsi_host_template dmx3191d_driver_template = {
        .use_clustering         = DISABLE_CLUSTERING,
 };
 
-static int __devinit dmx3191d_probe_one(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int dmx3191d_probe_one(struct pci_dev *pdev,
+                             const struct pci_device_id *id)
 {
        struct Scsi_Host *shost;
        unsigned long io;
@@ -123,7 +123,7 @@ static int __devinit dmx3191d_probe_one(struct pci_dev *pdev,
        return error;
 }
 
-static void __devexit dmx3191d_remove_one(struct pci_dev *pdev)
+static void dmx3191d_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
 
@@ -150,7 +150,7 @@ static struct pci_driver dmx3191d_pci_driver = {
        .name           = DMX3191D_DRIVER_NAME,
        .id_table       = dmx3191d_pci_tbl,
        .probe          = dmx3191d_probe_one,
-       .remove         = __devexit_p(dmx3191d_remove_one),
+       .remove         = dmx3191d_remove_one,
 };
 
 static int __init dmx3191d_init(void)
index 1a2a1e5824e3a5f117adba1661a4c9cbd2ce32f6..fff682976c56202de49122628de392b35cfa737d 100644 (file)
@@ -1771,7 +1771,7 @@ struct scsi_host_template fdomain_driver_template = {
 #ifndef PCMCIA
 #ifdef CONFIG_PCI
 
-static struct pci_device_id fdomain_pci_tbl[] __devinitdata = {
+static struct pci_device_id fdomain_pci_tbl[] = {
        { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { }
index fc98eb61e760daaa35d5a98ce92cdefa3f1b80b9..fbf3ac6e0c55e65516d2fbbecc9630164b89c4a4 100644 (file)
@@ -399,8 +399,7 @@ static u8 *fnic_get_mac(struct fc_lport *lport)
        return fnic->data_src_addr;
 }
 
-static int __devinit fnic_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct Scsi_Host *host;
        struct fc_lport *lp;
@@ -774,7 +773,7 @@ err_out:
        return err;
 }
 
-static void __devexit fnic_remove(struct pci_dev *pdev)
+static void fnic_remove(struct pci_dev *pdev)
 {
        struct fnic *fnic = pci_get_drvdata(pdev);
        struct fc_lport *lp = fnic->lport;
@@ -849,7 +848,7 @@ static struct pci_driver fnic_driver = {
        .name = DRV_NAME,
        .id_table = fnic_id_table,
        .probe = fnic_probe,
-       .remove = __devexit_p(fnic_remove),
+       .remove = fnic_remove,
 };
 
 static int __init fnic_init_module(void)
index 1a5954f0915acc3739e18115dea344a6f2b080ca..5041f925c19140eb901a48cfcb1ff7ed448c9146 100644 (file)
@@ -939,7 +939,7 @@ module_param(dtc_3181e, int, 0);
 MODULE_LICENSE("GPL");
 
 #ifndef SCSI_G_NCR5380_MEM
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
        {
         ISAPNP_ANY_ID, ISAPNP_ANY_ID,
         ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e),
index 5d72274c507ff7d271b607289dcced6e0f6c3138..599790e41a989046592a5ce50fc5bb3a2cc80804 100644 (file)
@@ -590,7 +590,7 @@ static struct pci_driver gdth_pci_driver = {
        .remove         = gdth_pci_remove_one,
 };
 
-static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
+static void gdth_pci_remove_one(struct pci_dev *pdev)
 {
        gdth_ha_str *ha = pci_get_drvdata(pdev);
 
@@ -602,8 +602,8 @@ static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static int __devinit gdth_pci_init_one(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int gdth_pci_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        u16 vendor = pdev->vendor;
        u16 device = pdev->device;
@@ -855,8 +855,8 @@ static int __init gdth_init_isa(u32 bios_adr,gdth_ha_str *ha)
 #endif /* CONFIG_ISA */
 
 #ifdef CONFIG_PCI
-static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
-                                  gdth_ha_str *ha)
+static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+                        gdth_ha_str *ha)
 {
     register gdt6_dpram_str __iomem *dp6_ptr;
     register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -1239,7 +1239,7 @@ static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
 
 /* controller protocol functions */
 
-static void __devinit gdth_enable_int(gdth_ha_str *ha)
+static void gdth_enable_int(gdth_ha_str *ha)
 {
     unsigned long flags;
     gdt2_dpram_str __iomem *dp2_ptr;
@@ -1555,7 +1555,7 @@ static int gdth_internal_cmd(gdth_ha_str *ha, u8 service, u16 opcode,
 
 /* search for devices */
 
-static int __devinit gdth_search_drives(gdth_ha_str *ha)
+static int gdth_search_drives(gdth_ha_str *ha)
 {
     u16 cdev_cnt, i;
     int ok;
@@ -4959,8 +4959,7 @@ static int __init gdth_eisa_probe_one(u16 eisa_slot)
 #endif /* CONFIG_EISA */
 
 #ifdef CONFIG_PCI
-static int __devinit gdth_pci_probe_one(gdth_pci_str *pcistr,
-                            gdth_ha_str **ha_out)
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out)
 {
        struct Scsi_Host *shp;
        gdth_ha_str *ha;
index 488fbc648656409be4bfb77167171d53b5e1839f..dbe4cc6b9f8b75be0823653fb05dd8e15e279cc9 100644 (file)
@@ -204,7 +204,7 @@ static struct scsi_host_template gvp11_scsi_template = {
        .use_clustering         = DISABLE_CLUSTERING
 };
 
-static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
+static int check_wd33c93(struct gvp11_scsiregs *regs)
 {
 #ifdef CHECK_WD33C93
        volatile unsigned char *sasr_3393, *scmd_3393;
@@ -284,8 +284,7 @@ static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
        return 0;
 }
 
-static int __devinit gvp11_probe(struct zorro_dev *z,
-                                const struct zorro_device_id *ent)
+static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
 {
        struct Scsi_Host *instance;
        unsigned long address;
@@ -380,7 +379,7 @@ fail_check_or_alloc:
        return error;
 }
 
-static void __devexit gvp11_remove(struct zorro_dev *z)
+static void gvp11_remove(struct zorro_dev *z)
 {
        struct Scsi_Host *instance = zorro_get_drvdata(z);
        struct gvp11_hostdata *hdata = shost_priv(instance);
@@ -398,7 +397,7 @@ static void __devexit gvp11_remove(struct zorro_dev *z)
         * SERIES I though).
         */
 
-static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id gvp11_zorro_tbl[] = {
        { ZORRO_PROD_GVP_COMBO_030_R3_SCSI,     ~0x00ffffff },
        { ZORRO_PROD_GVP_SERIES_II,             ~0x00ffffff },
        { ZORRO_PROD_GVP_GFORCE_030_SCSI,       ~0x01ffffff },
@@ -414,7 +413,7 @@ static struct zorro_driver gvp11_driver = {
        .name           = "gvp11",
        .id_table       = gvp11_zorro_tbl,
        .probe          = gvp11_probe,
-       .remove         = __devexit_p(gvp11_remove),
+       .remove         = gvp11_remove,
 };
 
 static int __init gvp11_init(void)
index 4217e49aea4624b5e0b2c9354a25b627fe10b915..4f338061b5c3305f3863ef0360aab649da737f8a 100644 (file)
@@ -189,16 +189,16 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
 /* performant mode helper functions */
 static void calc_bucket_map(int *bucket, int num_buckets,
        int nsgs, int *bucket_map);
-static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
 static inline u32 next_command(struct ctlr_info *h, u8 q);
-static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
-       void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
-       u64 *cfg_offset);
-static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
-       unsigned long *memory_bar);
-static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
-static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
-       void __iomem *vaddr, int wait_for_ready);
+static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+                              u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+                              u64 *cfg_offset);
+static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
+                                   unsigned long *memory_bar);
+static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
+static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
+                                    int wait_for_ready);
 static inline void finish_cmd(struct CommandList *c);
 #define BOARD_NOT_READY 0
 #define BOARD_READY 1
@@ -3182,8 +3182,8 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
        }
 }
 
-static int __devinit hpsa_send_host_reset(struct ctlr_info *h,
-       unsigned char *scsi3addr, u8 reset_type)
+static int hpsa_send_host_reset(struct ctlr_info *h, unsigned char *scsi3addr,
+                               u8 reset_type)
 {
        struct CommandList *c;
 
@@ -3606,8 +3606,8 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *queue)
  * in simple mode, not performant mode due to the tag lookup.
  * We only ever use this immediately after a controller reset.
  */
-static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
-                                               unsigned char type)
+static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
+                       unsigned char type)
 {
        struct Command {
                struct CommandListHeader CommandHeader;
@@ -3756,14 +3756,13 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
        return 0;
 }
 
-static __devinit void init_driver_version(char *driver_version, int len)
+static void init_driver_version(char *driver_version, int len)
 {
        memset(driver_version, 0, len);
        strncpy(driver_version, HPSA " " HPSA_DRIVER_VERSION, len - 1);
 }
 
-static __devinit int write_driver_ver_to_cfgtable(
-       struct CfgTable __iomem *cfgtable)
+static int write_driver_ver_to_cfgtable(struct CfgTable __iomem *cfgtable)
 {
        char *driver_version;
        int i, size = sizeof(cfgtable->driver_version);
@@ -3779,8 +3778,8 @@ static __devinit int write_driver_ver_to_cfgtable(
        return 0;
 }
 
-static __devinit void read_driver_ver_from_cfgtable(
-       struct CfgTable __iomem *cfgtable, unsigned char *driver_ver)
+static void read_driver_ver_from_cfgtable(struct CfgTable __iomem *cfgtable,
+                                         unsigned char *driver_ver)
 {
        int i;
 
@@ -3788,8 +3787,7 @@ static __devinit void read_driver_ver_from_cfgtable(
                driver_ver[i] = readb(&cfgtable->driver_version[i]);
 }
 
-static __devinit int controller_reset_failed(
-       struct CfgTable __iomem *cfgtable)
+static int controller_reset_failed(struct CfgTable __iomem *cfgtable)
 {
 
        char *driver_ver, *old_driver_ver;
@@ -3812,7 +3810,7 @@ static __devinit int controller_reset_failed(
 /* This does a hard reset of the controller using PCI power management
  * states or the using the doorbell register.
  */
-static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
+static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 {
        u64 cfg_offset;
        u32 cfg_base_addr;
@@ -4029,7 +4027,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
  * controllers that are capable. If not, we use IO-APIC mode.
  */
 
-static void __devinit hpsa_interrupt_mode(struct ctlr_info *h)
+static void hpsa_interrupt_mode(struct ctlr_info *h)
 {
 #ifdef CONFIG_PCI_MSI
        int err, i;
@@ -4077,7 +4075,7 @@ default_int_mode:
        h->intr[h->intr_mode] = h->pdev->irq;
 }
 
-static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
+static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
 {
        int i;
        u32 subsystem_vendor_id, subsystem_device_id;
@@ -4101,8 +4099,8 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
        return ARRAY_SIZE(products) - 1; /* generic unknown smart array */
 }
 
-static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
-       unsigned long *memory_bar)
+static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
+                                   unsigned long *memory_bar)
 {
        int i;
 
@@ -4118,8 +4116,8 @@ static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
-       void __iomem *vaddr, int wait_for_ready)
+static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
+                                    int wait_for_ready)
 {
        int i, iterations;
        u32 scratchpad;
@@ -4143,9 +4141,9 @@ static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
-       void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index,
-       u64 *cfg_offset)
+static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
+                              u32 *cfg_base_addr, u64 *cfg_base_addr_index,
+                              u64 *cfg_offset)
 {
        *cfg_base_addr = readl(vaddr + SA5_CTCFG_OFFSET);
        *cfg_offset = readl(vaddr + SA5_CTMEM_OFFSET);
@@ -4158,7 +4156,7 @@ static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
        return 0;
 }
 
-static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
+static int hpsa_find_cfgtables(struct ctlr_info *h)
 {
        u64 cfg_offset;
        u32 cfg_base_addr;
@@ -4187,7 +4185,7 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
        return 0;
 }
 
-static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
+static void hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
 {
        h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
 
@@ -4208,7 +4206,7 @@ static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
  * max commands, max SG elements without chaining, and with chaining,
  * SG chain block size, etc.
  */
-static void __devinit hpsa_find_board_params(struct ctlr_info *h)
+static void hpsa_find_board_params(struct ctlr_info *h)
 {
        hpsa_get_max_perf_mode_cmds(h);
        h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
@@ -4266,7 +4264,7 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
        writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
 }
 
-static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
+static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 {
        int i;
        u32 doorbell_value;
@@ -4287,7 +4285,7 @@ static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
        }
 }
 
-static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)
+static int hpsa_enter_simple_mode(struct ctlr_info *h)
 {
        u32 trans_support;
 
@@ -4310,7 +4308,7 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)
        return 0;
 }
 
-static int __devinit hpsa_pci_init(struct ctlr_info *h)
+static int hpsa_pci_init(struct ctlr_info *h)
 {
        int prod_index, err;
 
@@ -4378,7 +4376,7 @@ err_out_free_res:
        return err;
 }
 
-static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
+static void hpsa_hba_inquiry(struct ctlr_info *h)
 {
        int rc;
 
@@ -4394,7 +4392,7 @@ static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
        }
 }
 
-static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
+static int hpsa_init_reset_devices(struct pci_dev *pdev)
 {
        int rc, i;
 
@@ -4426,7 +4424,7 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
        return 0;
 }
 
-static __devinit int hpsa_allocate_cmd_pool(struct ctlr_info *h)
+static int hpsa_allocate_cmd_pool(struct ctlr_info *h)
 {
        h->cmd_pool_bits = kzalloc(
                DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
@@ -4499,7 +4497,7 @@ static int hpsa_request_irq(struct ctlr_info *h,
        return 0;
 }
 
-static int __devinit hpsa_kdump_soft_reset(struct ctlr_info *h)
+static int hpsa_kdump_soft_reset(struct ctlr_info *h)
 {
        if (hpsa_send_host_reset(h, RAID_CTLR_LUNID,
                HPSA_RESET_TYPE_CONTROLLER)) {
@@ -4713,8 +4711,7 @@ static void stop_controller_lockup_detector(struct ctlr_info *h)
        spin_unlock_irqrestore(&lockup_detector_lock, flags);
 }
 
-static int __devinit hpsa_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int dac, rc;
        struct ctlr_info *h;
@@ -4910,7 +4907,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)
        hpsa_free_irqs_and_disable_msix(h);
 }
 
-static void __devexit hpsa_free_device_info(struct ctlr_info *h)
+static void hpsa_free_device_info(struct ctlr_info *h)
 {
        int i;
 
@@ -4918,7 +4915,7 @@ static void __devexit hpsa_free_device_info(struct ctlr_info *h)
                kfree(h->dev[i]);
 }
 
-static void __devexit hpsa_remove_one(struct pci_dev *pdev)
+static void hpsa_remove_one(struct pci_dev *pdev)
 {
        struct ctlr_info *h;
 
@@ -4966,7 +4963,7 @@ static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev)
 static struct pci_driver hpsa_pci_driver = {
        .name = HPSA,
        .probe = hpsa_init_one,
-       .remove = __devexit_p(hpsa_remove_one),
+       .remove = hpsa_remove_one,
        .id_table = hpsa_pci_device_id, /* id_table */
        .shutdown = hpsa_shutdown,
        .suspend = hpsa_suspend,
@@ -5010,8 +5007,7 @@ static void  calc_bucket_map(int bucket[], int num_buckets,
        }
 }
 
-static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
-       u32 use_short_tags)
+static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 use_short_tags)
 {
        int i;
        unsigned long register_value;
@@ -5079,7 +5075,7 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
        h->transMethod = CFGTBL_Trans_Performant;
 }
 
-static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 {
        u32 trans_support;
        int i;
index 138e573f37ef5b08ceadafbe90ec39701507704e..ee196b363d81c16cb2c85702bab0bb929d43d1b0 100644 (file)
@@ -1282,8 +1282,7 @@ static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)
                return -1;
 }
 
-static int __devinit hptiop_probe(struct pci_dev *pcidev,
-                                       const struct pci_device_id *id)
+static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
 {
        struct Scsi_Host *host = NULL;
        struct hptiop_hba *hba;
index 5e8d51bd03de92222874321ec874559b9a91ec83..cc82d0f322b6cb30fd3fdaf1fd5e49665302dece 100644 (file)
@@ -4905,7 +4905,7 @@ static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
        return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
 }
 
-static struct vio_device_id ibmvfc_device_table[] __devinitdata = {
+static struct vio_device_id ibmvfc_device_table[] = {
        {"fcp", "IBM,vfc-client"},
        { "", "" }
 };
index ef9a54c7da6730b2f7ff9fc07a6037f12fb02a96..a044f593e8b98437e208cc1b785ca58371483890 100644 (file)
@@ -2362,7 +2362,7 @@ static int ibmvscsi_resume(struct device *dev)
  * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 
  * support.
  */
-static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
+static struct vio_device_id ibmvscsi_device_table[] = {
        {"vscsi", "IBM,v-scsi"},
        { "", "" }
 };
index aa7ed81e92371140738bbe4f8d32559662e9b3d7..bf9eca84516658b5a6ad00527e665e4b2457672d 100644 (file)
@@ -907,7 +907,7 @@ static int ibmvstgt_remove(struct vio_dev *dev)
        return 0;
 }
 
-static struct vio_device_id ibmvstgt_device_table[] __devinitdata = {
+static struct vio_device_id ibmvstgt_device_table[] = {
        {"v-scsi-host", "IBM,v-scsi-host"},
        {"",""}
 };
index dd741bcd6ccd78e1190fad6dd688b826756b0cdf..280d5af113d1deb851791ca2f9d254b6d45b149c 100644 (file)
@@ -2992,7 +2992,7 @@ static struct pci_driver initio_pci_driver = {
        .name           = "initio",
        .id_table       = initio_pci_tbl,
        .probe          = initio_probe_one,
-       .remove         = __devexit_p(initio_remove_one),
+       .remove         = initio_remove_one,
 };
 
 static int __init initio_init_driver(void)
index fe6029f4df164406e406fb8ca6b2c698461fd48a..1d7da3f41ebb62db01cb74d4f2478b3d595fdbef 100644 (file)
@@ -8296,7 +8296,7 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev,
  * Return value:
  *     0 on success / -EIO on failure
  **/
-static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
 {
        int rc = 0;
        unsigned long host_lock_flags = 0;
@@ -8425,7 +8425,7 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
  * Return value:
  *     0 on success / -ENOMEM on allocation failure
  **/
-static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
 {
        struct ipr_cmnd *ipr_cmd;
        struct ipr_ioarcb *ioarcb;
@@ -8497,7 +8497,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
  * Return value:
  *     0 on success / non-zero for error
  **/
-static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
+static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 {
        struct pci_dev *pdev = ioa_cfg->pdev;
        int i, rc = -ENOMEM;
@@ -8601,7 +8601,7 @@ out_free_res_entries:
  * Return value:
  *     none
  **/
-static void __devinit ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
+static void ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
 {
        int i;
 
@@ -8625,8 +8625,8 @@ static void __devinit ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg)
  * Return value:
  *     none
  **/
-static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
-                                      struct Scsi_Host *host, struct pci_dev *pdev)
+static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
+                            struct Scsi_Host *host, struct pci_dev *pdev)
 {
        const struct ipr_interrupt_offsets *p;
        struct ipr_interrupts *t;
@@ -8712,7 +8712,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
  * Return value:
  *     ptr to chip information on success / NULL on failure
  **/
-static const struct ipr_chip_t * __devinit
+static const struct ipr_chip_t *
 ipr_get_chip_info(const struct pci_device_id *dev_id)
 {
        int i;
@@ -8734,7 +8734,7 @@ ipr_get_chip_info(const struct pci_device_id *dev_id)
  * Return value:
  *     0 on success / non-zero on failure
  **/
-static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
+static irqreturn_t ipr_test_intr(int irq, void *devp)
 {
        struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
        unsigned long lock_flags = 0;
@@ -8761,8 +8761,7 @@ static irqreturn_t __devinit ipr_test_intr(int irq, void *devp)
  * Return value:
  *     0 on success / non-zero on failure
  **/
-static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
-                                 struct pci_dev *pdev)
+static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev)
 {
        int rc;
        volatile u32 int_reg;
@@ -8815,8 +8814,8 @@ static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg,
  * Return value:
  *     0 on success / non-zero on failure
  **/
-static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
-                                  const struct pci_device_id *dev_id)
+static int ipr_probe_ioa(struct pci_dev *pdev,
+                        const struct pci_device_id *dev_id)
 {
        struct ipr_ioa_cfg *ioa_cfg;
        struct Scsi_Host *host;
@@ -9113,7 +9112,7 @@ static void __ipr_remove(struct pci_dev *pdev)
  * Return value:
  *     none
  **/
-static void __devexit ipr_remove(struct pci_dev *pdev)
+static void ipr_remove(struct pci_dev *pdev)
 {
        struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
 
@@ -9136,8 +9135,7 @@ static void __devexit ipr_remove(struct pci_dev *pdev)
  * Return value:
  *     0 on success / non-zero on failure
  **/
-static int __devinit ipr_probe(struct pci_dev *pdev,
-                              const struct pci_device_id *dev_id)
+static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
 {
        struct ipr_ioa_cfg *ioa_cfg;
        int rc;
@@ -9218,7 +9216,7 @@ static void ipr_shutdown(struct pci_dev *pdev)
        wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
 }
 
-static struct pci_device_id ipr_pci_table[] __devinitdata = {
+static struct pci_device_id ipr_pci_table[] = {
        { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 },
        { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
@@ -9305,7 +9303,7 @@ static struct pci_driver ipr_driver = {
        .name = IPR_NAME,
        .id_table = ipr_pci_table,
        .probe = ipr_probe,
-       .remove = __devexit_p(ipr_remove),
+       .remove = ipr_remove,
        .shutdown = ipr_shutdown,
        .err_handler = &ipr_err_handler,
 };
index b6d7a5c2fc9497b0dcbcfa78d73d75bd173a44e5..9aa86a315a088c9a450e8ff061196349e5c13f34 100644 (file)
@@ -389,14 +389,14 @@ MODULE_DEVICE_TABLE( pci, ips_pci_table );
 
 static char ips_hot_plug_name[] = "ips";
 
-static int __devinit  ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
-static void __devexit ips_remove_device(struct pci_dev *pci_dev);
+static int  ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static void ips_remove_device(struct pci_dev *pci_dev);
 
 static struct pci_driver ips_pci_driver = {
        .name           = ips_hot_plug_name,
        .id_table       = ips_pci_table,
        .probe          = ips_insert_device,
-       .remove         = __devexit_p(ips_remove_device),
+       .remove         = ips_remove_device,
 };
 
 
@@ -6837,7 +6837,7 @@ err_out_sh:
 /*   Routine Description:                                                    */
 /*     Remove one Adapter ( Hot Plugging )                                   */
 /*---------------------------------------------------------------------------*/
-static void __devexit
+static void
 ips_remove_device(struct pci_dev *pci_dev)
 {
        struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
@@ -6898,7 +6898,7 @@ module_exit(ips_module_exit);
 /*   Return Value:                                                           */
 /*     0 if Successful, else non-zero                                        */
 /*---------------------------------------------------------------------------*/
-static int __devinit
+static int
 ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
 {
        int index = -1;
index b74050b95d6af93ad5720baa39790b852a7f1413..2839baa82a5a458d0035d59e8a5666ac07690779 100644 (file)
@@ -282,7 +282,7 @@ static void isci_unregister(struct isci_host *isci_host)
        scsi_host_put(shost);
 }
 
-static int __devinit isci_pci_init(struct pci_dev *pdev)
+static int isci_pci_init(struct pci_dev *pdev)
 {
        int err, bar_num, bar_mask = 0;
        void __iomem * const *iomap;
@@ -616,7 +616,7 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
        return NULL;
 }
 
-static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct isci_pci_info *pci_info;
        int err, i;
@@ -633,7 +633,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
                return -ENOMEM;
        pci_set_drvdata(pdev, pci_info);
 
-       if (efi_enabled)
+       if (efi_enabled(EFI_RUNTIME_SERVICES))
                orom = isci_get_efi_var(pdev);
 
        if (!orom)
@@ -709,7 +709,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
        return err;
 }
 
-static void __devexit isci_pci_remove(struct pci_dev *pdev)
+static void isci_pci_remove(struct pci_dev *pdev)
 {
        struct isci_host *ihost;
        int i;
@@ -778,7 +778,7 @@ static struct pci_driver isci_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = isci_id_table,
        .probe          = isci_pci_probe,
-       .remove         = __devexit_p(isci_pci_remove),
+       .remove         = isci_pci_remove,
 #ifdef CONFIG_PM
        .driver.pm      = &isci_pm_ops,
 #endif
index 27cfb0cb186cd7fdd79029ef724c7e6c8beed79a..69efbf12b299ac351d61bf8a324fa51a6ca69e09 100644 (file)
@@ -129,7 +129,7 @@ static const struct esp_driver_ops jazz_esp_ops = {
        .dma_error      =       jazz_esp_dma_error,
 };
 
-static int __devinit esp_jazz_probe(struct platform_device *dev)
+static int esp_jazz_probe(struct platform_device *dev)
 {
        struct scsi_host_template *tpnt = &scsi_esp_template;
        struct Scsi_Host *host;
@@ -201,7 +201,7 @@ fail:
        return err;
 }
 
-static int __devexit esp_jazz_remove(struct platform_device *dev)
+static int esp_jazz_remove(struct platform_device *dev)
 {
        struct esp *esp = dev_get_drvdata(&dev->dev);
        unsigned int irq = esp->host->irq;
@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:jazz_esp");
 
 static struct platform_driver esp_jazz_driver = {
        .probe          = esp_jazz_probe,
-       .remove         = __devexit_p(esp_jazz_remove),
+       .remove         = esp_jazz_remove,
        .driver = {
                .name   = "jazz_esp",
                .owner  = THIS_MODULE,
index 23880f8fe7e4fccb985997d782fce852b916ed54..5c4ded997265d4833f63039c17edf93ba6ecbd12 100644 (file)
@@ -168,7 +168,7 @@ static struct parisc_driver lasi700_driver = {
        .name =         "lasi_scsi",
        .id_table =     lasi700_ids,
        .probe =        lasi700_probe,
-       .remove =       __devexit_p(lasi700_driver_remove),
+       .remove =       lasi700_driver_remove,
 };
 
 static int __init
index c20eec78adc16e6b75f1df76536b5cbacb3c777b..89ad55807012007654e5fb4888ef36ac838016fa 100644 (file)
@@ -8813,7 +8813,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
  *     0 - driver can claim the device
  *     negative value - driver can not claim the device
  **/
-static int __devinit
+static int
 lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
@@ -8980,7 +8980,7 @@ out_free_phba:
  * removed from PCI bus, it performs all the necessary cleanup for the HBA
  * device to be removed from the PCI subsystem properly.
  **/
-static void __devexit
+static void
 lpfc_pci_remove_one_s3(struct pci_dev *pdev)
 {
        struct Scsi_Host  *shost = pci_get_drvdata(pdev);
@@ -9587,7 +9587,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
  *     0 - driver can claim the device
  *     negative value - driver can not claim the device
  **/
-static int __devinit
+static int
 lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
@@ -9779,7 +9779,7 @@ out_free_phba:
  * removed from PCI bus, it performs all the necessary cleanup for the HBA
  * device to be removed from the PCI subsystem properly.
  **/
-static void __devexit
+static void
 lpfc_pci_remove_one_s4(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -10205,7 +10205,7 @@ lpfc_io_resume_s4(struct pci_dev *pdev)
  *     0 - driver can claim the device
  *     negative value - driver can not claim the device
  **/
-static int __devinit
+static int
 lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        int rc;
@@ -10233,7 +10233,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
  * remove routine, which will perform all the necessary cleanup for the
  * device to be removed from the PCI subsystem properly.
  **/
-static void __devexit
+static void
 lpfc_pci_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -10575,7 +10575,7 @@ static struct pci_driver lpfc_driver = {
        .name           = LPFC_DRIVER_NAME,
        .id_table       = lpfc_id_table,
        .probe          = lpfc_pci_probe_one,
-       .remove         = __devexit_p(lpfc_pci_remove_one),
+       .remove         = lpfc_pci_remove_one,
        .suspend        = lpfc_pci_suspend_one,
        .resume         = lpfc_pci_resume_one,
        .err_handler    = &lpfc_err_handler,
index 70eb1f79b1ba2f9fd08568e190bfb9126ece962c..994fc5caf036c89434f1231425696ec6ecd398ba 100644 (file)
@@ -481,7 +481,7 @@ static struct esp_driver_ops mac_esp_ops = {
        .dma_error        = mac_esp_dma_error,
 };
 
-static int __devinit esp_mac_probe(struct platform_device *dev)
+static int esp_mac_probe(struct platform_device *dev)
 {
        struct scsi_host_template *tpnt = &scsi_esp_template;
        struct Scsi_Host *host;
@@ -591,7 +591,7 @@ fail:
        return err;
 }
 
-static int __devexit esp_mac_remove(struct platform_device *dev)
+static int esp_mac_remove(struct platform_device *dev)
 {
        struct mac_esp_priv *mep = platform_get_drvdata(dev);
        struct esp *esp = mep->esp;
@@ -614,7 +614,7 @@ static int __devexit esp_mac_remove(struct platform_device *dev)
 
 static struct platform_driver esp_mac_driver = {
        .probe    = esp_mac_probe,
-       .remove   = __devexit_p(esp_mac_remove),
+       .remove   = esp_mac_remove,
        .driver   = {
                .name   = DRV_MODULE_NAME,
                .owner  = THIS_MODULE,
index 76ad72d32c3f5ef8123b0b32b921de5ad7634f86..9504ec0ec68291273a2ad3ef6845e3c4e0c94bc5 100644 (file)
@@ -4522,7 +4522,7 @@ static struct scsi_host_template megaraid_template = {
        .eh_host_reset_handler          = megaraid_reset,
 };
 
-static int __devinit
+static int
 megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct Scsi_Host *host;
@@ -4914,7 +4914,7 @@ __megaraid_shutdown(adapter_t *adapter)
                mdelay(1000);
 }
 
-static void __devexit
+static void
 megaraid_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -5008,7 +5008,7 @@ static struct pci_driver megaraid_pci_driver = {
        .name           = "megaraid_legacy",
        .id_table       = megaraid_pci_tbl,
        .probe          = megaraid_probe_one,
-       .remove         = __devexit_p(megaraid_remove_one),
+       .remove         = megaraid_remove_one,
        .shutdown       = megaraid_shutdown,
 };
 
index 54b1c5bb310f99f52e6a119eb7634ecb3f95d698..e6a1e0b38a19a8710eb30ca4bcfe615703224108 100644 (file)
@@ -305,7 +305,7 @@ static struct pci_driver megaraid_pci_driver = {
        .name           = "megaraid",
        .id_table       = pci_id_table_g,
        .probe          = megaraid_probe_one,
-       .remove         = __devexit_p(megaraid_detach_one),
+       .remove         = megaraid_detach_one,
        .shutdown       = megaraid_mbox_shutdown,
 };
 
@@ -434,7 +434,7 @@ megaraid_exit(void)
  * This routine should be called whenever a new adapter is detected by the
  * PCI hotplug susbsystem.
  */
-static int __devinit
+static int
 megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        adapter_t       *adapter;
@@ -735,7 +735,7 @@ megaraid_io_detach(adapter_t *adapter)
  * - Allocate memory required for all the commands
  * - Use internal library of FW routines, build up complete soft state
  */
-static int __devinit
+static int
 megaraid_init_mbox(adapter_t *adapter)
 {
        struct pci_dev          *pdev;
index e4f2baacf1e1783ec9054bae3f7013afb5af0a5f..66a0fec0437b316ae8f25f55a493da9873de81b2 100644 (file)
@@ -3972,8 +3972,8 @@ fail_set_dma_mask:
  * @pdev:              PCI device structure
  * @id:                        PCI ids of supported hotplugged adapter
  */
-static int __devinit
-megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int megasas_probe_one(struct pci_dev *pdev,
+                            const struct pci_device_id *id)
 {
        int rval, pos, i, j;
        struct Scsi_Host *host;
@@ -4525,7 +4525,7 @@ fail_ready_state:
  * megasas_detach_one -        PCI hot"un"plug entry point
  * @pdev:              PCI device structure
  */
-static void __devexit megasas_detach_one(struct pci_dev *pdev)
+static void megasas_detach_one(struct pci_dev *pdev)
 {
        int i;
        struct Scsi_Host *host;
@@ -5119,7 +5119,7 @@ static struct pci_driver megasas_pci_driver = {
        .name = "megaraid_sas",
        .id_table = megasas_pci_table,
        .probe = megasas_probe_one,
-       .remove = __devexit_p(megasas_detach_one),
+       .remove = megasas_detach_one,
        .suspend = megasas_suspend,
        .resume = megasas_resume,
        .shutdown = megasas_shutdown,
index af4e6c451b1b56239d26a87dd23d4835bac69153..c6bdc92672298acabb6da842ba840710894ca6ab 100644 (file)
@@ -7686,7 +7686,7 @@ _scsih_shutdown(struct pci_dev *pdev)
  * Routine called when unloading the driver.
  * Return nothing.
  */
-static void __devexit
+static void
 _scsih_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -8338,7 +8338,7 @@ static struct pci_driver scsih_driver = {
        .name           = MPT2SAS_DRIVER_NAME,
        .id_table       = scsih_pci_table,
        .probe          = _scsih_probe,
-       .remove         = __devexit_p(_scsih_remove),
+       .remove         = _scsih_remove,
        .shutdown       = _scsih_shutdown,
        .err_handler    = &_scsih_err_handler,
 #ifdef CONFIG_PM
index 05f80450ac7e6c96e7173289419696f883d5abb3..6421a06c4ce20dac97de5f4ada0e431ed33a24f0 100644 (file)
@@ -7374,8 +7374,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  * Routine called when unloading the driver.
  * Return nothing.
  */
-static void __devexit
-_scsih_remove(struct pci_dev *pdev)
+static void _scsih_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8044,7 +8043,7 @@ static struct pci_driver scsih_driver = {
        .name           = MPT3SAS_DRIVER_NAME,
        .id_table       = scsih_pci_table,
        .probe          = _scsih_probe,
-       .remove         = __devexit_p(_scsih_remove),
+       .remove         = _scsih_remove,
        .shutdown       = _scsih_shutdown,
        .err_handler    = &_scsih_err_handler,
 #ifdef CONFIG_PM
index 39f554f5f26114b1e5a7f401036974d9119cc697..8fbb97a8bfd32dc71aa0e784ef1810059626ed00 100644 (file)
@@ -34,8 +34,7 @@ static struct scsi_host_template mvme16x_scsi_driver_template = {
 
 static struct platform_device *mvme16x_scsi_device;
 
-static __devinit int
-mvme16x_probe(struct platform_device *dev)
+static int mvme16x_probe(struct platform_device *dev)
 {
        struct Scsi_Host * host = NULL;
        struct NCR_700_Host_Parameters *hostdata;
@@ -103,8 +102,7 @@ mvme16x_probe(struct platform_device *dev)
        return -ENODEV;
 }
 
-static __devexit int
-mvme16x_device_remove(struct platform_device *dev)
+static int mvme16x_device_remove(struct platform_device *dev)
 {
        struct Scsi_Host *host = platform_get_drvdata(dev);
        struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -131,7 +129,7 @@ static struct platform_driver mvme16x_scsi_driver = {
                .owner          = THIS_MODULE,
        },
        .probe          = mvme16x_probe,
-       .remove         = __devexit_p(mvme16x_device_remove),
+       .remove         = mvme16x_device_remove,
 };
 
 static int __init mvme16x_scsi_init(void)
index 8ba47229049f5d44bde2a6d55a145f9c1b277fff..8bb06995adfb0e1f5dc90287f4a358022bc29602 100644 (file)
@@ -41,7 +41,7 @@ static void mvs_64xx_detect_porttype(struct mvs_info *mvi, int i)
                phy->phy_type |= PORT_TYPE_SATA;
 }
 
-static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+static void mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
 {
        void __iomem *regs = mvi->regs;
        u32 tmp;
@@ -54,7 +54,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
        mw32(MVS_PCS, tmp);
 }
 
-static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
+static void mvs_64xx_phy_hacks(struct mvs_info *mvi)
 {
        void __iomem *regs = mvi->regs;
        int i;
@@ -156,7 +156,7 @@ void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
        }
 }
 
-static int __devinit mvs_64xx_chip_reset(struct mvs_info *mvi)
+static int mvs_64xx_chip_reset(struct mvs_info *mvi)
 {
        void __iomem *regs = mvi->regs;
        u32 tmp;
@@ -250,7 +250,7 @@ static void mvs_64xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
        }
 }
 
-static int __devinit mvs_64xx_init(struct mvs_info *mvi)
+static int mvs_64xx_init(struct mvs_info *mvi)
 {
        void __iomem *regs = mvi->regs;
        int i;
index 7e423e5ad5e103e53e9df4868ebc3ffee0608e08..1e4479f3331a44692934cf9a2c7bb7421185b09d 100644 (file)
@@ -216,8 +216,7 @@ void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
        mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v);
 }
 
-static void __devinit
-mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
+static void mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
 {
        u32 temp;
        temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]);
@@ -258,7 +257,7 @@ mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
                mvi->hba_info_param.phy_rate[phy_id]);
 }
 
-static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
+static void mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
 {
        void __iomem *regs = mvi->regs;
        u32 tmp;
@@ -331,7 +330,7 @@ static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
        mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
 }
 
-static int __devinit mvs_94xx_init(struct mvs_info *mvi)
+static int mvs_94xx_init(struct mvs_info *mvi)
 {
        void __iomem *regs = mvi->regs;
        int i;
index bcc408042cee3b54c8e93ab890d9a0c2e69f2e9a..8c4479ab49e80f409f2f0e3e7f2fee747c2b7140 100644 (file)
@@ -160,7 +160,7 @@ static inline void mvs_write_port_irq_mask(struct mvs_info *mvi,
                        MVS_P4_INT_MASK, port, val);
 }
 
-static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
+static inline void mvs_phy_hacks(struct mvs_info *mvi)
 {
        u32 tmp;
 
index cc59dff3810b3d9e03ba7c418942fcd5eb5f8122..ce90d0546cddf3a0e7b85957c003266c05d2d6fd 100644 (file)
@@ -96,7 +96,7 @@ static struct sas_domain_function_template mvs_transport_ops = {
 
 };
 
-static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
+static void mvs_phy_init(struct mvs_info *mvi, int phy_id)
 {
        struct mvs_phy *phy = &mvi->phy[phy_id];
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -235,7 +235,7 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
        return IRQ_HANDLED;
 }
 
-static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
+static int mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 {
        int i = 0, slot_nr;
        char pool_name[32];
@@ -373,7 +373,7 @@ void mvs_iounmap(void __iomem *regs)
        iounmap(regs);
 }
 
-static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
+static struct mvs_info *mvs_pci_alloc(struct pci_dev *pdev,
                                const struct pci_device_id *ent,
                                struct Scsi_Host *shost, unsigned int id)
 {
@@ -444,7 +444,7 @@ static int pci_go_64(struct pci_dev *pdev)
        return rc;
 }
 
-static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
+static int mvs_prep_sas_ha_init(struct Scsi_Host *shost,
                                const struct mvs_chip_info *chip_info)
 {
        int phy_nr, port_nr; unsigned short core_nr;
@@ -486,7 +486,7 @@ exit_free:
 
 }
 
-static void  __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
+static void  mvs_post_sas_ha_init(struct Scsi_Host *shost,
                        const struct mvs_chip_info *chip_info)
 {
        int can_queue, i = 0, j = 0;
@@ -537,8 +537,7 @@ static void mvs_init_sas_add(struct mvs_info *mvi)
        memcpy(mvi->sas_addr, &mvi->phy[0].dev_sas_addr, SAS_ADDR_SIZE);
 }
 
-static int __devinit mvs_pci_init(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int mvs_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned int rc, nhost = 0;
        struct mvs_info *mvi;
@@ -645,7 +644,7 @@ err_out_enable:
        return rc;
 }
 
-static void __devexit mvs_pci_remove(struct pci_dev *pdev)
+static void mvs_pci_remove(struct pci_dev *pdev)
 {
        unsigned short core_nr, i = 0;
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
@@ -677,7 +676,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
        return;
 }
 
-static struct pci_device_id __devinitdata mvs_pci_table[] = {
+static struct pci_device_id mvs_pci_table[] = {
        { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 },
        { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 },
        {
@@ -748,7 +747,7 @@ static struct pci_driver mvs_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = mvs_pci_table,
        .probe          = mvs_pci_init,
-       .remove         = __devexit_p(mvs_pci_remove),
+       .remove         = mvs_pci_remove,
 };
 
 static ssize_t
index a3776d6ced60df7606b329f39ca3780914486741..078c63913b5596f05503410b79ac9cf71dc7f5b0 100644 (file)
@@ -220,8 +220,8 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
        return rc;
 }
 
-void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
-                               u32 off_lo, u32 off_hi, u64 sas_addr)
+void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
+                     u32 off_hi, u64 sas_addr)
 {
        u32 lo = (u32)sas_addr;
        u32 hi = (u32)(sas_addr>>32);
index da249553858c4d1240348b6d0387b15d69dc64e8..2ae77a0394b2b24ae1500802f31f444ff281d8e8 100644 (file)
@@ -456,8 +456,8 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex);
 void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard);
 int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                        void *funcdata);
-void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
-                               u32 off_lo, u32 off_hi, u64 sas_addr);
+void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
+                     u32 off_hi, u64 sas_addr);
 void mvs_scan_start(struct Scsi_Host *shost);
 int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
 int mvs_queue_command(struct sas_task *task, const int num,
index c585a925b3cd1e159832b86a8b531b011059ec91..4594ccaaf49ba2ce3f697c2fab355efe493f122d 100644 (file)
@@ -2506,8 +2506,7 @@ fail_add_device:
  * @pdev:              PCI device structure
  * @id:                        PCI ids of supported hotplugged adapter
  */
-static int __devinit mvumi_probe_one(struct pci_dev *pdev,
-                                       const struct pci_device_id *id)
+static int mvumi_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct Scsi_Host *host;
        struct mvumi_hba *mhba;
@@ -2728,7 +2727,7 @@ static struct pci_driver mvumi_pci_driver = {
        .name = MV_DRIVER_NAME,
        .id_table = mvumi_pci_table,
        .probe = mvumi_probe_one,
-       .remove = __devexit_p(mvumi_detach_one),
+       .remove = mvumi_detach_one,
        .shutdown = mvumi_shutdown,
 #ifdef CONFIG_PM
        .suspend = mvumi_suspend,
index 62b616891a33f684f0081a6efa427d4a6a22f3d1..1cc0c1c69c880b1f37d0c89063beff4b5566b697 100644 (file)
@@ -76,7 +76,7 @@ static const char *nsp32_release_version = "1.2";
 /****************************************************************************
  * Supported hardware
  */
-static struct pci_device_id nsp32_pci_table[] __devinitdata = {
+static struct pci_device_id nsp32_pci_table[] = {
        {
                .vendor      = PCI_VENDOR_ID_IODATA,
                .device      = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II,
@@ -186,10 +186,10 @@ static nsp32_sync_table nsp32_sync_table_pci[] = {
  * function declaration
  */
 /* module entry point */
-static int  __devinit nsp32_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit nsp32_remove(struct pci_dev *);
-static int  __init    init_nsp32  (void);
-static void __exit    exit_nsp32  (void);
+static int         nsp32_probe (struct pci_dev *, const struct pci_device_id *);
+static void        nsp32_remove(struct pci_dev *);
+static int  __init init_nsp32  (void);
+static void __exit exit_nsp32  (void);
 
 /* struct struct scsi_host_template */
 static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
@@ -3382,7 +3382,7 @@ static int nsp32_resume(struct pci_dev *pdev)
 /************************************************************************
  * PCI/Cardbus probe/remove routine
  */
-static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int ret;
        nsp32_hw_data *data = &nsp32_data_base;
@@ -3418,7 +3418,7 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i
        return ret;
 }
 
-static void __devexit nsp32_remove(struct pci_dev *pdev)
+static void nsp32_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
 
@@ -3435,7 +3435,7 @@ static struct pci_driver nsp32_driver = {
        .name           = "nsp32",
        .id_table       = nsp32_pci_table,
        .probe          = nsp32_probe,
-       .remove         = __devexit_p(nsp32_remove),
+       .remove         = nsp32_remove,
 #ifdef CONFIG_PM
        .suspend        = nsp32_suspend, 
        .resume         = nsp32_resume, 
index bf54aafc2d717aee606de8c928c08ef6a39bba41..b8dd05074abb4f61faebbe0af12bd3074fd8b930 100644 (file)
@@ -47,7 +47,7 @@
  * read_main_config_table - read the configure table and save it.
  * @pm8001_ha: our hba card information
  */
-static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
+static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
        pm8001_ha->main_cfg_tbl.signature       = pm8001_mr32(address, 0x00);
@@ -83,8 +83,7 @@ static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
  * read_general_status_table - read the general status table and save it.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-read_general_status_table(struct pm8001_hba_info *pm8001_ha)
+static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->general_stat_tbl_addr;
        pm8001_ha->gs_tbl.gst_len_mpistate      = pm8001_mr32(address, 0x00);
@@ -118,8 +117,7 @@ read_general_status_table(struct pm8001_hba_info *pm8001_ha)
  * read_inbnd_queue_table - read the inbound queue table and save it.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
        int inbQ_num = 1;
        int i;
@@ -137,8 +135,7 @@ read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
  * read_outbnd_queue_table - read the outbound queue table and save it.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
        int outbQ_num = 1;
        int i;
@@ -156,8 +153,7 @@ read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
  * init_default_table_values - init the default table.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 {
        int qn = 1;
        int i;
@@ -250,8 +246,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
  * update_main_config_table - update the main default table to the HBA.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-update_main_config_table(struct pm8001_hba_info *pm8001_ha)
+static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
        pm8001_mw32(address, 0x24,
@@ -297,8 +292,8 @@ update_main_config_table(struct pm8001_hba_info *pm8001_ha)
  * update_inbnd_queue_table - update the inbound queue table to the HBA.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
+static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+                                    int number)
 {
        void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
        u16 offset = number * 0x20;
@@ -318,8 +313,8 @@ update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
  * update_outbnd_queue_table - update the outbound queue table to the HBA.
  * @pm8001_ha: our hba card information
  */
-static void __devinit
-update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number)
+static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+                                     int number)
 {
        void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
        u16 offset = number * 0x24;
@@ -370,8 +365,8 @@ int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue)
  * @pm8001_ha: our hba card information
  * @SSCbit: set SSCbit to 0 to disable all phys ssc; 1 to enable all phys ssc.
  */
-static void __devinit
-mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
+static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha,
+                                    u32 SSCbit)
 {
        u32 value, offset, i;
        unsigned long flags;
@@ -438,9 +433,8 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
  * @pm8001_ha: our hba card information
  * @interval - interval time for each OPEN_REJECT (RETRY). The units are in 1us.
  */
-static void __devinit
-mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha,
-                               u32 interval)
+static void mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha,
+                                           u32 interval)
 {
        u32 offset;
        u32 value;
@@ -601,7 +595,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
  * pm8001_chip_init - the main init function that initialize whole PM8001 chip.
  * @pm8001_ha: our hba card information
  */
-static int __devinit pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
 {
        /* check the firmware status */
        if (-1 == check_fw_ready(pm8001_ha)) {
index 0267c22f87419e5c87375992b7c5dec707d41edc..4c9fe733fe8889d2bdb66657ff5928294237b766 100644 (file)
@@ -104,8 +104,7 @@ static struct sas_domain_function_template pm8001_transport_ops = {
  *@pm8001_ha: our hba structure.
  *@phy_id: phy id.
  */
-static void __devinit pm8001_phy_init(struct pm8001_hba_info *pm8001_ha,
-       int phy_id)
+static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
 {
        struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -195,7 +194,7 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque)
  * @pm8001_ha:our hba structure.
  *
  */
-static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
 {
        int i;
        spin_lock_init(&pm8001_ha->lock);
@@ -360,8 +359,9 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
  * @ent: ent
  * @shost: scsi host struct which has been initialized before.
  */
-static struct pm8001_hba_info *__devinit
-pm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost)
+static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
+                                               u32 chip_id,
+                                               struct Scsi_Host *shost)
 {
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
@@ -433,8 +433,8 @@ static int pci_go_44(struct pci_dev *pdev)
  * @shost: scsi host which has been allocated outside.
  * @chip_info: our ha struct.
  */
-static int __devinit pm8001_prep_sas_ha_init(struct Scsi_Host * shost,
-       const struct pm8001_chip_info *chip_info)
+static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost,
+                                  const struct pm8001_chip_info *chip_info)
 {
        int phy_nr, port_nr;
        struct asd_sas_phy **arr_phy;
@@ -479,8 +479,8 @@ exit:
  * @shost: scsi host which has been allocated outside
  * @chip_info: our ha struct.
  */
-static void  __devinit pm8001_post_sas_ha_init(struct Scsi_Host *shost,
-       const struct pm8001_chip_info *chip_info)
+static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
+                                    const struct pm8001_chip_info *chip_info)
 {
        int i = 0;
        struct pm8001_hba_info *pm8001_ha;
@@ -615,8 +615,8 @@ intx:
  * pci driver it is invoked, all struct an hardware initilization should be done
  * here, also, register interrupt
  */
-static int __devinit pm8001_pci_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int pm8001_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        unsigned int rc;
        u32     pci_reg;
@@ -707,7 +707,7 @@ err_out_enable:
        return rc;
 }
 
-static void __devexit pm8001_pci_remove(struct pci_dev *pdev)
+static void pm8001_pci_remove(struct pci_dev *pdev)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
@@ -842,7 +842,7 @@ err_out_enable:
        return rc;
 }
 
-static struct pci_device_id __devinitdata pm8001_pci_table[] = {
+static struct pci_device_id pm8001_pci_table[] = {
        {
                PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001
        },
@@ -857,7 +857,7 @@ static struct pci_driver pm8001_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = pm8001_pci_table,
        .probe          = pm8001_pci_probe,
-       .remove         = __devexit_p(pm8001_pci_remove),
+       .remove         = pm8001_pci_remove,
        .suspend        = pm8001_pci_suspend,
        .resume         = pm8001_pci_resume,
 };
index af763eab2039022b997a572b324e6d9466a7449b..b46f5e90683793043853ca6a6f2ad500b9746806 100644 (file)
@@ -125,7 +125,7 @@ static struct pmcraid_chip_details pmcraid_chip_cfg[] = {
 /*
  * PCI device ids supported by pmcraid driver
  */
-static struct pci_device_id pmcraid_pci_table[] __devinitdata = {
+static struct pci_device_id pmcraid_pci_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_PMC, PCI_DEVICE_ID_PMC_MAXRAID),
          0, 0, (kernel_ulong_t)&pmcraid_chip_cfg[0]
        },
@@ -4818,8 +4818,7 @@ pmcraid_release_control_blocks(
  * Return Value
  *     0 in case of success; -ENOMEM in case of failure
  */
-static int __devinit
-pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
 {
        int i;
 
@@ -4855,8 +4854,7 @@ pmcraid_allocate_cmd_blocks(struct pmcraid_instance *pinstance)
  * Return Value
  *  0 in case it can allocate all control blocks, otherwise -ENOMEM
  */
-static int __devinit
-pmcraid_allocate_control_blocks(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_control_blocks(struct pmcraid_instance *pinstance)
 {
        int i;
 
@@ -4922,8 +4920,7 @@ pmcraid_release_host_rrqs(struct pmcraid_instance *pinstance, int maxindex)
  * Return value
  *     0 hrrq buffers are allocated, -ENOMEM otherwise.
  */
-static int __devinit
-pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance)
 {
        int i, buffer_size;
 
@@ -5062,8 +5059,7 @@ static void pmcraid_release_config_buffers(struct pmcraid_instance *pinstance)
  * Return Value
  *     0 for successful allocation, -ENOMEM for any failure
  */
-static int __devinit
-pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance)
+static int pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance)
 {
        int i;
 
@@ -5181,7 +5177,7 @@ static void pmcraid_release_buffers(struct pmcraid_instance *pinstance)
  * Return Value
  *      0 in case all of the blocks are allocated, -ENOMEM otherwise.
  */
-static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance)
+static int pmcraid_init_buffers(struct pmcraid_instance *pinstance)
 {
        int i;
 
@@ -5281,11 +5277,8 @@ static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance)
  * Return Value
  *      0 on success, non-zero in case of any failure
  */
-static int __devinit pmcraid_init_instance(
-       struct pci_dev *pdev,
-       struct Scsi_Host *host,
-       void __iomem *mapped_pci_addr
-)
+static int pmcraid_init_instance(struct pci_dev *pdev, struct Scsi_Host *host,
+                                void __iomem *mapped_pci_addr)
 {
        struct pmcraid_instance *pinstance =
                (struct pmcraid_instance *)host->hostdata;
@@ -5442,7 +5435,7 @@ static void pmcraid_release_chrdev(struct pmcraid_instance *pinstance)
  * Return value
  *       none
  */
-static void __devexit pmcraid_remove(struct pci_dev *pdev)
+static void pmcraid_remove(struct pci_dev *pdev)
 {
        struct pmcraid_instance *pinstance = pci_get_drvdata(pdev);
 
@@ -5883,10 +5876,8 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd)
  *     returns 0 if the device is claimed and successfully configured.
  *     returns non-zero error code in case of any failure
  */
-static int __devinit pmcraid_probe(
-       struct pci_dev *pdev,
-       const struct pci_device_id *dev_id
-)
+static int pmcraid_probe(struct pci_dev *pdev,
+                        const struct pci_device_id *dev_id)
 {
        struct pmcraid_instance *pinstance;
        struct Scsi_Host *host;
index 959f10055be77cf2e9cf04e98d0229633cfa8489..e6e2a30493e69d6baeda15585a840865fd26c6f9 100644 (file)
@@ -359,7 +359,7 @@ static struct scsi_host_template ps3rom_host_template = {
 };
 
 
-static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
+static int ps3rom_probe(struct ps3_system_bus_device *_dev)
 {
        struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
        int error;
index 538230be5cca1be39898aa37bffb1d220f1ddb41..5a522c5bbd433910e3f745005fe3bc6ded93da54 100644 (file)
@@ -1438,7 +1438,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
  * Returns:
  *      0 = success
  */
-static int __devinit
+static int
 qla1280_initialize_adapter(struct scsi_qla_host *ha)
 {
        struct device_reg __iomem *reg;
@@ -4230,7 +4230,7 @@ static struct scsi_host_template qla1280_driver_template = {
 };
 
 
-static int __devinit
+static int
 qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int devnum = id->driver_data;
@@ -4399,7 +4399,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 }
 
 
-static void __devexit
+static void
 qla1280_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -4433,7 +4433,7 @@ static struct pci_driver qla1280_pci_driver = {
        .name           = "qla1280",
        .id_table       = qla1280_pci_tbl,
        .probe          = qla1280_probe_one,
-       .remove         = __devexit_p(qla1280_remove_one),
+       .remove         = qla1280_remove_one,
 };
 
 static int __init
index 3a1661cf8c1e59bcc94837fc003a68d6963e70ce..10d23f8b7036c11c025e4341829046667749d38f 100644 (file)
@@ -2154,7 +2154,7 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
 /*
  * PCI driver interface
  */
-static int __devinit
+static int
 qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int     ret = -ENODEV;
index fbc546e893ac2bcad8ea7a42d430096ea2905429..4cec123a6a6a5f02503bb3ebc4175479cbe10030 100644 (file)
@@ -5124,8 +5124,8 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
  * It returns zero if successful. It also initializes all data necessary for
  * the driver.
  **/
-static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
-                                          const struct pci_device_id *ent)
+static int qla4xxx_probe_adapter(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
 {
        int ret = -ENODEV, status;
        struct Scsi_Host *host;
@@ -5464,7 +5464,7 @@ static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)
  * qla4xxx_remove_adapter - callback function to remove adapter.
  * @pci_dev: PCI device pointer
  **/
-static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
+static void qla4xxx_remove_adapter(struct pci_dev *pdev)
 {
        struct scsi_qla_host *ha;
 
index 1e874f1fb5c64a403fd6e7da8365edce51b929df..13d628b56ff790473d2088759fba4d8a32b7cd1e 100644 (file)
@@ -142,7 +142,7 @@ module_param_array(irq, int, NULL, 0);
 MODULE_PARM_DESC(iobase, "I/O address");
 MODULE_PARM_DESC(irq, "IRQ");
 
-static int __devinit qlogicfas_detect(struct scsi_host_template *sht)
+static int qlogicfas_detect(struct scsi_host_template *sht)
 {
        struct Scsi_Host *shost;
        struct qlogicfas408_priv *priv;
index 71fddbc60f181feb15bbd30994f16dc5b35d4831..6d48d30bed050d350768ec7ffb3a9e64b7bd04f2 100644 (file)
@@ -461,7 +461,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
 
 #define PTI_RESET_LIMIT 400
 
-static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
+static int qlogicpti_load_firmware(struct qlogicpti *qpti)
 {
        const struct firmware *fw;
        const char fwname[] = "qlogic/isp1000.bin";
@@ -670,7 +670,7 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
 
 static irqreturn_t qpti_intr(int irq, void *dev_id);
 
-static void __devinit qpti_chain_add(struct qlogicpti *qpti)
+static void qpti_chain_add(struct qlogicpti *qpti)
 {
        spin_lock_irq(&qptichain_lock);
        if (qptichain != NULL) {
@@ -686,7 +686,7 @@ static void __devinit qpti_chain_add(struct qlogicpti *qpti)
        spin_unlock_irq(&qptichain_lock);
 }
 
-static void __devexit qpti_chain_del(struct qlogicpti *qpti)
+static void qpti_chain_del(struct qlogicpti *qpti)
 {
        spin_lock_irq(&qptichain_lock);
        if (qptichain == qpti) {
@@ -701,7 +701,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti)
        spin_unlock_irq(&qptichain_lock);
 }
 
-static int __devinit qpti_map_regs(struct qlogicpti *qpti)
+static int qpti_map_regs(struct qlogicpti *qpti)
 {
        struct platform_device *op = qpti->op;
 
@@ -724,7 +724,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti)
        return 0;
 }
 
-static int __devinit qpti_register_irq(struct qlogicpti *qpti)
+static int qpti_register_irq(struct qlogicpti *qpti)
 {
        struct platform_device *op = qpti->op;
 
@@ -749,7 +749,7 @@ fail:
        return -1;
 }
 
-static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti)
+static void qpti_get_scsi_id(struct qlogicpti *qpti)
 {
        struct platform_device *op = qpti->op;
        struct device_node *dp;
@@ -803,7 +803,7 @@ static void qpti_get_clock(struct qlogicpti *qpti)
 /* The request and response queues must each be aligned
  * on a page boundary.
  */
-static int __devinit qpti_map_queues(struct qlogicpti *qpti)
+static int qpti_map_queues(struct qlogicpti *qpti)
 {
        struct platform_device *op = qpti->op;
 
@@ -1292,7 +1292,7 @@ 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)
+static int qpti_sbus_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct Scsi_Host *host;
@@ -1402,7 +1402,7 @@ fail_unlink:
        return -ENODEV;
 }
 
-static int __devexit qpti_sbus_remove(struct platform_device *op)
+static int qpti_sbus_remove(struct platform_device *op)
 {
        struct qlogicpti *qpti = dev_get_drvdata(&op->dev);
 
@@ -1459,7 +1459,7 @@ static struct platform_driver qpti_sbus_driver = {
                .of_match_table = qpti_match,
        },
        .probe          = qpti_sbus_probe,
-       .remove         = __devexit_p(qpti_sbus_remove),
+       .remove         = qpti_sbus_remove,
 };
 
 static int __init qpti_init(void)
index 3a9d85ca6047068b495c208a844f5a4ce3c71b52..a464d959f66e647d7f923f8d2c0099119a2b41af 100644 (file)
@@ -226,7 +226,7 @@ static struct scsi_host_template sgiwd93_template = {
        .use_clustering         = DISABLE_CLUSTERING,
 };
 
-static int __devinit sgiwd93_probe(struct platform_device *pdev)
+static int sgiwd93_probe(struct platform_device *pdev)
 {
        struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
        unsigned char *wdregs = pd->wdregs;
@@ -312,7 +312,7 @@ static int __exit sgiwd93_remove(struct platform_device *pdev)
 
 static struct platform_driver sgiwd93_driver = {
        .probe  = sgiwd93_probe,
-       .remove = __devexit_p(sgiwd93_remove),
+       .remove = sgiwd93_remove,
        .driver = {
                .name   = "sgiwd93",
                .owner  = THIS_MODULE,
index a318264a4ba1dc8895faeb8d058899e1e28b2318..3b3b56f4a8300ae7ebac68f4c27fb26863cef1e8 100644 (file)
@@ -94,9 +94,9 @@ static struct scsi_host_template sim710_driver_template = {
        .module                 = THIS_MODULE,
 };
 
-static __devinit int
-sim710_probe_common(struct device *dev, unsigned long base_addr,
-                   int irq, int clock, int differential, int scsi_id)
+static int sim710_probe_common(struct device *dev, unsigned long base_addr,
+                              int irq, int clock, int differential,
+                              int scsi_id)
 {
        struct Scsi_Host * host = NULL;
        struct NCR_700_Host_Parameters *hostdata =
@@ -153,8 +153,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
        return -ENODEV;
 }
 
-static __devexit int
-sim710_device_remove(struct device *dev)
+static int sim710_device_remove(struct device *dev)
 {
        struct Scsi_Host *host = dev_get_drvdata(dev);
        struct NCR_700_Host_Parameters *hostdata =
@@ -221,7 +220,7 @@ static struct eisa_driver sim710_eisa_driver = {
        .driver = {
                .name           = "sim710",
                .probe          = sim710_eisa_probe,
-               .remove         = __devexit_p(sim710_device_remove),
+               .remove         = sim710_device_remove,
        },
 };
 #endif /* CONFIG_EISA */
index cf51432f8e72e94add7726b5aa323d7c54cc79ed..52d54e7425db957b2dc1805935a2365ade7eb98a 100644 (file)
@@ -65,7 +65,7 @@ static struct scsi_host_template snirm710_template = {
        .module         = THIS_MODULE,
 };
 
-static int __devinit snirm710_probe(struct platform_device *dev)
+static int snirm710_probe(struct platform_device *dev)
 {
        unsigned long base;
        struct NCR_700_Host_Parameters *hostdata;
@@ -134,7 +134,7 @@ static int __exit snirm710_driver_remove(struct platform_device *dev)
 
 static struct platform_driver snirm710_driver = {
        .probe  = snirm710_probe,
-       .remove = __devexit_p(snirm710_driver_remove),
+       .remove = snirm710_driver_remove,
        .driver = {
                .name   = "snirm_53c710",
                .owner  = THIS_MODULE,
index 606215e54b8896f38deeb51603a29f8e12cd5e40..325c31caa6e0dd98dbce0724b968a7ee5efcba69 100644 (file)
@@ -1540,8 +1540,7 @@ static void stex_free_irq(struct st_hba *hba)
                pci_disable_msi(pdev);
 }
 
-static int __devinit
-stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct st_hba *hba;
        struct Scsi_Host *host;
@@ -1815,7 +1814,7 @@ static struct pci_driver stex_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = stex_pci_tbl,
        .probe          = stex_probe,
-       .remove         = __devexit_p(stex_remove),
+       .remove         = stex_remove,
        .shutdown       = stex_shutdown,
 };
 
index 0621037f027129970748ac77ad918ef0dd6d1442..534eb96fc3a7c4892b9f2fc82c165095d52d3166 100644 (file)
@@ -194,7 +194,7 @@ static const struct esp_driver_ops sun3x_esp_ops = {
        .dma_error      =       sun3x_esp_dma_error,
 };
 
-static int __devinit esp_sun3x_probe(struct platform_device *dev)
+static int esp_sun3x_probe(struct platform_device *dev)
 {
        struct scsi_host_template *tpnt = &scsi_esp_template;
        struct Scsi_Host *host;
@@ -268,7 +268,7 @@ fail:
        return err;
 }
 
-static int __devexit esp_sun3x_remove(struct platform_device *dev)
+static int esp_sun3x_remove(struct platform_device *dev)
 {
        struct esp *esp = dev_get_drvdata(&dev->dev);
        unsigned int irq = esp->host->irq;
@@ -292,7 +292,7 @@ static int __devexit esp_sun3x_remove(struct platform_device *dev)
 
 static struct platform_driver esp_sun3x_driver = {
        .probe          = esp_sun3x_probe,
-       .remove         = __devexit_p(esp_sun3x_remove),
+       .remove         = esp_sun3x_remove,
        .driver = {
                .name   = "sun3x_esp",
                .owner  = THIS_MODULE,
index 676fe9ac7f61267bf156f7235aaa94e3c29af0a0..f2e68459f7ea6fa8d775c40ec93a49534ea675f3 100644 (file)
@@ -43,8 +43,7 @@ enum dvma_rev {
        dvmahme
 };
 
-static int __devinit esp_sbus_setup_dma(struct esp *esp,
-                                       struct platform_device *dma_of)
+static int esp_sbus_setup_dma(struct esp *esp, struct platform_device *dma_of)
 {
        esp->dma = dma_of;
 
@@ -79,7 +78,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp,
 
 }
 
-static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
+static int esp_sbus_map_regs(struct esp *esp, int hme)
 {
        struct platform_device *op = esp->dev;
        struct resource *res;
@@ -99,7 +98,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
        return 0;
 }
 
-static int __devinit esp_sbus_map_command_block(struct esp *esp)
+static int esp_sbus_map_command_block(struct esp *esp)
 {
        struct platform_device *op = esp->dev;
 
@@ -111,7 +110,7 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp)
        return 0;
 }
 
-static int __devinit esp_sbus_register_irq(struct esp *esp)
+static int esp_sbus_register_irq(struct esp *esp)
 {
        struct Scsi_Host *host = esp->host;
        struct platform_device *op = esp->dev;
@@ -120,7 +119,7 @@ static int __devinit esp_sbus_register_irq(struct esp *esp)
        return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
 }
 
-static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
+static void esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
 {
        struct platform_device *op = esp->dev;
        struct device_node *dp;
@@ -142,7 +141,7 @@ done:
        esp->scsi_id_mask = (1 << esp->scsi_id);
 }
 
-static void __devinit esp_get_differential(struct esp *esp)
+static void esp_get_differential(struct esp *esp)
 {
        struct platform_device *op = esp->dev;
        struct device_node *dp;
@@ -154,7 +153,7 @@ static void __devinit esp_get_differential(struct esp *esp)
                esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
 }
 
-static void __devinit esp_get_clock_params(struct esp *esp)
+static void esp_get_clock_params(struct esp *esp)
 {
        struct platform_device *op = esp->dev;
        struct device_node *bus_dp, *dp;
@@ -170,7 +169,7 @@ static void __devinit esp_get_clock_params(struct esp *esp)
        esp->cfreq = fmhz;
 }
 
-static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
+static void esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
 {
        struct device_node *dma_dp = dma_of->dev.of_node;
        struct platform_device *op = esp->dev;
@@ -195,7 +194,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dm
        esp->bursts = bursts;
 }
 
-static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
+static void esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
 {
        esp_get_scsi_id(esp, espdma);
        esp_get_differential(esp);
@@ -487,9 +486,8 @@ static const struct esp_driver_ops sbus_esp_ops = {
        .dma_error      =       sbus_esp_dma_error,
 };
 
-static int __devinit esp_sbus_probe_one(struct platform_device *op,
-                                       struct platform_device *espdma,
-                                       int hme)
+static int esp_sbus_probe_one(struct platform_device *op,
+                             struct platform_device *espdma, int hme)
 {
        struct scsi_host_template *tpnt = &scsi_esp_template;
        struct Scsi_Host *host;
@@ -562,7 +560,7 @@ fail:
        return err;
 }
 
-static int __devinit esp_sbus_probe(struct platform_device *op)
+static int esp_sbus_probe(struct platform_device *op)
 {
        struct device_node *dma_node = NULL;
        struct device_node *dp = op->dev.of_node;
@@ -585,7 +583,7 @@ static int __devinit esp_sbus_probe(struct platform_device *op)
        return esp_sbus_probe_one(op, dma_of, hme);
 }
 
-static int __devexit esp_sbus_remove(struct platform_device *op)
+static int esp_sbus_remove(struct platform_device *op)
 {
        struct esp *esp = dev_get_drvdata(&op->dev);
        struct platform_device *dma_of = esp->dma;
@@ -639,7 +637,7 @@ static struct platform_driver esp_sbus_driver = {
                .of_match_table = esp_match,
        },
        .probe          = esp_sbus_probe,
-       .remove         = __devexit_p(esp_sbus_remove),
+       .remove         = esp_sbus_remove,
 };
 
 static int __init sunesp_init(void)
index ac4eca6a532810d71de3812cf377847d484bc388..0b7819f3e09b1736288a1827b5410c39efcdc437 100644 (file)
@@ -581,7 +581,7 @@ static int sym53c416_test(int base)
 }
 
 
-static struct isapnp_device_id id_table[] __devinitdata = {
+static struct isapnp_device_id id_table[] = {
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
                ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4161), 0 },
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
index e2b8e68b57e7b3dfe1a467e0046a9d83318713c1..599568299fbea49bce5847b060645d59f059b76e 100644 (file)
@@ -1284,8 +1284,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
  * sym_free_resources() should be used instead of this function after calling
  * sym_attach().
  */
-static void __devinit
-sym_iounmap_device(struct sym_device *device)
+static void sym_iounmap_device(struct sym_device *device)
 {
        if (device->s.ioaddr)
                pci_iounmap(device->pdev, device->s.ioaddr);
@@ -1325,8 +1324,8 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
  *  If all is OK, install interrupt handling and
  *  start the timer daemon.
  */
-static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
-               int unit, struct sym_device *dev)
+static struct Scsi_Host *sym_attach(struct scsi_host_template *tpnt, int unit,
+                                   struct sym_device *dev)
 {
        struct sym_data *sym_data;
        struct sym_hcb *np = NULL;
@@ -1481,7 +1480,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
  *    Detect and try to read SYMBIOS and TEKRAM NVRAM.
  */
 #if SYM_CONF_NVRAM_SUPPORT
-static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
+static void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
 {
        devp->nvram = nvp;
        nvp->type = 0;
@@ -1494,7 +1493,7 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
 }
 #endif /* SYM_CONF_NVRAM_SUPPORT */
 
-static int __devinit sym_check_supported(struct sym_device *device)
+static int sym_check_supported(struct sym_device *device)
 {
        struct sym_chip *chip;
        struct pci_dev *pdev = device->pdev;
@@ -1531,7 +1530,7 @@ static int __devinit sym_check_supported(struct sym_device *device)
  * Ignore Symbios chips controlled by various RAID controllers.
  * These controllers set value 0x52414944 at RAM end - 16.
  */
-static int __devinit sym_check_raid(struct sym_device *device)
+static int sym_check_raid(struct sym_device *device)
 {
        unsigned int ram_size, ram_val;
 
@@ -1552,7 +1551,7 @@ static int __devinit sym_check_raid(struct sym_device *device)
        return -ENODEV;
 }
 
-static int __devinit sym_set_workarounds(struct sym_device *device)
+static int sym_set_workarounds(struct sym_device *device)
 {
        struct sym_chip *chip = &device->chip;
        struct pci_dev *pdev = device->pdev;
@@ -1602,8 +1601,7 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
 /*
  * Map HBA registers and on-chip SRAM (if present).
  */
-static int __devinit
-sym_iomap_device(struct sym_device *device)
+static int sym_iomap_device(struct sym_device *device)
 {
        struct pci_dev *pdev = device->pdev;
        struct pci_bus_region bus_addr;
@@ -1751,8 +1749,7 @@ static struct scsi_host_template sym2_template = {
 
 static int attach_count;
 
-static int __devinit sym2_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int sym2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct sym_device sym_dev;
        struct sym_nvram nvram;
@@ -2077,7 +2074,7 @@ static struct spi_function_template sym2_transport_functions = {
        .get_signalling = sym2_get_signalling,
 };
 
-static struct pci_device_id sym2_id_table[] __devinitdata = {
+static struct pci_device_id sym2_id_table[] = {
        { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C810,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C820,
index a1baccce05f08a9abbae70522a478ce5f2f12911..9327f5fcec4e85c9a8d8606bd9347b7d0702709e 100644 (file)
@@ -2219,7 +2219,7 @@ static struct scsi_host_template driver_template = {
  *
  **********************************************************************/
 
-static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
 {
        u8 carryFlag = 1, j = 0x80, bval;
        int i;
@@ -2242,7 +2242,7 @@ static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
        }
 }
 
-static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
 {
        int i;
        u16 wval = 0;
@@ -2264,7 +2264,7 @@ static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
        return wval;
 }
 
-static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
 {
        u8 cmd = EEPROM_READ, i;
 
@@ -2282,7 +2282,7 @@ static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
 }
 
 /* Override EEprom values with explicitly set values */
-static void __devinit dc390_eeprom_override(u8 index)
+static void dc390_eeprom_override(u8 index)
 {
        u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
 
@@ -2305,7 +2305,7 @@ static void __devinit dc390_eeprom_override(u8 index)
        }
 }
 
-static int __devinitdata tmscsim_def[] = {
+static int tmscsim_def[] = {
        7,
        0 /* 10MHz */,
        PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
@@ -2315,7 +2315,7 @@ static int __devinitdata tmscsim_def[] = {
 };
 
 /* Copy defaults over set values where missing */
-static void __devinit dc390_fill_with_defaults (void)
+static void dc390_fill_with_defaults (void)
 {
        int i;
 
@@ -2335,7 +2335,7 @@ static void __devinit dc390_fill_with_defaults (void)
                tmscsim[5] = 180;
 }
 
-static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
+static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
 {
        u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
        u8 EEbuf[128];
@@ -2372,7 +2372,7 @@ static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
        }
 }
 
-static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
+static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
 {
        struct Scsi_Host *shost = pACB->pScsiHost;
        u8 dstate;
@@ -2422,8 +2422,7 @@ static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
        DC390_write8(DMA_Status, dstate);
 }
 
-static int __devinit dc390_probe_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
+static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct dc390_acb *pACB;
        struct Scsi_Host *shost;
@@ -2532,7 +2531,7 @@ static int __devinit dc390_probe_one(struct pci_dev *pdev,
  *
  * @dev: The PCI device to remove.
  */
-static void __devexit dc390_remove_one(struct pci_dev *dev)
+static void dc390_remove_one(struct pci_dev *dev)
 {
        struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
        unsigned long iflags;
@@ -2568,7 +2567,7 @@ static struct pci_driver dc390_driver = {
        .name           = "tmscsim",
        .id_table       = tmscsim_pci_tbl,
        .probe          = dc390_probe_one,
-       .remove         = __devexit_p(dc390_remove_one),
+       .remove         = dc390_remove_one,
 };
 
 static int __init dc390_module_init(void)
index 58f4ba6fe4124320a49e10e282d60e42f624adfe..91a4046ca9ba438f920b8e2b3e2a03b22ed4c682 100644 (file)
@@ -1811,8 +1811,7 @@ static int ufshcd_set_dma_mask(struct ufs_hba *hba)
  *
  * Returns 0 on success, non-zero value on failure
  */
-static int __devinit
-ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct Scsi_Host *host;
        struct ufs_hba *hba;
@@ -1947,7 +1946,7 @@ static struct pci_driver ufshcd_pci_driver = {
        .name = UFSHCD,
        .id_table = ufshcd_pci_tbl,
        .probe = ufshcd_probe,
-       .remove = __devexit_p(ufshcd_remove),
+       .remove = ufshcd_remove,
        .shutdown = ufshcd_shutdown,
 #ifdef CONFIG_PM
        .suspend = ufshcd_suspend,
index 74ab67a169ec2b170cd9c92137852cfdb56e6fea..3449a1f8c656246d2a0aa6631c46d8b53f571e9f 100644 (file)
@@ -679,7 +679,7 @@ out:
        return err;
 }
 
-static int __devinit virtscsi_probe(struct virtio_device *vdev)
+static int virtscsi_probe(struct virtio_device *vdev)
 {
        struct Scsi_Host *shost;
        struct virtio_scsi *vscsi;
@@ -733,7 +733,7 @@ virtscsi_init_failed:
        return err;
 }
 
-static void __devexit virtscsi_remove(struct virtio_device *vdev)
+static void virtscsi_remove(struct virtio_device *vdev)
 {
        struct Scsi_Host *shost = virtio_scsi_host(vdev);
        struct virtio_scsi *vscsi = shost_priv(shost);
@@ -785,7 +785,7 @@ static struct virtio_driver virtio_scsi_driver = {
        .freeze = virtscsi_freeze,
        .restore = virtscsi_restore,
 #endif
-       .remove = __devexit_p(virtscsi_remove),
+       .remove = virtscsi_remove,
 };
 
 static int __init init(void)
index 20b3a483c2ccedada3a5b65f53bdd1db0f4b07cb..3bfaa66fa0d16d31610ee33ef41c9cce10031f1a 100644 (file)
@@ -397,7 +397,7 @@ static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
                                 SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE);
 }
 
-static int __devinit pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
+static int pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
 {
        adapter->rings_state = pci_alloc_consistent(adapter->dev, PAGE_SIZE,
                                                    &adapter->ringStatePA);
@@ -1152,7 +1152,7 @@ static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
  * just use a statically allocated scatter list.
  *
  */
-static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
+static int pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
 {
        struct pvscsi_ctx *ctx;
        int i;
@@ -1233,8 +1233,7 @@ exit:
        return numPhys;
 }
 
-static int __devinit pvscsi_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id)
+static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct pvscsi_adapter *adapter;
        struct Scsi_Host *host;
@@ -1454,7 +1453,7 @@ static struct pci_driver pvscsi_pci_driver = {
        .name           = "vmw_pvscsi",
        .id_table       = pvscsi_pci_tbl,
        .probe          = pvscsi_probe,
-       .remove         = __devexit_p(pvscsi_remove),
+       .remove         = pvscsi_remove,
        .shutdown       = pvscsi_shutdown,
 };
 
index 27e84e4b1fa98857d571f3abafdfe9f4b03cf7ad..97ccb0383539e42429b0ef77303cb6f032b29ed3 100644 (file)
@@ -182,7 +182,7 @@ static struct parisc_driver zalon_driver = {
        .name =         "zalon",
        .id_table =     zalon_tbl,
        .probe =        zalon_probe,
-       .remove =       __devexit_p(zalon_remove),
+       .remove =       zalon_remove,
 };
 
 static int __init zalon7xx_init(void)
index e17764d7147624045fefb50ea95c477a9b04a8a1..cbf3476c68cd3511e13592296198da53ddcc441d 100644 (file)
@@ -38,7 +38,7 @@ static struct zorro_driver_data {
        const char *name;
        unsigned long offset;
        int absolute;   /* offset is absolute address */
-} zorro7xx_driver_data[] __devinitdata = {
+} zorro7xx_driver_data[] = {
        { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
        { .name = "WarpEngine 40xx", .offset = 0x40000 },
        { .name = "A4091", .offset = 0x800000 },
@@ -46,7 +46,7 @@ static struct zorro_driver_data {
        { 0 }
 };
 
-static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id zorro7xx_zorro_tbl[] = {
        {
                .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
                .driver_data = (unsigned long)&zorro7xx_driver_data[0],
@@ -71,8 +71,8 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
 
-static int __devinit zorro7xx_init_one(struct zorro_dev *z,
-                                      const struct zorro_device_id *ent)
+static int zorro7xx_init_one(struct zorro_dev *z,
+                            const struct zorro_device_id *ent)
 {
        struct Scsi_Host *host;
        struct NCR_700_Host_Parameters *hostdata;
@@ -150,7 +150,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z,
        return -ENODEV;
 }
 
-static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
+static void zorro7xx_remove_one(struct zorro_dev *z)
 {
        struct Scsi_Host *host = zorro_get_drvdata(z);
        struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
@@ -167,7 +167,7 @@ static struct zorro_driver zorro7xx_driver = {
        .name     = "zorro7xx-scsi",
        .id_table = zorro7xx_zorro_tbl,
        .probe    = zorro7xx_init_one,
-       .remove   = __devexit_p(zorro7xx_remove_one),
+       .remove   = zorro7xx_remove_one,
 };
 
 static int __init zorro7xx_scsi_init(void)
index 5aedcdf4ac5cd185a2ffac8ebcca2e3dcffd6c27..1ebe67cd18333c3b39f98d0e2badcd7b0a948090 100644 (file)
@@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
 
 static int sh_clk_div_enable(struct clk *clk)
 {
+       if (clk->div_mask == SH_CLK_DIV6_MSK) {
+               int ret = sh_clk_div_set_rate(clk, clk->rate);
+               if (ret < 0)
+                       return ret;
+       }
+
        sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
        return 0;
 }
index 038fa071382ac0e3c89be50977bb25b6160f58d5..6a24f07c2013b0bf4fce27384edc1e3e31ba12ee 100644 (file)
@@ -165,7 +165,7 @@ static int sh_pfc_gpio_match(struct gpio_chip *gc, void *data)
        return !!strstr(gc->label, data);
 }
 
-static int __devinit sh_pfc_gpio_probe(struct platform_device *pdev)
+static int sh_pfc_gpio_probe(struct platform_device *pdev)
 {
        struct sh_pfc_chip *chip;
        struct gpio_chip *gc;
@@ -184,7 +184,7 @@ static int __devinit sh_pfc_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit sh_pfc_gpio_remove(struct platform_device *pdev)
+static int sh_pfc_gpio_remove(struct platform_device *pdev)
 {
        struct sh_pfc_chip *chip = platform_get_drvdata(pdev);
        int ret;
@@ -199,7 +199,7 @@ static int __devexit sh_pfc_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver sh_pfc_gpio_driver = {
        .probe          = sh_pfc_gpio_probe,
-       .remove         = __devexit_p(sh_pfc_gpio_remove),
+       .remove         = sh_pfc_gpio_remove,
        .driver         = {
                .name   = KBUILD_MODNAME,
                .owner  = THIS_MODULE,
index 0646bf6e7889a10ed6e4773af378c264377d5f8b..4109b769eac034160b718a847f0bcfd83c02a2f8 100644 (file)
@@ -328,10 +328,10 @@ static struct pinctrl_desc sh_pfc_pinctrl_desc = {
        .confops        = &sh_pfc_pinconf_ops,
 };
 
-static inline void __devinit sh_pfc_map_one_gpio(struct sh_pfc *pfc,
-                                                struct sh_pfc_pinctrl *pmx,
-                                                struct pinmux_gpio *gpio,
-                                                unsigned offset)
+static inline void sh_pfc_map_one_gpio(struct sh_pfc *pfc,
+                                      struct sh_pfc_pinctrl *pmx,
+                                      struct pinmux_gpio *gpio,
+                                      unsigned offset)
 {
        struct pinmux_data_reg *dummy;
        unsigned long flags;
@@ -351,8 +351,7 @@ static inline void __devinit sh_pfc_map_one_gpio(struct sh_pfc *pfc,
 }
 
 /* pinmux ranges -> pinctrl pin descs */
-static int __devinit sh_pfc_map_gpios(struct sh_pfc *pfc,
-                                     struct sh_pfc_pinctrl *pmx)
+static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 {
        unsigned long flags;
        int i;
@@ -396,8 +395,7 @@ static int __devinit sh_pfc_map_gpios(struct sh_pfc *pfc,
        return 0;
 }
 
-static int __devinit sh_pfc_map_functions(struct sh_pfc *pfc,
-                                         struct sh_pfc_pinctrl *pmx)
+static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 {
        unsigned long flags;
        int i, fn;
@@ -421,7 +419,7 @@ static int __devinit sh_pfc_map_functions(struct sh_pfc *pfc,
        return 0;
 }
 
-static int __devinit sh_pfc_pinctrl_probe(struct platform_device *pdev)
+static int sh_pfc_pinctrl_probe(struct platform_device *pdev)
 {
        struct sh_pfc *pfc;
        int ret;
@@ -465,7 +463,7 @@ free_pads:
        return ret;
 }
 
-static int __devexit sh_pfc_pinctrl_remove(struct platform_device *pdev)
+static int sh_pfc_pinctrl_remove(struct platform_device *pdev)
 {
        struct sh_pfc_pinctrl *pmx = platform_get_drvdata(pdev);
 
@@ -482,7 +480,7 @@ static int __devexit sh_pfc_pinctrl_remove(struct platform_device *pdev)
 
 static struct platform_driver sh_pfc_pinctrl_driver = {
        .probe          = sh_pfc_pinctrl_probe,
-       .remove         = __devexit_p(sh_pfc_pinctrl_remove),
+       .remove         = sh_pfc_pinctrl_remove,
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index b3b33fa26acda7bb99483341980f47bed9e6a213..fb7ea0d9a734dad8de9cbc66c6a80c7bab958b23 100644 (file)
@@ -575,11 +575,10 @@ void ioc3_unregister_submodule(struct ioc3_submodule *is)
  * Device management *
  *********************/
 
-static char * __devinitdata
-ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3",
-                       "MENET 4", "CADduo", "Altix Serial"};
+static char *ioc3_class_names[] = { "unknown", "IP27 BaseIO", "IP30 system",
+                       "MENET 1/2/3", "MENET 4", "CADduo", "Altix Serial" };
 
-static int __devinit ioc3_class(struct ioc3_driver_data *idd)
+static int ioc3_class(struct ioc3_driver_data *idd)
 {
        int res = IOC3_CLASS_NONE;
        /* NIC-based logic */
@@ -602,8 +601,7 @@ static int __devinit ioc3_class(struct ioc3_driver_data *idd)
        return res;
 }
 /* Adds a new instance of an IOC3 card */
-static int __devinit
-ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
        struct ioc3_driver_data *idd;
        uint32_t pcmd;
@@ -755,7 +753,7 @@ out:
 }
 
 /* Removes a particular instance of an IOC3 card. */
-static void __devexit ioc3_remove(struct pci_dev *pdev)
+static void ioc3_remove(struct pci_dev *pdev)
 {
        int id;
        struct ioc3_driver_data *idd;
@@ -807,7 +805,7 @@ static struct pci_driver ioc3_driver = {
        .name = "IOC3",
        .id_table = ioc3_id_table,
        .probe = ioc3_probe,
-       .remove = __devexit_p(ioc3_remove),
+       .remove = ioc3_remove,
 };
 
 MODULE_DEVICE_TABLE(pci, ioc3_id_table);
index 19ee901577da8d1649b975e9873b7a6c1e40029f..3a6083b386a134416c13b7f8e2c08cbe2e0fef11 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/export.h>
-#include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/ioport.h>
index ff3c8a21f10d90397dc9fda07b99dcfb08ebc9b9..5d6f2ec1c705f4ede0ced96ca75efdf8495879d6 100644 (file)
@@ -162,8 +162,7 @@ config SSB_DRIVER_GIGE
 
 config SSB_DRIVER_GPIO
        bool "SSB GPIO driver"
-       depends on SSB
-       select GPIOLIB
+       depends on SSB && GPIOLIB
        help
          Driver to provide access to the GPIO pins on the bus.
 
index f30ea689933a8be5608c1a0cc331b075a10051fd..21f71a1581fa6cefcd3e055e4001aa259ee92729 100644 (file)
@@ -107,9 +107,8 @@ void gige_pcicfg_write32(struct ssb_gige *dev,
        gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
 }
 
-static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
-                                             unsigned int devfn, int reg,
-                                             int size, u32 *val)
+static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+                                   int reg, int size, u32 *val)
 {
        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
        unsigned long flags;
@@ -138,9 +137,8 @@ static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
-                                              unsigned int devfn, int reg,
-                                              int size, u32 val)
+static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+                                    int reg, int size, u32 val)
 {
        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
        unsigned long flags;
@@ -169,8 +167,8 @@ static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int __devinit ssb_gige_probe(struct ssb_device *sdev,
-                                   const struct ssb_device_id *id)
+static int ssb_gige_probe(struct ssb_device *sdev,
+                         const struct ssb_device_id *id)
 {
        struct ssb_gige *dev;
        u32 base, tmslow, tmshigh;
index 97ac0a38e3d0c7277aaab702078d2878db20f1cd..eb2753008ef0550b6c3bfeda984ca9dfe47d26bd 100644 (file)
@@ -174,3 +174,15 @@ int ssb_gpio_init(struct ssb_bus *bus)
 
        return -1;
 }
+
+int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       if (ssb_chipco_available(&bus->chipco) ||
+           ssb_extif_available(&bus->extif)) {
+               return gpiochip_remove(&bus->gpio);
+       } else {
+               SSB_WARN_ON(1);
+       }
+
+       return -1;
+}
index 49d209173f55b1de99e306dc105c7ebd5e52c1b5..59801d23d7ec13624010be83c11ce5fd0f80a6c6 100644 (file)
@@ -315,7 +315,7 @@ int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return ssb_mips_irq(extpci_core->dev) + 2;
 }
 
-static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 {
        u32 val;
 
@@ -380,7 +380,7 @@ static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
        register_pci_controller(&ssb_pcicore_controller);
 }
 
-static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
 {
        struct ssb_bus *bus = pc->dev->bus;
        u16 chipid_top;
@@ -413,7 +413,7 @@ static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
  * Workarounds.
  **************************************************/
 
-static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
 {
        u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
        if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -515,7 +515,7 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
  * Generic and Clientmode operation code.
  **************************************************/
 
-static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
 {
        struct ssb_device *pdev = pc->dev;
        struct ssb_bus *bus = pdev->bus;
@@ -534,7 +534,7 @@ static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
        }
 }
 
-void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
+void ssb_pcicore_init(struct ssb_pcicore *pc)
 {
        struct ssb_device *dev = pc->dev;
 
index c82c5c95fe85022180971af93139b8fc33416c50..24dc331b4701efd796381882e635c6ef791c45cf 100644 (file)
@@ -443,6 +443,15 @@ static void ssb_devices_unregister(struct ssb_bus *bus)
 
 void ssb_bus_unregister(struct ssb_bus *bus)
 {
+       int err;
+
+       err = ssb_gpio_unregister(bus);
+       if (err == -EBUSY)
+               ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n");
+       else if (err)
+               ssb_dprintk(KERN_ERR PFX
+                           "Can not unregister GPIO driver: %i\n", err);
+
        ssb_buses_lock();
        ssb_devices_unregister(bus);
        list_del(&bus->list);
@@ -548,7 +557,7 @@ error:
 }
 
 /* Needs ssb_buses_lock() */
-static int __devinit ssb_attach_queued_buses(void)
+static int ssb_attach_queued_buses(void)
 {
        struct ssb_bus *bus, *n;
        int err = 0;
@@ -761,9 +770,9 @@ out:
        return err;
 }
 
-static int __devinit ssb_bus_register(struct ssb_bus *bus,
-                                     ssb_invariants_func_t get_invariants,
-                                     unsigned long baseaddr)
+static int ssb_bus_register(struct ssb_bus *bus,
+                           ssb_invariants_func_t get_invariants,
+                           unsigned long baseaddr)
 {
        int err;
 
@@ -851,8 +860,7 @@ err_disable_xtal:
 }
 
 #ifdef CONFIG_SSB_PCIHOST
-int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
-                                     struct pci_dev *host_pci)
+int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci)
 {
        int err;
 
@@ -875,9 +883,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register);
 #endif /* CONFIG_SSB_PCIHOST */
 
 #ifdef CONFIG_SSB_PCMCIAHOST
-int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
-                                        struct pcmcia_device *pcmcia_dev,
-                                        unsigned long baseaddr)
+int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+                              struct pcmcia_device *pcmcia_dev,
+                              unsigned long baseaddr)
 {
        int err;
 
@@ -897,9 +905,8 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
 #ifdef CONFIG_SSB_SDIOHOST
-int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
-                                      struct sdio_func *func,
-                                      unsigned int quirks)
+int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
+                            unsigned int quirks)
 {
        int err;
 
@@ -919,9 +926,8 @@ int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
 EXPORT_SYMBOL(ssb_bus_sdiobus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
-int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
-                                     unsigned long baseaddr,
-                                     ssb_invariants_func_t get_invariants)
+int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
+                           ssb_invariants_func_t get_invariants)
 {
        int err;
 
index af5448f5e2d2242b86fff652fe58c0f8d3219b67..32ed1fa4a82eae28cad87ea0eeb77333dbe7b8e2 100644 (file)
@@ -54,8 +54,8 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
 # define ssb_pcihost_resume    NULL
 #endif /* CONFIG_PM */
 
-static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+static int ssb_pcihost_probe(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        struct ssb_bus *ssb;
        int err = -ENOMEM;
@@ -111,7 +111,7 @@ static void ssb_pcihost_remove(struct pci_dev *dev)
        pci_set_drvdata(dev, NULL);
 }
 
-int __devinit ssb_pcihost_register(struct pci_driver *driver)
+int ssb_pcihost_register(struct pci_driver *driver)
 {
        driver->probe = ssb_pcihost_probe;
        driver->remove = ssb_pcihost_remove;
index 6c10b66c796cf7ee23ae3e9334086034198e911c..da38305a2d22a2c24de7b4563da7ed0daa7354a0 100644 (file)
@@ -252,11 +252,16 @@ static inline void ssb_extif_init(struct ssb_extif *extif)
 
 #ifdef CONFIG_SSB_DRIVER_GPIO
 extern int ssb_gpio_init(struct ssb_bus *bus);
+extern int ssb_gpio_unregister(struct ssb_bus *bus);
 #else /* CONFIG_SSB_DRIVER_GPIO */
 static inline int ssb_gpio_init(struct ssb_bus *bus)
 {
        return -ENOTSUPP;
 }
+static inline int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       return 0;
+}
 #endif /* CONFIG_SSB_DRIVER_GPIO */
 
 #endif /* LINUX_SSB_PRIVATE_H_ */
index 7de2a10213bd9d49294daa57430992e6934168ea..36eec320569c6bd14d077be6328b34ae4fede36f 100644 (file)
@@ -444,6 +444,7 @@ config COMEDI_ADQ12B
 
 config COMEDI_NI_AT_A2150
        tristate "NI AT-A2150 ISA card support"
+       select COMEDI_FC
        depends on VIRT_TO_BUS
        ---help---
          Enable support for National Instruments AT-A2150 cards
index b7bba1790a20005bbb955c50ba9a142a1480ac51..9b038e4a7e711eea1b5bd3873706847b701de2fe 100644 (file)
@@ -1549,6 +1549,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
        if (cmd == COMEDI_DEVCONFIG) {
                rc = do_devconfig_ioctl(dev,
                                        (struct comedi_devconfig __user *)arg);
+               if (rc == 0)
+                       /* Evade comedi_auto_unconfig(). */
+                       dev_file_info->hardware_device = NULL;
                goto done;
        }
 
index fb3d09323ba145c2460408971459ee29f39bd63b..01de996239f1e6142f07f9851cc840e8ddc14a75 100644 (file)
@@ -345,7 +345,7 @@ static int waveform_ai_cancel(struct comedi_device *dev,
        struct waveform_private *devpriv = dev->private;
 
        devpriv->timer_running = 0;
-       del_timer(&devpriv->timer);
+       del_timer_sync(&devpriv->timer);
        return 0;
 }
 
index aaac0b2cc9eb7172ab963aa361e8d7e828ceb751..fd1662b4175db8755b8c605ed90f08437c12ba4c 100644 (file)
@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_625x_ao,
         .reg_type = ni_reg_625x,
         .ao_unipolar = 0,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 8,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_625x_ao,
         .reg_type = ni_reg_625x,
         .ao_unipolar = 0,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 8,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_625x_ao,
         .reg_type = ni_reg_625x,
         .ao_unipolar = 0,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 8,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_625x_ao,
         .reg_type = ni_reg_625x,
         .ao_unipolar = 0,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 32,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_625x_ao,
         .reg_type = ni_reg_625x,
         .ao_unipolar = 0,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 32,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_628x_ao,
         .reg_type = ni_reg_628x,
         .ao_unipolar = 1,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 8,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_628x_ao,
         .reg_type = ni_reg_628x,
         .ao_unipolar = 1,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 8,
         .caldac = {caldac_none},
         .has_8255 = 0,
@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_boards[] = {
         .ao_range_table = &range_ni_M_628x_ao,
         .reg_type = ni_reg_628x,
         .ao_unipolar = 1,
-        .ao_speed = 357,
+        .ao_speed = 350,
         .num_p0_dio_channels = 32,
         .caldac = {caldac_none},
         .has_8255 = 0,
index 1a1f5c79822ae1dbea65497ba6aac2d71a7a9216..7b133597e923f792a942cffff1ff399546fed8ee 100644 (file)
@@ -15,7 +15,7 @@
  */
 #include "csr_wifi_hip_unifi.h"
 #include "unifi_priv.h"
-
+#include <linux/sched/rt.h>
 
 /*
  * ---------------------------------------------------------------------------
index 7c6c4138fc76dba99998e7be91420cc3a0d01035..49395da34b7f07cd286e307f7d4f832fae3a5070 100644 (file)
@@ -15,7 +15,7 @@
 #include "unifi_priv.h"
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
-
+#include <linux/sched/rt.h>
 
 
 
index 580406cb1808e55b201aafad0611f62ed536744f..b2f8331e4acf90005887a7f1e5947d0c7b560aea 100644 (file)
@@ -3,7 +3,9 @@ config FIREWIRE_SERIAL
        depends on FIREWIRE
        help
           This enables TTY over IEEE 1394, providing high-speed serial
-         connectivity to cabled peers.
+         connectivity to cabled peers. This driver implements a
+         ad-hoc transport protocol and is currently limited to
+         Linux-to-Linux communication.
 
          To compile this driver as a module, say M here:  the module will
          be called firewire-serial.
index 726900548eae5c8136861588d4bce475cd9349b4..8dae8fb252233905b380927218cb80b8bb96e4cc 100644 (file)
@@ -1,5 +1,5 @@
-TODOs
------
+TODOs prior to this driver moving out of staging
+------------------------------------------------
 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR
    - I/O is handled asynchronously which presents some issues when error
      conditions occur.
@@ -11,17 +11,9 @@ TODOs
 -- Issues with firewire stack --
 1. This driver uses the same unregistered vendor id that the firewire core does
      (0xd00d1e). Perhaps this could be exposed as a define in
-     firewire-constants.h?
-2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci
-   - otherwise how will this driver know the max size of address window to
-     open for one packet write?
+     firewire.h?
 3. Maybe device_max_receive() and link_speed_to_max_payload() should be
      taken up by the firewire core?
-4. To avoid dropping rx data while still limiting the maximum buffering,
-     the size of the AR context must be known. How to expose this to drivers?
-5. Explore if bigger AR context will reduce RCODE_BUSY responses
-   (or auto-grow to certain max size -- but this would require major surgery
-    as the current AR is contiguously mapped)
 
 -- Issues with TTY core --
   1. Hack for alternate device name scheme
index 61ee29083b268ece51870b1c80c60035acd4fa55..d03a7f57e8d475ceddedb052d42b3077c2a7745d 100644 (file)
@@ -179,7 +179,7 @@ static void dump_profile(struct seq_file *m, struct stats *stats)
 /* Returns the max receive packet size for the given card */
 static inline int device_max_receive(struct fw_device *fw_device)
 {
-       return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1);
+       return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1);
 }
 
 static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
index 8b572edf95634264ce5897938b1bc279a618c243..caa1c1ea82d5f783782efd263f2f60500a68062b 100644 (file)
@@ -374,10 +374,10 @@ static inline void fwtty_bind_console(struct fwtty_port *port,
  */
 static inline int link_speed_to_max_payload(unsigned speed)
 {
-       static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, };
-       BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200);
+       static const int max_async[] = { 307, 614, 1229, 2458, };
+       BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800);
 
-       speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200);
+       speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800);
        if (limit_bw)
                return max_async[speed];
        else
index fb31b457a56a9b2b50fe96982ce083d25d89a032..c5ceb9d90ea83a696a4ca4518dc379a2c6a82831 100644 (file)
@@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
        struct mxs_lradc *lradc = iio_priv(iio);
        const uint32_t chan_value = LRADC_CH_ACCUMULATE |
                ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
-       int i, j = 0;
+       unsigned int i, j = 0;
 
        for_each_set_bit(i, iio->active_scan_mask, iio->masklength) {
                lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
index ea295b25308c470525e9213ad039c46eadc95ca5..87979a0d03a91358d1e892ed133292f855bfad3e 100644 (file)
@@ -27,8 +27,8 @@ config ADIS16130
 config ADIS16260
        tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
        depends on SPI
-       select IIO_TRIGGER if IIO_BUFFER
-       select IIO_SW_RING if IIO_BUFFER
+       select IIO_ADIS_LIB
+       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
        help
          Say yes here to build support for Analog Devices ADIS16260 ADIS16265
          ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
index 3525a68d6a7529e01eb17c83bc00db5841faa33e..41d7350d030f3e9341175e8b4771068b2913a087 100644 (file)
@@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev,
        ret = spi_read(st->us, st->buf, 2);
 
        if (ret == 0)
-               *val = ((st->buf[0] & 0xF) << 8) | st->buf[1];
+               *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11);
        mutex_unlock(&st->buf_lock);
 
        return ret;
index 7d3207559265c35085652be0a23b3942f5031171..d44d3ad26fa517527f3d1369e28e221b40bc72f3 100644 (file)
@@ -21,7 +21,6 @@ config IIO_GPIO_TRIGGER
 config IIO_SYSFS_TRIGGER
        tristate "SYSFS trigger"
        depends on SYSFS
-       depends on HAVE_IRQ_WORK
        select IRQ_WORK
        help
          Provides support for using SYSFS entry as IIO triggers.
index ecf0f44bc70e1daf8dc4133d5d1a56e251560e8e..cec19f1cf56cb261ae5dc4782d266022813e6c15 100644 (file)
@@ -584,7 +584,6 @@ int imx_drm_add_encoder(struct drm_encoder *encoder,
 
        ret = imx_drm_encoder_register(imx_drm_encoder);
        if (ret) {
-               kfree(imx_drm_encoder);
                ret = -ENOMEM;
                goto err_register;
        }
index 677e665ca86d62dc764db90ca7205385cd2166c2..f7059cddd7fdb2da864ff19975d4ca99fbb0664f 100644 (file)
@@ -1104,7 +1104,9 @@ static int ipu_probe(struct platform_device *pdev)
        if (ret)
                goto out_failed_irq;
 
-       ipu_reset(ipu);
+       ret = ipu_reset(ipu);
+       if (ret)
+               goto out_failed_reset;
 
        /* Set MCU_T to divide MCU access window into 2 */
        ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
@@ -1129,6 +1131,7 @@ failed_add_clients:
        ipu_submodules_exit(ipu);
 failed_submodules_init:
        ipu_irq_exit(ipu);
+out_failed_reset:
 out_failed_irq:
        clk_disable_unprepare(ipu->clk);
 failed_clk_get:
index 1892006526b52fbf85eb19ca8e943db1b96615da..4b3a019409b5793632efa538cdcf65e0030f217f 100644 (file)
@@ -452,7 +452,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
        int ret;
 
        ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]);
-       if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) {
+       if (IS_ERR(ipu_crtc->ipu_ch)) {
                ret = PTR_ERR(ipu_crtc->ipu_ch);
                goto err_out;
        }
@@ -472,7 +472,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
        if (pdata->dp >= 0) {
                ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp);
                if (IS_ERR(ipu_crtc->dp)) {
-                       ret = PTR_ERR(ipu_crtc->ipu_ch);
+                       ret = PTR_ERR(ipu_crtc->dp);
                        goto err_out;
                }
        }
@@ -548,6 +548,8 @@ static int ipu_drm_probe(struct platform_device *pdev)
        ipu_crtc->dev = &pdev->dev;
 
        ret = ipu_crtc_init(ipu_crtc, pdata);
+       if (ret)
+               return ret;
 
        platform_set_drvdata(pdev, ipu_crtc);
 
index b724a41314359053d598176e7ac871ba3a63704e..09f65dc3d2c85397e4147e51291c1b7510450d03 100644 (file)
@@ -3,8 +3,8 @@ config DRM_OMAP
        tristate "OMAP DRM"
        depends on DRM && !CONFIG_FB_OMAP2
        depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
+       depends on OMAP2_DSS
        select DRM_KMS_HELPER
-       select OMAP2_DSS
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
index 1ca0e0016de424b249219b178dcb9ee71654fd06..d85e058f2845a014c0216cabeda52d70cc7bf0b6 100644 (file)
@@ -5,6 +5,7 @@
 
 ccflags-y := -Iinclude/drm -Werror
 omapdrm-y := omap_drv.o \
+       omap_irq.o \
        omap_debugfs.o \
        omap_crtc.o \
        omap_plane.o \
index 938c7888ca319ae1d82e566b086ab1e9abf133a2..abeeb00aaa12ca758c4c3c085b170ffe709fc5af 100644 (file)
@@ -17,9 +17,6 @@ TODO
 . Revisit GEM sync object infrastructure.. TTM has some framework for this
   already.  Possibly this could be refactored out and made more common?
   There should be some way to do this with less wheel-reinvention.
-. Review DSS vs KMS mismatches.  The omap_dss_device is sort of part encoder,
-  part connector.  Which results in a bit of duct tape to fwd calls from
-  encoder to connector.  Possibly this could be done a bit better.
 . Solve PM sequencing on resume.  DMM/TILER must be reloaded before any
   access is made from any component in the system.  Which means on suspend
   CRTC's should be disabled, and on resume the LUT should be reprogrammed
index 91edb3f9697292961883ca5876f4ab520b27ed6a..4cc9ee733c5fb4a80c656ad978ca6a349e07b8dc 100644 (file)
 struct omap_connector {
        struct drm_connector base;
        struct omap_dss_device *dssdev;
+       struct drm_encoder *encoder;
 };
 
-static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
+void copy_timings_omap_to_drm(struct drm_display_mode *mode,
                struct omap_video_timings *timings)
 {
        mode->clock = timings->pixel_clock;
@@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
                mode->flags |= DRM_MODE_FLAG_NVSYNC;
 }
 
-static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
+void copy_timings_drm_to_omap(struct omap_video_timings *timings,
                struct drm_display_mode *mode)
 {
        timings->pixel_clock = mode->clock;
@@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
        timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 }
 
-static void omap_connector_dpms(struct drm_connector *connector, int mode)
-{
-       struct omap_connector *omap_connector = to_omap_connector(connector);
-       struct omap_dss_device *dssdev = omap_connector->dssdev;
-       int old_dpms;
-
-       DBG("%s: %d", dssdev->name, mode);
-
-       old_dpms = connector->dpms;
-
-       /* from off to on, do from crtc to connector */
-       if (mode < old_dpms)
-               drm_helper_connector_dpms(connector, mode);
-
-       if (mode == DRM_MODE_DPMS_ON) {
-               /* store resume info for suspended displays */
-               switch (dssdev->state) {
-               case OMAP_DSS_DISPLAY_SUSPENDED:
-                       dssdev->activate_after_resume = true;
-                       break;
-               case OMAP_DSS_DISPLAY_DISABLED: {
-                       int ret = dssdev->driver->enable(dssdev);
-                       if (ret) {
-                               DBG("%s: failed to enable: %d",
-                                               dssdev->name, ret);
-                               dssdev->driver->disable(dssdev);
-                       }
-                       break;
-               }
-               default:
-                       break;
-               }
-       } else {
-               /* TODO */
-       }
-
-       /* from on to off, do from connector to crtc */
-       if (mode > old_dpms)
-               drm_helper_connector_dpms(connector, mode);
-}
-
-enum drm_connector_status omap_connector_detect(
+static enum drm_connector_status omap_connector_detect(
                struct drm_connector *connector, bool force)
 {
        struct omap_connector *omap_connector = to_omap_connector(connector);
@@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
        struct omap_connector *omap_connector = to_omap_connector(connector);
        struct omap_dss_device *dssdev = omap_connector->dssdev;
 
-       dssdev->driver->disable(dssdev);
-
        DBG("%s", omap_connector->dssdev->name);
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
@@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
 struct drm_encoder *omap_connector_attached_encoder(
                struct drm_connector *connector)
 {
-       int i;
        struct omap_connector *omap_connector = to_omap_connector(connector);
-
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               struct drm_mode_object *obj;
-
-               if (connector->encoder_ids[i] == 0)
-                       break;
-
-               obj = drm_mode_object_find(connector->dev,
-                               connector->encoder_ids[i],
-                               DRM_MODE_OBJECT_ENCODER);
-
-               if (obj) {
-                       struct drm_encoder *encoder = obj_to_encoder(obj);
-                       struct omap_overlay_manager *mgr =
-                                       omap_encoder_get_manager(encoder);
-                       DBG("%s: found %s", omap_connector->dssdev->name,
-                                       mgr->name);
-                       return encoder;
-               }
-       }
-
-       DBG("%s: no encoder", omap_connector->dssdev->name);
-
-       return NULL;
+       return omap_connector->encoder;
 }
 
 static const struct drm_connector_funcs omap_connector_funcs = {
-       .dpms = omap_connector_dpms,
+       .dpms = drm_helper_connector_dpms,
        .detect = omap_connector_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = omap_connector_destroy,
@@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
        .best_encoder = omap_connector_attached_encoder,
 };
 
-/* called from encoder when mode is set, to propagate settings to the dssdev */
-void omap_connector_mode_set(struct drm_connector *connector,
-               struct drm_display_mode *mode)
-{
-       struct drm_device *dev = connector->dev;
-       struct omap_connector *omap_connector = to_omap_connector(connector);
-       struct omap_dss_device *dssdev = omap_connector->dssdev;
-       struct omap_dss_driver *dssdrv = dssdev->driver;
-       struct omap_video_timings timings = {0};
-
-       copy_timings_drm_to_omap(&timings, mode);
-
-       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       omap_connector->dssdev->name,
-                       mode->base.id, mode->name, mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal, mode->type, mode->flags);
-
-       if (dssdrv->check_timings(dssdev, &timings)) {
-               dev_err(dev->dev, "could not set timings\n");
-               return;
-       }
-
-       dssdrv->set_timings(dssdev, &timings);
-}
-
 /* flush an area of the framebuffer (in case of manual update display that
  * is not automatically flushed)
  */
@@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector,
 
 /* initialize connector */
 struct drm_connector *omap_connector_init(struct drm_device *dev,
-               int connector_type, struct omap_dss_device *dssdev)
+               int connector_type, struct omap_dss_device *dssdev,
+               struct drm_encoder *encoder)
 {
        struct drm_connector *connector = NULL;
        struct omap_connector *omap_connector;
@@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
        }
 
        omap_connector->dssdev = dssdev;
+       omap_connector->encoder = encoder;
+
        connector = &omap_connector->base;
 
        drm_connector_init(dev, connector, &omap_connector_funcs,
index d87bd84257bd7542c6175964e3f5510822958a51..5c6ed6040eff572a384659561e1fdbaf427c883c 100644 (file)
 struct omap_crtc {
        struct drm_crtc base;
        struct drm_plane *plane;
+
        const char *name;
-       int id;
+       int pipe;
+       enum omap_channel channel;
+       struct omap_overlay_manager_info info;
+
+       /*
+        * Temporary: eventually this will go away, but it is needed
+        * for now to keep the output's happy.  (They only need
+        * mgr->id.)  Eventually this will be replaced w/ something
+        * more common-panel-framework-y
+        */
+       struct omap_overlay_manager mgr;
+
+       struct omap_video_timings timings;
+       bool enabled;
+       bool full_update;
+
+       struct omap_drm_apply apply;
+
+       struct omap_drm_irq apply_irq;
+       struct omap_drm_irq error_irq;
+
+       /* list of in-progress apply's: */
+       struct list_head pending_applies;
+
+       /* list of queued apply's: */
+       struct list_head queued_applies;
+
+       /* for handling queued and in-progress applies: */
+       struct work_struct apply_work;
 
        /* if there is a pending flip, these will be non-null: */
        struct drm_pending_vblank_event *event;
        struct drm_framebuffer *old_fb;
+
+       /* for handling page flips without caring about what
+        * the callback is called from.  Possibly we should just
+        * make omap_gem always call the cb from the worker so
+        * we don't have to care about this..
+        *
+        * XXX maybe fold into apply_work??
+        */
+       struct work_struct page_flip_work;
+};
+
+/*
+ * Manager-ops, callbacks from output when they need to configure
+ * the upstream part of the video pipe.
+ *
+ * Most of these we can ignore until we add support for command-mode
+ * panels.. for video-mode the crtc-helpers already do an adequate
+ * job of sequencing the setup of the video pipe in the proper order
+ */
+
+/* we can probably ignore these until we support command-mode panels: */
+static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
+{
+}
+
+static int omap_crtc_enable(struct omap_overlay_manager *mgr)
+{
+       return 0;
+}
+
+static void omap_crtc_disable(struct omap_overlay_manager *mgr)
+{
+}
+
+static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
+               const struct omap_video_timings *timings)
+{
+       struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
+       DBG("%s", omap_crtc->name);
+       omap_crtc->timings = *timings;
+       omap_crtc->full_update = true;
+}
+
+static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr,
+               const struct dss_lcd_mgr_config *config)
+{
+       struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
+       DBG("%s", omap_crtc->name);
+       dispc_mgr_set_lcd_config(omap_crtc->channel, config);
+}
+
+static int omap_crtc_register_framedone_handler(
+               struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+       return 0;
+}
+
+static void omap_crtc_unregister_framedone_handler(
+               struct omap_overlay_manager *mgr,
+               void (*handler)(void *), void *data)
+{
+}
+
+static const struct dss_mgr_ops mgr_ops = {
+               .start_update = omap_crtc_start_update,
+               .enable = omap_crtc_enable,
+               .disable = omap_crtc_disable,
+               .set_timings = omap_crtc_set_timings,
+               .set_lcd_config = omap_crtc_set_lcd_config,
+               .register_framedone_handler = omap_crtc_register_framedone_handler,
+               .unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
 };
 
+/*
+ * CRTC funcs:
+ */
+
 static void omap_crtc_destroy(struct drm_crtc *crtc)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+       DBG("%s", omap_crtc->name);
+
+       WARN_ON(omap_crtc->apply_irq.registered);
+       omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+
        omap_crtc->plane->funcs->destroy(omap_crtc->plane);
        drm_crtc_cleanup(crtc);
+
        kfree(omap_crtc);
 }
 
@@ -48,14 +160,25 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct omap_drm_private *priv = crtc->dev->dev_private;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
        int i;
 
-       WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
+       DBG("%s: %d", omap_crtc->name, mode);
+
+       if (enabled != omap_crtc->enabled) {
+               omap_crtc->enabled = enabled;
+               omap_crtc->full_update = true;
+               omap_crtc_apply(crtc, &omap_crtc->apply);
 
-       for (i = 0; i < priv->num_planes; i++) {
-               struct drm_plane *plane = priv->planes[i];
-               if (plane->crtc == crtc)
-                       WARN_ON(omap_plane_dpms(plane, mode));
+               /* also enable our private plane: */
+               WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
+
+               /* and any attached overlay planes: */
+               for (i = 0; i < priv->num_planes; i++) {
+                       struct drm_plane *plane = priv->planes[i];
+                       if (plane->crtc == crtc)
+                               WARN_ON(omap_plane_dpms(plane, mode));
+               }
        }
 }
 
@@ -73,12 +196,26 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc,
                struct drm_framebuffer *old_fb)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct drm_plane *plane = omap_crtc->plane;
 
-       return omap_plane_mode_set(plane, crtc, crtc->fb,
+       mode = adjusted_mode;
+
+       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       omap_crtc->name, mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       copy_timings_drm_to_omap(&omap_crtc->timings, mode);
+       omap_crtc->full_update = true;
+
+       return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
-                       mode->hdisplay << 16, mode->vdisplay << 16);
+                       mode->hdisplay << 16, mode->vdisplay << 16,
+                       NULL, NULL);
 }
 
 static void omap_crtc_prepare(struct drm_crtc *crtc)
@@ -102,10 +239,11 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_plane *plane = omap_crtc->plane;
        struct drm_display_mode *mode = &crtc->mode;
 
-       return plane->funcs->update_plane(plane, crtc, crtc->fb,
+       return omap_plane_mode_set(plane, crtc, crtc->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
-                       mode->hdisplay << 16, mode->vdisplay << 16);
+                       mode->hdisplay << 16, mode->vdisplay << 16,
+                       NULL, NULL);
 }
 
 static void omap_crtc_load_lut(struct drm_crtc *crtc)
@@ -114,63 +252,54 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc)
 
 static void vblank_cb(void *arg)
 {
-       static uint32_t sequence;
        struct drm_crtc *crtc = arg;
        struct drm_device *dev = crtc->dev;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct drm_pending_vblank_event *event = omap_crtc->event;
        unsigned long flags;
-       struct timeval now;
 
-       WARN_ON(!event);
+       spin_lock_irqsave(&dev->event_lock, flags);
+
+       /* wakeup userspace */
+       if (omap_crtc->event)
+               drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event);
 
        omap_crtc->event = NULL;
+       omap_crtc->old_fb = NULL;
 
-       /* wakeup userspace */
-       if (event) {
-               do_gettimeofday(&now);
-
-               spin_lock_irqsave(&dev->event_lock, flags);
-               /* TODO: we can't yet use the vblank time accounting,
-                * because omapdss lower layer is the one that knows
-                * the irq # and registers the handler, which more or
-                * less defeats how drm_irq works.. for now just fake
-                * the sequence number and use gettimeofday..
-                *
-               event->event.sequence = drm_vblank_count_and_time(
-                               dev, omap_crtc->id, &now);
-                */
-               event->event.sequence = sequence++;
-               event->event.tv_sec = now.tv_sec;
-               event->event.tv_usec = now.tv_usec;
-               list_add_tail(&event->base.link,
-                               &event->base.file_priv->event_list);
-               wake_up_interruptible(&event->base.file_priv->event_wait);
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void page_flip_cb(void *arg)
+static void page_flip_worker(struct work_struct *work)
 {
-       struct drm_crtc *crtc = arg;
-       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct drm_framebuffer *old_fb = omap_crtc->old_fb;
+       struct omap_crtc *omap_crtc =
+                       container_of(work, struct omap_crtc, page_flip_work);
+       struct drm_crtc *crtc = &omap_crtc->base;
+       struct drm_device *dev = crtc->dev;
+       struct drm_display_mode *mode = &crtc->mode;
        struct drm_gem_object *bo;
 
-       omap_crtc->old_fb = NULL;
-
-       omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
-
-       /* really we'd like to setup the callback atomically w/ setting the
-        * new scanout buffer to avoid getting stuck waiting an extra vblank
-        * cycle.. for now go for correctness and later figure out speed..
-        */
-       omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc);
+       mutex_lock(&dev->mode_config.mutex);
+       omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       crtc->x << 16, crtc->y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16,
+                       vblank_cb, crtc);
+       mutex_unlock(&dev->mode_config.mutex);
 
        bo = omap_framebuffer_bo(crtc->fb, 0);
        drm_gem_object_unreference_unlocked(bo);
 }
 
+static void page_flip_cb(void *arg)
+{
+       struct drm_crtc *crtc = arg;
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       struct omap_drm_private *priv = crtc->dev->dev_private;
+
+       /* avoid assumptions about what ctxt we are called from: */
+       queue_work(priv->wq, &omap_crtc->page_flip_work);
+}
+
 static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
                 struct drm_framebuffer *fb,
                 struct drm_pending_vblank_event *event)
@@ -179,14 +308,14 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
        struct drm_gem_object *bo;
 
-       DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id);
+       DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1,
+                       fb->base.id, event);
 
-       if (omap_crtc->event) {
+       if (omap_crtc->old_fb) {
                dev_err(dev->dev, "already a pending flip\n");
                return -EINVAL;
        }
 
-       omap_crtc->old_fb = crtc->fb;
        omap_crtc->event = event;
        crtc->fb = fb;
 
@@ -234,14 +363,244 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
        .load_lut = omap_crtc_load_lut,
 };
 
+const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
+{
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       return &omap_crtc->timings;
+}
+
+enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
+{
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       return omap_crtc->channel;
+}
+
+static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+       struct omap_crtc *omap_crtc =
+                       container_of(irq, struct omap_crtc, error_irq);
+       struct drm_crtc *crtc = &omap_crtc->base;
+       DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
+       /* avoid getting in a flood, unregister the irq until next vblank */
+       omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+}
+
+static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+       struct omap_crtc *omap_crtc =
+                       container_of(irq, struct omap_crtc, apply_irq);
+       struct drm_crtc *crtc = &omap_crtc->base;
+
+       if (!omap_crtc->error_irq.registered)
+               omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+
+       if (!dispc_mgr_go_busy(omap_crtc->channel)) {
+               struct omap_drm_private *priv =
+                               crtc->dev->dev_private;
+               DBG("%s: apply done", omap_crtc->name);
+               omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
+               queue_work(priv->wq, &omap_crtc->apply_work);
+       }
+}
+
+static void apply_worker(struct work_struct *work)
+{
+       struct omap_crtc *omap_crtc =
+                       container_of(work, struct omap_crtc, apply_work);
+       struct drm_crtc *crtc = &omap_crtc->base;
+       struct drm_device *dev = crtc->dev;
+       struct omap_drm_apply *apply, *n;
+       bool need_apply;
+
+       /*
+        * Synchronize everything on mode_config.mutex, to keep
+        * the callbacks and list modification all serialized
+        * with respect to modesetting ioctls from userspace.
+        */
+       mutex_lock(&dev->mode_config.mutex);
+       dispc_runtime_get();
+
+       /*
+        * If we are still pending a previous update, wait.. when the
+        * pending update completes, we get kicked again.
+        */
+       if (omap_crtc->apply_irq.registered)
+               goto out;
+
+       /* finish up previous apply's: */
+       list_for_each_entry_safe(apply, n,
+                       &omap_crtc->pending_applies, pending_node) {
+               apply->post_apply(apply);
+               list_del(&apply->pending_node);
+       }
+
+       need_apply = !list_empty(&omap_crtc->queued_applies);
+
+       /* then handle the next round of of queued apply's: */
+       list_for_each_entry_safe(apply, n,
+                       &omap_crtc->queued_applies, queued_node) {
+               apply->pre_apply(apply);
+               list_del(&apply->queued_node);
+               apply->queued = false;
+               list_add_tail(&apply->pending_node,
+                               &omap_crtc->pending_applies);
+       }
+
+       if (need_apply) {
+               enum omap_channel channel = omap_crtc->channel;
+
+               DBG("%s: GO", omap_crtc->name);
+
+               if (dispc_mgr_is_enabled(channel)) {
+                       omap_irq_register(dev, &omap_crtc->apply_irq);
+                       dispc_mgr_go(channel);
+               } else {
+                       struct omap_drm_private *priv = dev->dev_private;
+                       queue_work(priv->wq, &omap_crtc->apply_work);
+               }
+       }
+
+out:
+       dispc_runtime_put();
+       mutex_unlock(&dev->mode_config.mutex);
+}
+
+int omap_crtc_apply(struct drm_crtc *crtc,
+               struct omap_drm_apply *apply)
+{
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+
+       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
+       /* no need to queue it again if it is already queued: */
+       if (apply->queued)
+               return 0;
+
+       apply->queued = true;
+       list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
+
+       /*
+        * If there are no currently pending updates, then go ahead and
+        * kick the worker immediately, otherwise it will run again when
+        * the current update finishes.
+        */
+       if (list_empty(&omap_crtc->pending_applies)) {
+               struct omap_drm_private *priv = crtc->dev->dev_private;
+               queue_work(priv->wq, &omap_crtc->apply_work);
+       }
+
+       return 0;
+}
+
+/* called only from apply */
+static void set_enabled(struct drm_crtc *crtc, bool enable)
+{
+       struct drm_device *dev = crtc->dev;
+       struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+       enum omap_channel channel = omap_crtc->channel;
+       struct omap_irq_wait *wait = NULL;
+
+       if (dispc_mgr_is_enabled(channel) == enable)
+               return;
+
+       /* ignore sync-lost irqs during enable/disable */
+       omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+
+       if (dispc_mgr_get_framedone_irq(channel)) {
+               if (!enable) {
+                       wait = omap_irq_wait_init(dev,
+                                       dispc_mgr_get_framedone_irq(channel), 1);
+               }
+       } else {
+               /*
+                * When we disable digit output, we need to wait until fields
+                * are done.  Otherwise the DSS is still working, and turning
+                * off the clocks prevents DSS from going to OFF mode. And when
+                * enabling, we need to wait for the extra sync losts
+                */
+               wait = omap_irq_wait_init(dev,
+                               dispc_mgr_get_vsync_irq(channel), 2);
+       }
+
+       dispc_mgr_enable(channel, enable);
+
+       if (wait) {
+               int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
+               if (ret) {
+                       dev_err(dev->dev, "%s: timeout waiting for %s\n",
+                                       omap_crtc->name, enable ? "enable" : "disable");
+               }
+       }
+
+       omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+}
+
+static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
+{
+       struct omap_crtc *omap_crtc =
+                       container_of(apply, struct omap_crtc, apply);
+       struct drm_crtc *crtc = &omap_crtc->base;
+       struct drm_encoder *encoder = NULL;
+
+       DBG("%s: enabled=%d, full=%d", omap_crtc->name,
+                       omap_crtc->enabled, omap_crtc->full_update);
+
+       if (omap_crtc->full_update) {
+               struct omap_drm_private *priv = crtc->dev->dev_private;
+               int i;
+               for (i = 0; i < priv->num_encoders; i++) {
+                       if (priv->encoders[i]->crtc == crtc) {
+                               encoder = priv->encoders[i];
+                               break;
+                       }
+               }
+       }
+
+       if (!omap_crtc->enabled) {
+               set_enabled(&omap_crtc->base, false);
+               if (encoder)
+                       omap_encoder_set_enabled(encoder, false);
+       } else {
+               if (encoder) {
+                       omap_encoder_set_enabled(encoder, false);
+                       omap_encoder_update(encoder, &omap_crtc->mgr,
+                                       &omap_crtc->timings);
+                       omap_encoder_set_enabled(encoder, true);
+                       omap_crtc->full_update = false;
+               }
+
+               dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
+               dispc_mgr_set_timings(omap_crtc->channel,
+                               &omap_crtc->timings);
+               set_enabled(&omap_crtc->base, true);
+       }
+
+       omap_crtc->full_update = false;
+}
+
+static void omap_crtc_post_apply(struct omap_drm_apply *apply)
+{
+       /* nothing needed for post-apply */
+}
+
+static const char *channel_names[] = {
+               [OMAP_DSS_CHANNEL_LCD] = "lcd",
+               [OMAP_DSS_CHANNEL_DIGIT] = "tv",
+               [OMAP_DSS_CHANNEL_LCD2] = "lcd2",
+};
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
-               struct omap_overlay *ovl, int id)
+               struct drm_plane *plane, enum omap_channel channel, int id)
 {
        struct drm_crtc *crtc = NULL;
-       struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
+       struct omap_crtc *omap_crtc;
+       struct omap_overlay_manager_info *info;
+
+       DBG("%s", channel_names[channel]);
 
-       DBG("%s", ovl->name);
+       omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
 
        if (!omap_crtc) {
                dev_err(dev->dev, "could not allocate CRTC\n");
@@ -250,10 +609,40 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 
        crtc = &omap_crtc->base;
 
-       omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true);
+       INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker);
+       INIT_WORK(&omap_crtc->apply_work, apply_worker);
+
+       INIT_LIST_HEAD(&omap_crtc->pending_applies);
+       INIT_LIST_HEAD(&omap_crtc->queued_applies);
+
+       omap_crtc->apply.pre_apply  = omap_crtc_pre_apply;
+       omap_crtc->apply.post_apply = omap_crtc_post_apply;
+
+       omap_crtc->apply_irq.irqmask = pipe2vbl(id);
+       omap_crtc->apply_irq.irq = omap_crtc_apply_irq;
+
+       omap_crtc->error_irq.irqmask =
+                       dispc_mgr_get_sync_lost_irq(channel);
+       omap_crtc->error_irq.irq = omap_crtc_error_irq;
+       omap_irq_register(dev, &omap_crtc->error_irq);
+
+       omap_crtc->channel = channel;
+       omap_crtc->plane = plane;
        omap_crtc->plane->crtc = crtc;
-       omap_crtc->name = ovl->name;
-       omap_crtc->id = id;
+       omap_crtc->name = channel_names[channel];
+       omap_crtc->pipe = id;
+
+       /* temporary: */
+       omap_crtc->mgr.id = channel;
+
+       dss_install_mgr_ops(&mgr_ops);
+
+       /* TODO: fix hard-coded setup.. add properties! */
+       info = &omap_crtc->info;
+       info->default_color = 0x00000000;
+       info->trans_key = 0x00000000;
+       info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+       info->trans_enabled = false;
 
        drm_crtc_init(dev, crtc, &omap_crtc_funcs);
        drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
index 84943e5ba1d6563f49877ada93e022a1d67b5385..ae5ecc2efbc758268d692d732482d1f49f13c352 100644 (file)
@@ -74,320 +74,99 @@ static int get_connector_type(struct omap_dss_device *dssdev)
        }
 }
 
-#if 0 /* enable when dss2 supports hotplug */
-static int omap_drm_notifier(struct notifier_block *nb,
-               unsigned long evt, void *arg)
-{
-       switch (evt) {
-       case OMAP_DSS_SIZE_CHANGE:
-       case OMAP_DSS_HOTPLUG_CONNECT:
-       case OMAP_DSS_HOTPLUG_DISCONNECT: {
-               struct drm_device *dev = drm_device;
-               DBG("hotplug event: evt=%d, dev=%p", evt, dev);
-               if (dev)
-                       drm_sysfs_hotplug_event(dev);
-
-               return NOTIFY_OK;
-       }
-       default:  /* don't care about other events for now */
-               return NOTIFY_DONE;
-       }
-}
-#endif
-
-static void dump_video_chains(void)
-{
-       int i;
-
-       DBG("dumping video chains: ");
-       for (i = 0; i < omap_dss_get_num_overlays(); i++) {
-               struct omap_overlay *ovl = omap_dss_get_overlay(i);
-               struct omap_overlay_manager *mgr = ovl->manager;
-               struct omap_dss_device *dssdev = mgr ?
-                                       mgr->get_device(mgr) : NULL;
-               if (dssdev) {
-                       DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,
-                                               dssdev->name);
-               } else if (mgr) {
-                       DBG("%d: %s -> %s", i, ovl->name, mgr->name);
-               } else {
-                       DBG("%d: %s", i, ovl->name);
-               }
-       }
-}
-
-/* create encoders for each manager */
-static int create_encoder(struct drm_device *dev,
-               struct omap_overlay_manager *mgr)
-{
-       struct omap_drm_private *priv = dev->dev_private;
-       struct drm_encoder *encoder = omap_encoder_init(dev, mgr);
-
-       if (!encoder) {
-               dev_err(dev->dev, "could not create encoder: %s\n",
-                               mgr->name);
-               return -ENOMEM;
-       }
-
-       BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
-
-       priv->encoders[priv->num_encoders++] = encoder;
-
-       return 0;
-}
-
-/* create connectors for each display device */
-static int create_connector(struct drm_device *dev,
-               struct omap_dss_device *dssdev)
+static int omap_modeset_init(struct drm_device *dev)
 {
        struct omap_drm_private *priv = dev->dev_private;
-       static struct notifier_block *notifier;
-       struct drm_connector *connector;
-       int j;
-
-       if (!dssdev->driver) {
-               dev_warn(dev->dev, "%s has no driver.. skipping it\n",
-                               dssdev->name);
-               return 0;
-       }
+       struct omap_dss_device *dssdev = NULL;
+       int num_ovls = dss_feat_get_num_ovls();
+       int id;
 
-       if (!(dssdev->driver->get_timings ||
-                               dssdev->driver->read_edid)) {
-               dev_warn(dev->dev, "%s driver does not support "
-                       "get_timings or read_edid.. skipping it!\n",
-                       dssdev->name);
-               return 0;
-       }
+       drm_mode_config_init(dev);
 
-       connector = omap_connector_init(dev,
-                       get_connector_type(dssdev), dssdev);
+       omap_drm_irq_install(dev);
 
-       if (!connector) {
-               dev_err(dev->dev, "could not create connector: %s\n",
-                               dssdev->name);
-               return -ENOMEM;
-       }
-
-       BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
+       /*
+        * Create private planes and CRTCs for the last NUM_CRTCs overlay
+        * plus manager:
+        */
+       for (id = 0; id < min(num_crtc, num_ovls); id++) {
+               struct drm_plane *plane;
+               struct drm_crtc *crtc;
 
-       priv->connectors[priv->num_connectors++] = connector;
+               plane = omap_plane_init(dev, id, true);
+               crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);
 
-#if 0 /* enable when dss2 supports hotplug */
-       notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
-       notifier->notifier_call = omap_drm_notifier;
-       omap_dss_add_notify(dssdev, notifier);
-#else
-       notifier = NULL;
-#endif
+               BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
+               priv->crtcs[id] = crtc;
+               priv->num_crtcs++;
 
-       for (j = 0; j < priv->num_encoders; j++) {
-               struct omap_overlay_manager *mgr =
-                       omap_encoder_get_manager(priv->encoders[j]);
-               if (mgr->get_device(mgr) == dssdev) {
-                       drm_mode_connector_attach_encoder(connector,
-                                       priv->encoders[j]);
-               }
+               priv->planes[id] = plane;
+               priv->num_planes++;
        }
 
-       return 0;
-}
-
-/* create up to max_overlays CRTCs mapping to overlays.. by default,
- * connect the overlays to different managers/encoders, giving priority
- * to encoders connected to connectors with a detected connection
- */
-static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
-               int *j, unsigned int connected_connectors)
-{
-       struct omap_drm_private *priv = dev->dev_private;
-       struct omap_overlay_manager *mgr = NULL;
-       struct drm_crtc *crtc;
-
-       /* find next best connector, ones with detected connection first
+       /*
+        * Create normal planes for the remaining overlays:
         */
-       while (*j < priv->num_connectors && !mgr) {
-               if (connected_connectors & (1 << *j)) {
-                       struct drm_encoder *encoder =
-                               omap_connector_attached_encoder(
-                                               priv->connectors[*j]);
-                       if (encoder)
-                               mgr = omap_encoder_get_manager(encoder);
+       for (; id < num_ovls; id++) {
+               struct drm_plane *plane = omap_plane_init(dev, id, false);
 
-               }
-               (*j)++;
+               BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
+               priv->planes[priv->num_planes++] = plane;
        }
 
-       /* if we couldn't find another connected connector, lets start
-        * looking at the unconnected connectors:
-        *
-        * note: it might not be immediately apparent, but thanks to
-        * the !mgr check in both this loop and the one above, the only
-        * way to enter this loop is with *j == priv->num_connectors,
-        * so idx can never go negative.
-        */
-       while (*j < 2 * priv->num_connectors && !mgr) {
-               int idx = *j - priv->num_connectors;
-               if (!(connected_connectors & (1 << idx))) {
-                       struct drm_encoder *encoder =
-                               omap_connector_attached_encoder(
-                                               priv->connectors[idx]);
-                       if (encoder)
-                               mgr = omap_encoder_get_manager(encoder);
+       for_each_dss_dev(dssdev) {
+               struct drm_connector *connector;
+               struct drm_encoder *encoder;
 
+               if (!dssdev->driver) {
+                       dev_warn(dev->dev, "%s has no driver.. skipping it\n",
+                                       dssdev->name);
+                       return 0;
                }
-               (*j)++;
-       }
-
-       crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
-
-       if (!crtc) {
-               dev_err(dev->dev, "could not create CRTC: %s\n",
-                               ovl->name);
-               return -ENOMEM;
-       }
 
-       BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
-
-       priv->crtcs[priv->num_crtcs++] = crtc;
-
-       return 0;
-}
-
-static int create_plane(struct drm_device *dev, struct omap_overlay *ovl,
-               unsigned int possible_crtcs)
-{
-       struct omap_drm_private *priv = dev->dev_private;
-       struct drm_plane *plane =
-                       omap_plane_init(dev, ovl, possible_crtcs, false);
-
-       if (!plane) {
-               dev_err(dev->dev, "could not create plane: %s\n",
-                               ovl->name);
-               return -ENOMEM;
-       }
-
-       BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
-
-       priv->planes[priv->num_planes++] = plane;
-
-       return 0;
-}
-
-static int match_dev_name(struct omap_dss_device *dssdev, void *data)
-{
-       return !strcmp(dssdev->name, data);
-}
-
-static unsigned int detect_connectors(struct drm_device *dev)
-{
-       struct omap_drm_private *priv = dev->dev_private;
-       unsigned int connected_connectors = 0;
-       int i;
-
-       for (i = 0; i < priv->num_connectors; i++) {
-               struct drm_connector *connector = priv->connectors[i];
-               if (omap_connector_detect(connector, true) ==
-                               connector_status_connected) {
-                       connected_connectors |= (1 << i);
+               if (!(dssdev->driver->get_timings ||
+                                       dssdev->driver->read_edid)) {
+                       dev_warn(dev->dev, "%s driver does not support "
+                               "get_timings or read_edid.. skipping it!\n",
+                               dssdev->name);
+                       return 0;
                }
-       }
-
-       return connected_connectors;
-}
 
-static int omap_modeset_init(struct drm_device *dev)
-{
-       const struct omap_drm_platform_data *pdata = dev->dev->platform_data;
-       struct omap_kms_platform_data *kms_pdata = NULL;
-       struct omap_drm_private *priv = dev->dev_private;
-       struct omap_dss_device *dssdev = NULL;
-       int i, j;
-       unsigned int connected_connectors = 0;
+               encoder = omap_encoder_init(dev, dssdev);
 
-       drm_mode_config_init(dev);
-
-       if (pdata && pdata->kms_pdata) {
-               kms_pdata = pdata->kms_pdata;
-
-               /* if platform data is provided by the board file, use it to
-                * control which overlays, managers, and devices we own.
-                */
-               for (i = 0; i < kms_pdata->mgr_cnt; i++) {
-                       struct omap_overlay_manager *mgr =
-                               omap_dss_get_overlay_manager(
-                                               kms_pdata->mgr_ids[i]);
-                       create_encoder(dev, mgr);
-               }
-
-               for (i = 0; i < kms_pdata->dev_cnt; i++) {
-                       struct omap_dss_device *dssdev =
-                               omap_dss_find_device(
-                                       (void *)kms_pdata->dev_names[i],
-                                       match_dev_name);
-                       if (!dssdev) {
-                               dev_warn(dev->dev, "no such dssdev: %s\n",
-                                               kms_pdata->dev_names[i]);
-                               continue;
-                       }
-                       create_connector(dev, dssdev);
+               if (!encoder) {
+                       dev_err(dev->dev, "could not create encoder: %s\n",
+                                       dssdev->name);
+                       return -ENOMEM;
                }
 
-               connected_connectors = detect_connectors(dev);
+               connector = omap_connector_init(dev,
+                               get_connector_type(dssdev), dssdev, encoder);
 
-               j = 0;
-               for (i = 0; i < kms_pdata->ovl_cnt; i++) {
-                       struct omap_overlay *ovl =
-                               omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
-                       create_crtc(dev, ovl, &j, connected_connectors);
+               if (!connector) {
+                       dev_err(dev->dev, "could not create connector: %s\n",
+                                       dssdev->name);
+                       return -ENOMEM;
                }
 
-               for (i = 0; i < kms_pdata->pln_cnt; i++) {
-                       struct omap_overlay *ovl =
-                               omap_dss_get_overlay(kms_pdata->pln_ids[i]);
-                       create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
-               }
-       } else {
-               /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
-                * to make educated guesses about everything else
-                */
-               int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);
+               BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
+               BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
 
-               for (i = 0; i < omap_dss_get_num_overlay_managers(); i++)
-                       create_encoder(dev, omap_dss_get_overlay_manager(i));
-
-               for_each_dss_dev(dssdev) {
-                       create_connector(dev, dssdev);
-               }
+               priv->encoders[priv->num_encoders++] = encoder;
+               priv->connectors[priv->num_connectors++] = connector;
 
-               connected_connectors = detect_connectors(dev);
+               drm_mode_connector_attach_encoder(connector, encoder);
 
-               j = 0;
-               for (i = 0; i < max_overlays; i++) {
-                       create_crtc(dev, omap_dss_get_overlay(i),
-                                       &j, connected_connectors);
-               }
-
-               /* use any remaining overlays as drm planes */
-               for (; i < omap_dss_get_num_overlays(); i++) {
-                       struct omap_overlay *ovl = omap_dss_get_overlay(i);
-                       create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
+               /* figure out which crtc's we can connect the encoder to: */
+               encoder->possible_crtcs = 0;
+               for (id = 0; id < priv->num_crtcs; id++) {
+                       enum omap_dss_output_id supported_outputs =
+                                       dss_feat_get_supported_outputs(pipe2chan(id));
+                       if (supported_outputs & dssdev->output->id)
+                               encoder->possible_crtcs |= (1 << id);
                }
        }
 
-       /* for now keep the mapping of CRTCs and encoders static.. */
-       for (i = 0; i < priv->num_encoders; i++) {
-               struct drm_encoder *encoder = priv->encoders[i];
-               struct omap_overlay_manager *mgr =
-                               omap_encoder_get_manager(encoder);
-
-               encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
-
-               DBG("%s: possible_crtcs=%08x", mgr->name,
-                                       encoder->possible_crtcs);
-       }
-
-       dump_video_chains();
-
        dev->mode_config.min_width = 32;
        dev->mode_config.min_height = 32;
 
@@ -450,7 +229,7 @@ static int ioctl_gem_new(struct drm_device *dev, void *data,
                struct drm_file *file_priv)
 {
        struct drm_omap_gem_new *args = data;
-       DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
+       VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
                        args->size.bytes, args->flags);
        return omap_gem_new_handle(dev, file_priv, args->size,
                        args->flags, &args->handle);
@@ -510,7 +289,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
        struct drm_gem_object *obj;
        int ret = 0;
 
-       DBG("%p:%p: handle=%d", dev, file_priv, args->handle);
+       VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (!obj)
@@ -565,14 +344,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = priv;
 
-       ret = omapdss_compat_init();
-       if (ret) {
-               dev_err(dev->dev, "coult not init omapdss\n");
-               dev->dev_private = NULL;
-               kfree(priv);
-               return ret;
-       }
-
        priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 
        INIT_LIST_HEAD(&priv->obj_list);
@@ -584,10 +355,13 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
                dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
                dev->dev_private = NULL;
                kfree(priv);
-               omapdss_compat_uninit();
                return ret;
        }
 
+       ret = drm_vblank_init(dev, priv->num_crtcs);
+       if (ret)
+               dev_warn(dev->dev, "could not init vblank\n");
+
        priv->fbdev = omap_fbdev_init(dev);
        if (!priv->fbdev) {
                dev_warn(dev->dev, "omap_fbdev_init failed\n");
@@ -596,10 +370,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
        drm_kms_helper_poll_init(dev);
 
-       ret = drm_vblank_init(dev, priv->num_crtcs);
-       if (ret)
-               dev_warn(dev->dev, "could not init vblank\n");
-
        return 0;
 }
 
@@ -609,8 +379,9 @@ static int dev_unload(struct drm_device *dev)
 
        DBG("unload: dev=%p", dev);
 
-       drm_vblank_cleanup(dev);
        drm_kms_helper_poll_fini(dev);
+       drm_vblank_cleanup(dev);
+       omap_drm_irq_uninstall(dev);
 
        omap_fbdev_free(dev);
        omap_modeset_free(dev);
@@ -619,8 +390,6 @@ static int dev_unload(struct drm_device *dev)
        flush_workqueue(priv->wq);
        destroy_workqueue(priv->wq);
 
-       omapdss_compat_uninit();
-
        kfree(dev->dev_private);
        dev->dev_private = NULL;
 
@@ -680,7 +449,9 @@ static void dev_lastclose(struct drm_device *dev)
                }
        }
 
+       mutex_lock(&dev->mode_config.mutex);
        ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+       mutex_unlock(&dev->mode_config.mutex);
        if (ret)
                DBG("failed to restore crtc mode");
 }
@@ -695,60 +466,6 @@ static void dev_postclose(struct drm_device *dev, struct drm_file *file)
        DBG("postclose: dev=%p, file=%p", dev, file);
 }
 
-/**
- * enable_vblank - enable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Enable vblank interrupts for @crtc.  If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- *
- * RETURNS
- * Zero on success, appropriate errno if the given @crtc's vblank
- * interrupt cannot be enabled.
- */
-static int dev_enable_vblank(struct drm_device *dev, int crtc)
-{
-       DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc);
-       return 0;
-}
-
-/**
- * disable_vblank - disable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Disable vblank interrupts for @crtc.  If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- */
-static void dev_disable_vblank(struct drm_device *dev, int crtc)
-{
-       DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc);
-}
-
-static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS)
-{
-       return IRQ_HANDLED;
-}
-
-static void dev_irq_preinstall(struct drm_device *dev)
-{
-       DBG("irq_preinstall: dev=%p", dev);
-}
-
-static int dev_irq_postinstall(struct drm_device *dev)
-{
-       DBG("irq_postinstall: dev=%p", dev);
-       return 0;
-}
-
-static void dev_irq_uninstall(struct drm_device *dev)
-{
-       DBG("irq_uninstall: dev=%p", dev);
-}
-
 static const struct vm_operations_struct omap_gem_vm_ops = {
        .fault = omap_gem_fault,
        .open = drm_gem_vm_open,
@@ -778,12 +495,12 @@ static struct drm_driver omap_drm_driver = {
                .preclose = dev_preclose,
                .postclose = dev_postclose,
                .get_vblank_counter = drm_vblank_count,
-               .enable_vblank = dev_enable_vblank,
-               .disable_vblank = dev_disable_vblank,
-               .irq_preinstall = dev_irq_preinstall,
-               .irq_postinstall = dev_irq_postinstall,
-               .irq_uninstall = dev_irq_uninstall,
-               .irq_handler = dev_irq_handler,
+               .enable_vblank = omap_irq_enable_vblank,
+               .disable_vblank = omap_irq_disable_vblank,
+               .irq_preinstall = omap_irq_preinstall,
+               .irq_postinstall = omap_irq_postinstall,
+               .irq_uninstall = omap_irq_uninstall,
+               .irq_handler = omap_irq_handler,
 #ifdef CONFIG_DEBUG_FS
                .debugfs_init = omap_debugfs_init,
                .debugfs_cleanup = omap_debugfs_cleanup,
index 1d4aea53b75da20e44be90b4a32e589a4a067785..cd1f22b0b124ddbf9eb1eff0efe5b77ddb7fd061 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/platform_data/omap_drm.h>
 #include "omap_drm.h"
 
+
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
 
  */
 #define MAX_MAPPERS 2
 
+/* parameters which describe (unrotated) coordinates of scanout within a fb: */
+struct omap_drm_window {
+       uint32_t rotation;
+       int32_t  crtc_x, crtc_y;                /* signed because can be offscreen */
+       uint32_t crtc_w, crtc_h;
+       uint32_t src_x, src_y;
+       uint32_t src_w, src_h;
+};
+
+/* Once GO bit is set, we can't make further updates to shadowed registers
+ * until the GO bit is cleared.  So various parts in the kms code that need
+ * to update shadowed registers queue up a pair of callbacks, pre_apply
+ * which is called before setting GO bit, and post_apply that is called
+ * after GO bit is cleared.  The crtc manages the queuing, and everyone
+ * else goes thru omap_crtc_apply() using these callbacks so that the
+ * code which has to deal w/ GO bit state is centralized.
+ */
+struct omap_drm_apply {
+       struct list_head pending_node, queued_node;
+       bool queued;
+       void (*pre_apply)(struct omap_drm_apply *apply);
+       void (*post_apply)(struct omap_drm_apply *apply);
+};
+
+/* For transiently registering for different DSS irqs that various parts
+ * of the KMS code need during setup/configuration.  We these are not
+ * necessarily the same as what drm_vblank_get/put() are requesting, and
+ * the hysteresis in drm_vblank_put() is not necessarily desirable for
+ * internal housekeeping related irq usage.
+ */
+struct omap_drm_irq {
+       struct list_head node;
+       uint32_t irqmask;
+       bool registered;
+       void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
+};
+
+/* For KMS code that needs to wait for a certain # of IRQs:
+ */
+struct omap_irq_wait;
+struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
+               uint32_t irqmask, int count);
+int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
+               unsigned long timeout);
+
 struct omap_drm_private {
        uint32_t omaprev;
 
@@ -58,6 +104,7 @@ struct omap_drm_private {
 
        struct workqueue_struct *wq;
 
+       /* list of GEM objects: */
        struct list_head obj_list;
 
        bool has_dmm;
@@ -65,6 +112,11 @@ struct omap_drm_private {
        /* properties: */
        struct drm_property *rotation_prop;
        struct drm_property *zorder_prop;
+
+       /* irq handling: */
+       struct list_head irq_list;    /* list of omap_drm_irq */
+       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+       struct omap_drm_irq error_handler;
 };
 
 /* this should probably be in drm-core to standardize amongst drivers */
@@ -75,15 +127,6 @@ struct omap_drm_private {
 #define DRM_REFLECT_X  4
 #define DRM_REFLECT_Y  5
 
-/* parameters which describe (unrotated) coordinates of scanout within a fb: */
-struct omap_drm_window {
-       uint32_t rotation;
-       int32_t  crtc_x, crtc_y;                /* signed because can be offscreen */
-       uint32_t crtc_w, crtc_h;
-       uint32_t src_x, src_y;
-       uint32_t src_w, src_h;
-};
-
 #ifdef CONFIG_DEBUG_FS
 int omap_debugfs_init(struct drm_minor *minor);
 void omap_debugfs_cleanup(struct drm_minor *minor);
@@ -92,23 +135,36 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
 void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 #endif
 
+int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
+void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
+irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
+void omap_irq_preinstall(struct drm_device *dev);
+int omap_irq_postinstall(struct drm_device *dev);
+void omap_irq_uninstall(struct drm_device *dev);
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
+int omap_drm_irq_uninstall(struct drm_device *dev);
+int omap_drm_irq_install(struct drm_device *dev);
+
 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
 void omap_fbdev_free(struct drm_device *dev);
 
+const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
+enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
+int omap_crtc_apply(struct drm_crtc *crtc,
+               struct omap_drm_apply *apply);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
-               struct omap_overlay *ovl, int id);
+               struct drm_plane *plane, enum omap_channel channel, int id);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-               struct omap_overlay *ovl, unsigned int possible_crtcs,
-               bool priv);
+               int plane_id, bool private_plane);
 int omap_plane_dpms(struct drm_plane *plane, int mode);
 int omap_plane_mode_set(struct drm_plane *plane,
                struct drm_crtc *crtc, struct drm_framebuffer *fb,
                int crtc_x, int crtc_y,
                unsigned int crtc_w, unsigned int crtc_h,
                uint32_t src_x, uint32_t src_y,
-               uint32_t src_w, uint32_t src_h);
-void omap_plane_on_endwin(struct drm_plane *plane,
+               uint32_t src_w, uint32_t src_h,
                void (*fxn)(void *), void *arg);
 void omap_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj);
@@ -116,21 +172,25 @@ int omap_plane_set_property(struct drm_plane *plane,
                struct drm_property *property, uint64_t val);
 
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
-               struct omap_overlay_manager *mgr);
-struct omap_overlay_manager *omap_encoder_get_manager(
+               struct omap_dss_device *dssdev);
+int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled);
+int omap_encoder_update(struct drm_encoder *encoder,
+               struct omap_overlay_manager *mgr,
+               struct omap_video_timings *timings);
+
+struct drm_connector *omap_connector_init(struct drm_device *dev,
+               int connector_type, struct omap_dss_device *dssdev,
                struct drm_encoder *encoder);
 struct drm_encoder *omap_connector_attached_encoder(
                struct drm_connector *connector);
-enum drm_connector_status omap_connector_detect(
-               struct drm_connector *connector, bool force);
-
-struct drm_connector *omap_connector_init(struct drm_device *dev,
-               int connector_type, struct omap_dss_device *dssdev);
-void omap_connector_mode_set(struct drm_connector *connector,
-               struct drm_display_mode *mode);
 void omap_connector_flush(struct drm_connector *connector,
                int x, int y, int w, int h);
 
+void copy_timings_omap_to_drm(struct drm_display_mode *mode,
+               struct omap_video_timings *timings);
+void copy_timings_drm_to_omap(struct omap_video_timings *timings,
+               struct drm_display_mode *mode);
+
 uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
                uint32_t max_formats, enum omap_color_mode supported_modes);
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
@@ -207,6 +267,40 @@ static inline int align_pitch(int pitch, int width, int bpp)
        return ALIGN(pitch, 8 * bytespp);
 }
 
+static inline enum omap_channel pipe2chan(int pipe)
+{
+       int num_mgrs = dss_feat_get_num_mgrs();
+
+       /*
+        * We usually don't want to create a CRTC for each manager,
+        * at least not until we have a way to expose private planes
+        * to userspace.  Otherwise there would not be enough video
+        * pipes left for drm planes.  The higher #'d managers tend
+        * to have more features so start in reverse order.
+        */
+       return num_mgrs - pipe - 1;
+}
+
+/* map crtc to vblank mask */
+static inline uint32_t pipe2vbl(int crtc)
+{
+       enum omap_channel channel = pipe2chan(crtc);
+       return dispc_mgr_get_vsync_irq(channel);
+}
+
+static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)
+               if (priv->crtcs[i] == crtc)
+                       return i;
+
+       BUG();  /* bogus CRTC ptr */
+       return -1;
+}
+
 /* should these be made into common util helpers?
  */
 
index 5341d5e3e3179e30b2bbe8540b12cc935843a2b7..e053160d2db38c9fd6d77bea4971e22635ef18ad 100644 (file)
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
+#include <linux/list.h>
+
+
 /*
  * encoder funcs
  */
 
 #define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
 
+/* The encoder and connector both map to same dssdev.. the encoder
+ * handles the 'active' parts, ie. anything the modifies the state
+ * of the hw, and the connector handles the 'read-only' parts, like
+ * detecting connection and reading edid.
+ */
 struct omap_encoder {
        struct drm_encoder base;
-       struct omap_overlay_manager *mgr;
+       struct omap_dss_device *dssdev;
 };
 
 static void omap_encoder_destroy(struct drm_encoder *encoder)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       DBG("%s", omap_encoder->mgr->name);
        drm_encoder_cleanup(encoder);
        kfree(omap_encoder);
 }
 
+static const struct drm_encoder_funcs omap_encoder_funcs = {
+       .destroy = omap_encoder_destroy,
+};
+
+/*
+ * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right
+ * order.. the easiest way to work around this for now is to make all
+ * the encoder-helper's no-op's and have the omap_crtc code take care
+ * of the sequencing and call us in the right points.
+ *
+ * Eventually to handle connecting CRTCs to different encoders properly,
+ * either the CRTC helpers need to change or we need to replace
+ * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for
+ * that.
+ */
+
 static void omap_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       DBG("%s: %d", omap_encoder->mgr->name, mode);
 }
 
 static bool omap_encoder_mode_fixup(struct drm_encoder *encoder,
                                  const struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
 {
-       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       DBG("%s", omap_encoder->mgr->name);
        return true;
 }
 
@@ -60,47 +79,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
 {
-       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct drm_device *dev = encoder->dev;
-       struct omap_drm_private *priv = dev->dev_private;
-       int i;
-
-       mode = adjusted_mode;
-
-       DBG("%s: set mode: %dx%d", omap_encoder->mgr->name,
-                       mode->hdisplay, mode->vdisplay);
-
-       for (i = 0; i < priv->num_connectors; i++) {
-               struct drm_connector *connector = priv->connectors[i];
-               if (connector->encoder == encoder)
-                       omap_connector_mode_set(connector, mode);
-
-       }
 }
 
 static void omap_encoder_prepare(struct drm_encoder *encoder)
 {
-       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct drm_encoder_helper_funcs *encoder_funcs =
-                               encoder->helper_private;
-       DBG("%s", omap_encoder->mgr->name);
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void omap_encoder_commit(struct drm_encoder *encoder)
 {
-       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct drm_encoder_helper_funcs *encoder_funcs =
-                               encoder->helper_private;
-       DBG("%s", omap_encoder->mgr->name);
-       omap_encoder->mgr->apply(omap_encoder->mgr);
-       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
 }
 
-static const struct drm_encoder_funcs omap_encoder_funcs = {
-       .destroy = omap_encoder_destroy,
-};
-
 static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
        .dpms = omap_encoder_dpms,
        .mode_fixup = omap_encoder_mode_fixup,
@@ -109,23 +97,54 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
        .commit = omap_encoder_commit,
 };
 
-struct omap_overlay_manager *omap_encoder_get_manager(
-               struct drm_encoder *encoder)
+/*
+ * Instead of relying on the helpers for modeset, the omap_crtc code
+ * calls these functions in the proper sequence.
+ */
+
+int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       return omap_encoder->mgr;
+       struct omap_dss_device *dssdev = omap_encoder->dssdev;
+       struct omap_dss_driver *dssdrv = dssdev->driver;
+
+       if (enabled) {
+               return dssdrv->enable(dssdev);
+       } else {
+               dssdrv->disable(dssdev);
+               return 0;
+       }
+}
+
+int omap_encoder_update(struct drm_encoder *encoder,
+               struct omap_overlay_manager *mgr,
+               struct omap_video_timings *timings)
+{
+       struct drm_device *dev = encoder->dev;
+       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+       struct omap_dss_device *dssdev = omap_encoder->dssdev;
+       struct omap_dss_driver *dssdrv = dssdev->driver;
+       int ret;
+
+       dssdev->output->manager = mgr;
+
+       ret = dssdrv->check_timings(dssdev, timings);
+       if (ret) {
+               dev_err(dev->dev, "could not set timings: %d\n", ret);
+               return ret;
+       }
+
+       dssdrv->set_timings(dssdev, timings);
+
+       return 0;
 }
 
 /* initialize encoder */
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
-               struct omap_overlay_manager *mgr)
+               struct omap_dss_device *dssdev)
 {
        struct drm_encoder *encoder = NULL;
        struct omap_encoder *omap_encoder;
-       struct omap_overlay_manager_info info;
-       int ret;
-
-       DBG("%s", mgr->name);
 
        omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
        if (!omap_encoder) {
@@ -133,33 +152,14 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev,
                goto fail;
        }
 
-       omap_encoder->mgr = mgr;
+       omap_encoder->dssdev = dssdev;
+
        encoder = &omap_encoder->base;
 
        drm_encoder_init(dev, encoder, &omap_encoder_funcs,
                         DRM_MODE_ENCODER_TMDS);
        drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
 
-       mgr->get_manager_info(mgr, &info);
-
-       /* TODO: fix hard-coded setup.. */
-       info.default_color = 0x00000000;
-       info.trans_key = 0x00000000;
-       info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
-       info.trans_enabled = false;
-
-       ret = mgr->set_manager_info(mgr, &info);
-       if (ret) {
-               dev_err(dev->dev, "could not set manager info\n");
-               goto fail;
-       }
-
-       ret = mgr->apply(mgr);
-       if (ret) {
-               dev_err(dev->dev, "could not apply\n");
-               goto fail;
-       }
-
        return encoder;
 
 fail:
index 9a302062b031d4ea70d8205523aea7694dc5e54f..b6c5b5c6c8c53dbd39e84baa91cd43e1b81ebfb7 100644 (file)
@@ -194,7 +194,7 @@ struct dma_buf_ops omap_dmabuf_ops = {
 struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
                struct drm_gem_object *obj, int flags)
 {
-       return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600);
+       return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
 }
 
 struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
@@ -207,7 +207,12 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
                obj = buffer->priv;
                /* is it from our device? */
                if (obj->dev == dev) {
+                       /*
+                        * Importing dmabuf exported from out own gem increases
+                        * refcount on gem itself instead of f_count of dmabuf.
+                        */
                        drm_gem_object_reference(obj);
+                       dma_buf_put(buffer);
                        return obj;
                }
        }
diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c
new file mode 100644 (file)
index 0000000..2629ba7
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * drivers/staging/omapdrm/omap_irq.c
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+static DEFINE_SPINLOCK(list_lock);
+
+static void omap_irq_error_handler(struct omap_drm_irq *irq,
+               uint32_t irqstatus)
+{
+       DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+/* call with list_lock and dispc runtime held */
+static void omap_irq_update(struct drm_device *dev)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       struct omap_drm_irq *irq;
+       uint32_t irqmask = priv->vblank_mask;
+
+       BUG_ON(!spin_is_locked(&list_lock));
+
+       list_for_each_entry(irq, &priv->irq_list, node)
+               irqmask |= irq->irqmask;
+
+       DBG("irqmask=%08x", irqmask);
+
+       dispc_write_irqenable(irqmask);
+       dispc_read_irqenable();        /* flush posted write */
+}
+
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       unsigned long flags;
+
+       dispc_runtime_get();
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (!WARN_ON(irq->registered)) {
+               irq->registered = true;
+               list_add(&irq->node, &priv->irq_list);
+               omap_irq_update(dev);
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+       dispc_runtime_put();
+}
+
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       unsigned long flags;
+
+       dispc_runtime_get();
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (!WARN_ON(!irq->registered)) {
+               irq->registered = false;
+               list_del(&irq->node);
+               omap_irq_update(dev);
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+       dispc_runtime_put();
+}
+
+struct omap_irq_wait {
+       struct omap_drm_irq irq;
+       int count;
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_event);
+
+static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+       struct omap_irq_wait *wait =
+                       container_of(irq, struct omap_irq_wait, irq);
+       wait->count--;
+       wake_up_all(&wait_event);
+}
+
+struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
+               uint32_t irqmask, int count)
+{
+       struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
+       wait->irq.irq = wait_irq;
+       wait->irq.irqmask = irqmask;
+       wait->count = count;
+       omap_irq_register(dev, &wait->irq);
+       return wait;
+}
+
+int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
+               unsigned long timeout)
+{
+       int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
+       omap_irq_unregister(dev, &wait->irq);
+       kfree(wait);
+       if (ret == 0)
+               return -1;
+       return 0;
+}
+
+/**
+ * enable_vblank - enable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Enable vblank interrupts for @crtc.  If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ *
+ * RETURNS
+ * Zero on success, appropriate errno if the given @crtc's vblank
+ * interrupt cannot be enabled.
+ */
+int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       unsigned long flags;
+
+       DBG("dev=%p, crtc=%d", dev, crtc);
+
+       dispc_runtime_get();
+       spin_lock_irqsave(&list_lock, flags);
+       priv->vblank_mask |= pipe2vbl(crtc);
+       omap_irq_update(dev);
+       spin_unlock_irqrestore(&list_lock, flags);
+       dispc_runtime_put();
+
+       return 0;
+}
+
+/**
+ * disable_vblank - disable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Disable vblank interrupts for @crtc.  If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ */
+void omap_irq_disable_vblank(struct drm_device *dev, int crtc)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       unsigned long flags;
+
+       DBG("dev=%p, crtc=%d", dev, crtc);
+
+       dispc_runtime_get();
+       spin_lock_irqsave(&list_lock, flags);
+       priv->vblank_mask &= ~pipe2vbl(crtc);
+       omap_irq_update(dev);
+       spin_unlock_irqrestore(&list_lock, flags);
+       dispc_runtime_put();
+}
+
+irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       struct omap_drm_private *priv = dev->dev_private;
+       struct omap_drm_irq *handler, *n;
+       unsigned long flags;
+       unsigned int id;
+       u32 irqstatus;
+
+       irqstatus = dispc_read_irqstatus();
+       dispc_clear_irqstatus(irqstatus);
+       dispc_read_irqstatus();        /* flush posted write */
+
+       VERB("irqs: %08x", irqstatus);
+
+       for (id = 0; id < priv->num_crtcs; id++)
+               if (irqstatus & pipe2vbl(id))
+                       drm_handle_vblank(dev, id);
+
+       spin_lock_irqsave(&list_lock, flags);
+       list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
+               if (handler->irqmask & irqstatus) {
+                       spin_unlock_irqrestore(&list_lock, flags);
+                       handler->irq(handler, handler->irqmask & irqstatus);
+                       spin_lock_irqsave(&list_lock, flags);
+               }
+       }
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+void omap_irq_preinstall(struct drm_device *dev)
+{
+       DBG("dev=%p", dev);
+       dispc_runtime_get();
+       dispc_clear_irqstatus(0xffffffff);
+       dispc_runtime_put();
+}
+
+int omap_irq_postinstall(struct drm_device *dev)
+{
+       struct omap_drm_private *priv = dev->dev_private;
+       struct omap_drm_irq *error_handler = &priv->error_handler;
+
+       DBG("dev=%p", dev);
+
+       INIT_LIST_HEAD(&priv->irq_list);
+
+       error_handler->irq = omap_irq_error_handler;
+       error_handler->irqmask = DISPC_IRQ_OCP_ERR;
+
+       /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
+        * we just need to ignore it while enabling tv-out
+        */
+       error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
+
+       omap_irq_register(dev, error_handler);
+
+       return 0;
+}
+
+void omap_irq_uninstall(struct drm_device *dev)
+{
+       DBG("dev=%p", dev);
+       // TODO prolly need to call drm_irq_uninstall() somewhere too
+}
+
+/*
+ * We need a special version, instead of just using drm_irq_install(),
+ * because we need to register the irq via omapdss.  Once omapdss and
+ * omapdrm are merged together we can assign the dispc hwmod data to
+ * ourselves and drop these and just use drm_irq_{install,uninstall}()
+ */
+
+int omap_drm_irq_install(struct drm_device *dev)
+{
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (dev->irq_enabled) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EBUSY;
+       }
+       dev->irq_enabled = 1;
+       mutex_unlock(&dev->struct_mutex);
+
+       /* Before installing handler */
+       if (dev->driver->irq_preinstall)
+               dev->driver->irq_preinstall(dev);
+
+       ret = dispc_request_irq(dev->driver->irq_handler, dev);
+
+       if (ret < 0) {
+               mutex_lock(&dev->struct_mutex);
+               dev->irq_enabled = 0;
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       /* After installing handler */
+       if (dev->driver->irq_postinstall)
+               ret = dev->driver->irq_postinstall(dev);
+
+       if (ret < 0) {
+               mutex_lock(&dev->struct_mutex);
+               dev->irq_enabled = 0;
+               mutex_unlock(&dev->struct_mutex);
+               dispc_free_irq(dev);
+       }
+
+       return ret;
+}
+
+int omap_drm_irq_uninstall(struct drm_device *dev)
+{
+       unsigned long irqflags;
+       int irq_enabled, i;
+
+       mutex_lock(&dev->struct_mutex);
+       irq_enabled = dev->irq_enabled;
+       dev->irq_enabled = 0;
+       mutex_unlock(&dev->struct_mutex);
+
+       /*
+        * Wake up any waiters so they don't hang.
+        */
+       if (dev->num_crtcs) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               for (i = 0; i < dev->num_crtcs; i++) {
+                       DRM_WAKEUP(&dev->vbl_queue[i]);
+                       dev->vblank_enabled[i] = 0;
+                       dev->last_vblank[i] =
+                               dev->driver->get_vblank_counter(dev, i);
+               }
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+       }
+
+       if (!irq_enabled)
+               return -EINVAL;
+
+       if (dev->driver->irq_uninstall)
+               dev->driver->irq_uninstall(dev);
+
+       dispc_free_irq(dev);
+
+       return 0;
+}
index 2a8e5bab49c908aa2ef3edd9da4ded8f6074dd67..bb989d7f026dcafd62f1aba1f5d1877ea34d3d9b 100644 (file)
@@ -41,12 +41,14 @@ struct callback {
 
 struct omap_plane {
        struct drm_plane base;
-       struct omap_overlay *ovl;
+       int id;  /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */
+       const char *name;
        struct omap_overlay_info info;
+       struct omap_drm_apply apply;
 
        /* position/orientation of scanout within the fb: */
        struct omap_drm_window win;
-
+       bool enabled;
 
        /* last fb that we pinned: */
        struct drm_framebuffer *pinned_fb;
@@ -54,189 +56,15 @@ struct omap_plane {
        uint32_t nformats;
        uint32_t formats[32];
 
-       /* for synchronizing access to unpins fifo */
-       struct mutex unpin_mutex;
+       struct omap_drm_irq error_irq;
 
-       /* set of bo's pending unpin until next END_WIN irq */
+       /* set of bo's pending unpin until next post_apply() */
        DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *);
-       int num_unpins, pending_num_unpins;
-
-       /* for deferred unpin when we need to wait for scanout complete irq */
-       struct work_struct work;
-
-       /* callback on next endwin irq */
-       struct callback endwin;
-};
 
-/* map from ovl->id to the irq we are interested in for scanout-done */
-static const uint32_t id2irq[] = {
-               [OMAP_DSS_GFX]    = DISPC_IRQ_GFX_END_WIN,
-               [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN,
-               [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN,
-               [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN,
+       // XXX maybe get rid of this and handle vblank in crtc too?
+       struct callback apply_done_cb;
 };
 
-static void dispc_isr(void *arg, uint32_t mask)
-{
-       struct drm_plane *plane = arg;
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_drm_private *priv = plane->dev->dev_private;
-
-       omap_dispc_unregister_isr(dispc_isr, plane,
-                       id2irq[omap_plane->ovl->id]);
-
-       queue_work(priv->wq, &omap_plane->work);
-}
-
-static void unpin_worker(struct work_struct *work)
-{
-       struct omap_plane *omap_plane =
-                       container_of(work, struct omap_plane, work);
-       struct callback endwin;
-
-       mutex_lock(&omap_plane->unpin_mutex);
-       DBG("unpinning %d of %d", omap_plane->num_unpins,
-                       omap_plane->num_unpins + omap_plane->pending_num_unpins);
-       while (omap_plane->num_unpins > 0) {
-               struct drm_gem_object *bo = NULL;
-               int ret = kfifo_get(&omap_plane->unpin_fifo, &bo);
-               WARN_ON(!ret);
-               omap_gem_put_paddr(bo);
-               drm_gem_object_unreference_unlocked(bo);
-               omap_plane->num_unpins--;
-       }
-       endwin = omap_plane->endwin;
-       omap_plane->endwin.fxn = NULL;
-       mutex_unlock(&omap_plane->unpin_mutex);
-
-       if (endwin.fxn)
-               endwin.fxn(endwin.arg);
-}
-
-static void install_irq(struct drm_plane *plane)
-{
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_overlay *ovl = omap_plane->ovl;
-       int ret;
-
-       ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]);
-
-       /*
-        * omapdss has upper limit on # of registered irq handlers,
-        * which we shouldn't hit.. but if we do the limit should
-        * be raised or bad things happen:
-        */
-       WARN_ON(ret == -EBUSY);
-}
-
-/* push changes down to dss2 */
-static int commit(struct drm_plane *plane)
-{
-       struct drm_device *dev = plane->dev;
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_overlay *ovl = omap_plane->ovl;
-       struct omap_overlay_info *info = &omap_plane->info;
-       int ret;
-
-       DBG("%s", ovl->name);
-       DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
-                       info->out_height, info->screen_width);
-       DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
-                       info->paddr, info->p_uv_addr);
-
-       /* NOTE: do we want to do this at all here, or just wait
-        * for dpms(ON) since other CRTC's may not have their mode
-        * set yet, so fb dimensions may still change..
-        */
-       ret = ovl->set_overlay_info(ovl, info);
-       if (ret) {
-               dev_err(dev->dev, "could not set overlay info\n");
-               return ret;
-       }
-
-       mutex_lock(&omap_plane->unpin_mutex);
-       omap_plane->num_unpins += omap_plane->pending_num_unpins;
-       omap_plane->pending_num_unpins = 0;
-       mutex_unlock(&omap_plane->unpin_mutex);
-
-       /* our encoder doesn't necessarily get a commit() after this, in
-        * particular in the dpms() and mode_set_base() cases, so force the
-        * manager to update:
-        *
-        * could this be in the encoder somehow?
-        */
-       if (ovl->manager) {
-               ret = ovl->manager->apply(ovl->manager);
-               if (ret) {
-                       dev_err(dev->dev, "could not apply settings\n");
-                       return ret;
-               }
-
-               /*
-                * NOTE: really this should be atomic w/ mgr->apply() but
-                * omapdss does not expose such an API
-                */
-               if (omap_plane->num_unpins > 0)
-                       install_irq(plane);
-
-       } else {
-               struct omap_drm_private *priv = dev->dev_private;
-               queue_work(priv->wq, &omap_plane->work);
-       }
-
-
-       if (ovl->is_enabled(ovl)) {
-               omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
-                               info->out_width, info->out_height);
-       }
-
-       return 0;
-}
-
-/* when CRTC that we are attached to has potentially changed, this checks
- * if we are attached to proper manager, and if necessary updates.
- */
-static void update_manager(struct drm_plane *plane)
-{
-       struct omap_drm_private *priv = plane->dev->dev_private;
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_overlay *ovl = omap_plane->ovl;
-       struct omap_overlay_manager *mgr = NULL;
-       int i;
-
-       if (plane->crtc) {
-               for (i = 0; i < priv->num_encoders; i++) {
-                       struct drm_encoder *encoder = priv->encoders[i];
-                       if (encoder->crtc == plane->crtc) {
-                               mgr = omap_encoder_get_manager(encoder);
-                               break;
-                       }
-               }
-       }
-
-       if (ovl->manager != mgr) {
-               bool enabled = ovl->is_enabled(ovl);
-
-               /* don't switch things around with enabled overlays: */
-               if (enabled)
-                       omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
-
-               if (ovl->manager) {
-                       DBG("disconnecting %s from %s", ovl->name,
-                                       ovl->manager->name);
-                       ovl->unset_manager(ovl);
-               }
-
-               if (mgr) {
-                       DBG("connecting %s to %s", ovl->name, mgr->name);
-                       ovl->set_manager(ovl, mgr);
-               }
-
-               if (enabled && mgr)
-                       omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-       }
-}
-
 static void unpin(void *arg, struct drm_gem_object *bo)
 {
        struct drm_plane *plane = arg;
@@ -244,7 +72,6 @@ static void unpin(void *arg, struct drm_gem_object *bo)
 
        if (kfifo_put(&omap_plane->unpin_fifo,
                        (const struct drm_gem_object **)&bo)) {
-               omap_plane->pending_num_unpins++;
                /* also hold a ref so it isn't free'd while pinned */
                drm_gem_object_reference(bo);
        } else {
@@ -264,13 +91,19 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
 
                DBG("%p -> %p", pinned_fb, fb);
 
-               mutex_lock(&omap_plane->unpin_mutex);
+               if (fb)
+                       drm_framebuffer_reference(fb);
+
                ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin);
-               mutex_unlock(&omap_plane->unpin_mutex);
+
+               if (pinned_fb)
+                       drm_framebuffer_unreference(pinned_fb);
 
                if (ret) {
                        dev_err(plane->dev->dev, "could not swap %p -> %p\n",
                                        omap_plane->pinned_fb, fb);
+                       if (fb)
+                               drm_framebuffer_unreference(fb);
                        omap_plane->pinned_fb = NULL;
                        return ret;
                }
@@ -281,31 +114,90 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
        return 0;
 }
 
-/* update parameters that are dependent on the framebuffer dimensions and
- * position within the fb that this plane scans out from. This is called
- * when framebuffer or x,y base may have changed.
- */
-static void update_scanout(struct drm_plane *plane)
+static void omap_plane_pre_apply(struct omap_drm_apply *apply)
 {
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_overlay_info *info = &omap_plane->info;
+       struct omap_plane *omap_plane =
+                       container_of(apply, struct omap_plane, apply);
        struct omap_drm_window *win = &omap_plane->win;
+       struct drm_plane *plane = &omap_plane->base;
+       struct drm_device *dev = plane->dev;
+       struct omap_overlay_info *info = &omap_plane->info;
+       struct drm_crtc *crtc = plane->crtc;
+       enum omap_channel channel;
+       bool enabled = omap_plane->enabled && crtc;
+       bool ilace, replication;
        int ret;
 
-       ret = update_pin(plane, plane->fb);
-       if (ret) {
-               dev_err(plane->dev->dev,
-                       "could not pin fb: %d\n", ret);
-               omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+       DBG("%s, enabled=%d", omap_plane->name, enabled);
+
+       /* if fb has changed, pin new fb: */
+       update_pin(plane, enabled ? plane->fb : NULL);
+
+       if (!enabled) {
+               dispc_ovl_enable(omap_plane->id, false);
                return;
        }
 
+       channel = omap_crtc_channel(crtc);
+
+       /* update scanout: */
        omap_framebuffer_update_scanout(plane->fb, win, info);
 
-       DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name,
-                       win->src_x, win->src_y,
-                       (u32)info->paddr, (u32)info->p_uv_addr,
+       DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
+                       info->out_width, info->out_height,
                        info->screen_width);
+       DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
+                       info->paddr, info->p_uv_addr);
+
+       /* TODO: */
+       ilace = false;
+       replication = false;
+
+       /* and finally, update omapdss: */
+       ret = dispc_ovl_setup(omap_plane->id, info,
+                       replication, omap_crtc_timings(crtc), false);
+       if (ret) {
+               dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
+               return;
+       }
+
+       dispc_ovl_enable(omap_plane->id, true);
+       dispc_ovl_set_channel_out(omap_plane->id, channel);
+}
+
+static void omap_plane_post_apply(struct omap_drm_apply *apply)
+{
+       struct omap_plane *omap_plane =
+                       container_of(apply, struct omap_plane, apply);
+       struct drm_plane *plane = &omap_plane->base;
+       struct omap_overlay_info *info = &omap_plane->info;
+       struct drm_gem_object *bo = NULL;
+       struct callback cb;
+
+       cb = omap_plane->apply_done_cb;
+       omap_plane->apply_done_cb.fxn = NULL;
+
+       while (kfifo_get(&omap_plane->unpin_fifo, &bo)) {
+               omap_gem_put_paddr(bo);
+               drm_gem_object_unreference_unlocked(bo);
+       }
+
+       if (cb.fxn)
+               cb.fxn(cb.arg);
+
+       if (omap_plane->enabled) {
+               omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
+                               info->out_width, info->out_height);
+       }
+}
+
+static int apply(struct drm_plane *plane)
+{
+       if (plane->crtc) {
+               struct omap_plane *omap_plane = to_omap_plane(plane);
+               return omap_crtc_apply(plane->crtc, &omap_plane->apply);
+       }
+       return 0;
 }
 
 int omap_plane_mode_set(struct drm_plane *plane,
@@ -313,7 +205,8 @@ int omap_plane_mode_set(struct drm_plane *plane,
                int crtc_x, int crtc_y,
                unsigned int crtc_w, unsigned int crtc_h,
                uint32_t src_x, uint32_t src_y,
-               uint32_t src_w, uint32_t src_h)
+               uint32_t src_w, uint32_t src_h,
+               void (*fxn)(void *), void *arg)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
        struct omap_drm_window *win = &omap_plane->win;
@@ -329,17 +222,20 @@ int omap_plane_mode_set(struct drm_plane *plane,
        win->src_w = src_w >> 16;
        win->src_h = src_h >> 16;
 
-       /* note: this is done after this fxn returns.. but if we need
-        * to do a commit/update_scanout, etc before this returns we
-        * need the current value.
-        */
+       if (fxn) {
+               /* omap_crtc should ensure that a new page flip
+                * isn't permitted while there is one pending:
+                */
+               BUG_ON(omap_plane->apply_done_cb.fxn);
+
+               omap_plane->apply_done_cb.fxn = fxn;
+               omap_plane->apply_done_cb.arg = arg;
+       }
+
        plane->fb = fb;
        plane->crtc = crtc;
 
-       update_scanout(plane);
-       update_manager(plane);
-
-       return 0;
+       return apply(plane);
 }
 
 static int omap_plane_update(struct drm_plane *plane,
@@ -349,9 +245,12 @@ static int omap_plane_update(struct drm_plane *plane,
                uint32_t src_x, uint32_t src_y,
                uint32_t src_w, uint32_t src_h)
 {
-       omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h,
-                       src_x, src_y, src_w, src_h);
-       return omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       omap_plane->enabled = true;
+       return omap_plane_mode_set(plane, crtc, fb,
+                       crtc_x, crtc_y, crtc_w, crtc_h,
+                       src_x, src_y, src_w, src_h,
+                       NULL, NULL);
 }
 
 static int omap_plane_disable(struct drm_plane *plane)
@@ -364,48 +263,32 @@ static int omap_plane_disable(struct drm_plane *plane)
 static void omap_plane_destroy(struct drm_plane *plane)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
-       DBG("%s", omap_plane->ovl->name);
+
+       DBG("%s", omap_plane->name);
+
+       omap_irq_unregister(plane->dev, &omap_plane->error_irq);
+
        omap_plane_disable(plane);
        drm_plane_cleanup(plane);
-       WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0);
+
+       WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo));
        kfifo_free(&omap_plane->unpin_fifo);
+
        kfree(omap_plane);
 }
 
 int omap_plane_dpms(struct drm_plane *plane, int mode)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
-       struct omap_overlay *ovl = omap_plane->ovl;
-       int r;
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+       int ret = 0;
 
-       DBG("%s: %d", omap_plane->ovl->name, mode);
-
-       if (mode == DRM_MODE_DPMS_ON) {
-               update_scanout(plane);
-               r = commit(plane);
-               if (!r)
-                       r = ovl->enable(ovl);
-       } else {
-               struct omap_drm_private *priv = plane->dev->dev_private;
-               r = ovl->disable(ovl);
-               update_pin(plane, NULL);
-               queue_work(priv->wq, &omap_plane->work);
+       if (enabled != omap_plane->enabled) {
+               omap_plane->enabled = enabled;
+               ret = apply(plane);
        }
 
-       return r;
-}
-
-void omap_plane_on_endwin(struct drm_plane *plane,
-               void (*fxn)(void *), void *arg)
-{
-       struct omap_plane *omap_plane = to_omap_plane(plane);
-
-       mutex_lock(&omap_plane->unpin_mutex);
-       omap_plane->endwin.fxn = fxn;
-       omap_plane->endwin.arg = arg;
-       mutex_unlock(&omap_plane->unpin_mutex);
-
-       install_irq(plane);
+       return ret;
 }
 
 /* helper to install properties which are common to planes and crtcs */
@@ -454,25 +337,13 @@ int omap_plane_set_property(struct drm_plane *plane,
        int ret = -EINVAL;
 
        if (property == priv->rotation_prop) {
-               struct omap_overlay *ovl = omap_plane->ovl;
-
-               DBG("%s: rotation: %02x", ovl->name, (uint32_t)val);
+               DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
                omap_plane->win.rotation = val;
-
-               if (ovl->is_enabled(ovl))
-                       ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-               else
-                       ret = 0;
+               ret = apply(plane);
        } else if (property == priv->zorder_prop) {
-               struct omap_overlay *ovl = omap_plane->ovl;
-
-               DBG("%s: zorder: %d", ovl->name, (uint32_t)val);
+               DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
                omap_plane->info.zorder = val;
-
-               if (ovl->is_enabled(ovl))
-                       ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-               else
-                       ret = 0;
+               ret = apply(plane);
        }
 
        return ret;
@@ -485,20 +356,38 @@ static const struct drm_plane_funcs omap_plane_funcs = {
                .set_property = omap_plane_set_property,
 };
 
+static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+       struct omap_plane *omap_plane =
+                       container_of(irq, struct omap_plane, error_irq);
+       DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus);
+}
+
+static const char *plane_names[] = {
+               [OMAP_DSS_GFX] = "gfx",
+               [OMAP_DSS_VIDEO1] = "vid1",
+               [OMAP_DSS_VIDEO2] = "vid2",
+               [OMAP_DSS_VIDEO3] = "vid3",
+};
+
+static const uint32_t error_irqs[] = {
+               [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+               [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+               [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+               [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+};
+
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-               struct omap_overlay *ovl, unsigned int possible_crtcs,
-               bool priv)
+               int id, bool private_plane)
 {
+       struct omap_drm_private *priv = dev->dev_private;
        struct drm_plane *plane = NULL;
        struct omap_plane *omap_plane;
+       struct omap_overlay_info *info;
        int ret;
 
-       DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name,
-                       possible_crtcs, priv);
-
-       /* friendly reminder to update table for future hw: */
-       WARN_ON(ovl->id >= ARRAY_SIZE(id2irq));
+       DBG("%s: priv=%d", plane_names[id], private_plane);
 
        omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
        if (!omap_plane) {
@@ -506,47 +395,50 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
                goto fail;
        }
 
-       mutex_init(&omap_plane->unpin_mutex);
-
        ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
        if (ret) {
                dev_err(dev->dev, "could not allocate unpin FIFO\n");
                goto fail;
        }
 
-       INIT_WORK(&omap_plane->work, unpin_worker);
-
        omap_plane->nformats = omap_framebuffer_get_formats(
                        omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
-                       ovl->supported_modes);
-       omap_plane->ovl = ovl;
+                       dss_feat_get_supported_color_modes(id));
+       omap_plane->id = id;
+       omap_plane->name = plane_names[id];
+
        plane = &omap_plane->base;
 
-       drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
-                       omap_plane->formats, omap_plane->nformats, priv);
+       omap_plane->apply.pre_apply  = omap_plane_pre_apply;
+       omap_plane->apply.post_apply = omap_plane_post_apply;
+
+       omap_plane->error_irq.irqmask = error_irqs[id];
+       omap_plane->error_irq.irq = omap_plane_error_irq;
+       omap_irq_register(dev, &omap_plane->error_irq);
+
+       drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs,
+                       omap_plane->formats, omap_plane->nformats, private_plane);
 
        omap_plane_install_properties(plane, &plane->base);
 
        /* get our starting configuration, set defaults for parameters
         * we don't currently use, etc:
         */
-       ovl->get_overlay_info(ovl, &omap_plane->info);
-       omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA;
-       omap_plane->info.rotation = OMAP_DSS_ROT_0;
-       omap_plane->info.global_alpha = 0xff;
-       omap_plane->info.mirror = 0;
+       info = &omap_plane->info;
+       info->rotation_type = OMAP_DSS_ROT_DMA;
+       info->rotation = OMAP_DSS_ROT_0;
+       info->global_alpha = 0xff;
+       info->mirror = 0;
 
        /* Set defaults depending on whether we are a CRTC or overlay
         * layer.
         * TODO add ioctl to give userspace an API to change this.. this
         * will come in a subsequent patch.
         */
-       if (priv)
+       if (private_plane)
                omap_plane->info.zorder = 0;
        else
-               omap_plane->info.zorder = ovl->id;
-
-       update_manager(plane);
+               omap_plane->info.zorder = id;
 
        return plane;
 
index ae38475854b50249f6787b90762cd025c26fef5b..d10d75e8a33fc6775b8901297a6c9de397b064ce 100644 (file)
@@ -937,7 +937,8 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
 
                dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
                                         PCI_DMA_FROMDEVICE);
-
+               if (pci_dma_mapping_error(pdev, dma_tmp))
+                       return -1;
                if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
                           &(priv->rxbufferhead))) {
                        DMESGE("Unable to allocate mem RX buf");
index 808aab6fa5ef70b23baf41cbe4bbad20ca6d9f9c..a9d78e9651c6006a981c7e26c920f71cd57692d2 100644 (file)
@@ -1183,6 +1183,8 @@ void  rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
                                                pTxFwInfo->TxRate,
                                                cb_desc);
 
+       if (pci_dma_mapping_error(priv->pdev, mapping))
+               RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
        if (cb_desc->bAMPDUEnable) {
                pTxFwInfo->AllowAggregation = 1;
                pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1280,6 +1282,8 @@ void  rtl8192_tx_fill_cmd_desc(struct net_device *dev,
        dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
                         PCI_DMA_TODEVICE);
 
+       if (pci_dma_mapping_error(priv->pdev, mapping))
+               RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
        memset(entry, 0, 12);
        entry->LINIP = cb_desc->bLastIniPkt;
        entry->FirstSeg = 1;
index 1a70f324552f14becf86c43d347b4977b84cd94e..4ebf99b3097543b07cad50a264e700d70b926e27 100644 (file)
@@ -2104,7 +2104,10 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
                                                  skb_tail_pointer_rsl(skb),
                                                  priv->rxbuffersize,
                                                  PCI_DMA_FROMDEVICE);
-
+                       if (pci_dma_mapping_error(priv->pdev, *mapping)) {
+                               dev_kfree_skb_any(skb);
+                               return -1;
+                       }
                        entry->BufferAddress = cpu_to_le32(*mapping);
 
                        entry->Length = priv->rxbuffersize;
@@ -2397,7 +2400,11 @@ static void rtl8192_rx_normal(struct net_device *dev)
                                                    skb_tail_pointer_rsl(skb),
                                                    priv->rxbuffersize,
                                                    PCI_DMA_FROMDEVICE);
-
+                       if (pci_dma_mapping_error(priv->pdev,
+                                                 *((dma_addr_t *)skb->cb))) {
+                               dev_kfree_skb_any(skb);
+                               return;
+                       }
                }
 done:
                pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
index 6b73843e580af46e373c7885898b45e97baa9928..a96cd06d69dd7fc9ed78d71ec920763b8c33c022 100644 (file)
@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
        {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
        /* Belkin */
        {USB_DEVICE(0x050D, 0x945A)},
+       /* ISY IWL - Belkin clone */
+       {USB_DEVICE(0x050D, 0x11F1)},
        /* Corega */
        {USB_DEVICE(0x07AA, 0x0047)},
        /* D-Link */
index ac87c5e38dee05ec7f8e072a3d27c5c346594a13..1facad625554b0b88baf67c70e4a33b46d77560b 100644 (file)
@@ -2,6 +2,7 @@ config SB105X
        tristate "SystemBase PCI Multiport UART"
        select SERIAL_CORE
        depends on PCI
+       depends on X86
        help
          A driver for the SystemBase Multi-2/PCI serial card
 
index edb2a85b9d52512c41b161db44b5f74e93a44cd8..9464f3874346eb141f115c65752b9bbe41fc4c7d 100644 (file)
@@ -3054,6 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
                                sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
                        }
                        break;
+#ifdef CONFIG_PARPORT_PC
                case PCI_DEVICE_ID_MP2S1P :
                        sbdev->nr_ports = 2;
 
@@ -3073,6 +3074,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
                        /* add PC compatible parallel port */
                        parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
                        break;
+#endif
        }
 
        ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
index df9533798095cd7b2e2b08a1799f206c5091e07c..7616f058a00b43ab4c1dd91d0384e6a5400b9a65 100644 (file)
@@ -342,7 +342,7 @@ int synth_init(char *synth_name)
 
        mutex_lock(&spk_mutex);
        /* First, check if we already have it loaded. */
-       for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
+       for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
                if (strcmp(synths[i]->name, synth_name) == 0)
                        synth = synths[i];
 
@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth)
        int i;
        int status = 0;
        mutex_lock(&spk_mutex);
-       for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
+       for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
                /* synth_remove() is responsible for rotating the array down */
                if (in_synth == synths[i]) {
                        mutex_unlock(&spk_mutex);
index 543a127c7d4d63e5b43de81151ec54a382cf03b8..b783bfa59b1cea42f943596f8ddce5c620a08835 100644 (file)
@@ -31,7 +31,7 @@
  * driver should read or write to PRM/CM registers directly; they
  * should rely on OMAP core code to do this.
  */
-#include <mach-omap2/cm2xxx_3xxx.h>
+#include <mach-omap2/cm3xxx.h>
 #include <mach-omap2/prm-regbits-34xx.h>
 #include <mach-omap2/cm-regbits-34xx.h>
 #include <dspbridge/devdefs.h>
index b647207928b14aca75a5e445cce94e5efc56b940..2f084e181d39de2131360677c65c9deb4ed3143f 100644 (file)
@@ -121,9 +121,13 @@ void dsp_clk_exit(void)
        for (i = 0; i < DM_TIMER_CLOCKS; i++)
                omap_dm_timer_free(timer[i]);
 
+       clk_unprepare(iva2_clk);
        clk_put(iva2_clk);
+       clk_unprepare(ssi.sst_fck);
        clk_put(ssi.sst_fck);
+       clk_unprepare(ssi.ssr_fck);
        clk_put(ssi.ssr_fck);
+       clk_unprepare(ssi.ick);
        clk_put(ssi.ick);
 }
 
@@ -145,14 +149,21 @@ void dsp_clk_init(void)
        iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck");
        if (IS_ERR(iva2_clk))
                dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk);
+       else
+               clk_prepare(iva2_clk);
 
        ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck");
        ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck");
        ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick");
 
-       if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick))
+       if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) {
                dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n",
                                        ssi.sst_fck, ssi.ssr_fck, ssi.ick);
+       } else {
+               clk_prepare(ssi.sst_fck);
+               clk_prepare(ssi.ssr_fck);
+               clk_prepare(ssi.ick);
+       }
 }
 
 /**
index 1dce36fb828f1d24ebcd8ea4d19c5c86d9587c88..7ff0e6c980395c80c9c83fe4355a6eef854a6a79 100644 (file)
@@ -63,11 +63,15 @@ int dsp_wdt_init(void)
        dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
 
        if (!IS_ERR(dsp_wdt.fclk)) {
+               clk_prepare(dsp_wdt.fclk);
+
                dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
                if (IS_ERR(dsp_wdt.iclk)) {
                        clk_put(dsp_wdt.fclk);
                        dsp_wdt.fclk = NULL;
                        ret = -EFAULT;
+               } else {
+                       clk_prepare(dsp_wdt.iclk);
                }
        } else
                ret = -EFAULT;
@@ -95,10 +99,14 @@ void dsp_wdt_exit(void)
        free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
        tasklet_kill(&dsp_wdt.wdt3_tasklet);
 
-       if (dsp_wdt.fclk)
+       if (dsp_wdt.fclk) {
+               clk_unprepare(dsp_wdt.fclk);
                clk_put(dsp_wdt.fclk);
-       if (dsp_wdt.iclk)
+       }
+       if (dsp_wdt.iclk) {
+               clk_unprepare(dsp_wdt.iclk);
                clk_put(dsp_wdt.iclk);
+       }
 
        dsp_wdt.fclk = NULL;
        dsp_wdt.iclk = NULL;
index 0331178ca3b3c65d54da5a9ea0920118008e87f4..bf73ba26e88aee484b21dc5aeff7b661c07f0c90 100644 (file)
@@ -162,11 +162,9 @@ static struct vme_driver pio2_driver = {
 
 static int __init pio2_init(void)
 {
-       int retval = 0;
-
        if (bus_num == 0) {
                pr_err("No cards, skipping registration\n");
-               goto err_nocard;
+               return -ENODEV;
        }
 
        if (bus_num > PIO2_CARDS_MAX) {
@@ -176,15 +174,7 @@ static int __init pio2_init(void)
        }
 
        /* Register the PIO2 driver */
-       retval = vme_register_driver(&pio2_driver, bus_num);
-       if (retval != 0)
-               goto err_reg;
-
-       return retval;
-
-err_reg:
-err_nocard:
-       return retval;
+       return  vme_register_driver(&pio2_driver, bus_num);
 }
 
 static int pio2_match(struct vme_dev *vdev)
index 6b2ec390e77503e177989ef89ec205011d02b031..806cbf72fb59b6f58eb1419d98af755475fed311 100644 (file)
@@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject {
 } SRSNCapObject, *PSRSNCapObject;
 
 // BSS info(AP)
-#pragma pack(1)
 typedef struct tagKnownBSS {
     // BSS info
     BOOL            bActive;
index 5d8faf9f96ec4aac7f4e4c452b7d83dafb79bd35..e0d2b07ba608d14415f19daee1ae8d0924b6cf65 100644 (file)
@@ -34,7 +34,6 @@
 #include "device.h"
 
 /*---------------------  Export Definitions -------------------------*/
-#pragma pack(1)
 typedef struct tagSINTData {
        BYTE byTSR0;
        BYTE byPkt0;
index 22710cef751d77fe51dc9d760fc98574c6c94b44..ae6e2d237b207250a9ced56d059e590dccb61964 100644 (file)
@@ -95,13 +95,12 @@ typedef enum tagWZONETYPE {
 // Ioctl interface structure
 // Command structure
 //
-#pragma pack(1)
 typedef struct tagSCmdRequest {
        u8 name[16];
        void    *data;
        u16         wResult;
        u16     wCmdCode;
-} SCmdRequest, *PSCmdRequest;
+} __packed SCmdRequest, *PSCmdRequest;
 
 //
 // Scan
@@ -111,7 +110,7 @@ typedef struct tagSCmdScan {
 
     u8     ssid[SSID_MAXLEN + 2];
 
-} SCmdScan, *PSCmdScan;
+} __packed SCmdScan, *PSCmdScan;
 
 //
 // BSS Join
@@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin {
     BOOL    bPSEnable;
     BOOL    bShareKeyAuth;
 
-} SCmdBSSJoin, *PSCmdBSSJoin;
+} __packed SCmdBSSJoin, *PSCmdBSSJoin;
 
 //
 // Zonetype Setting
@@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet {
  BOOL       bWrite;
  WZONETYPE  ZoneType;
 
-} SCmdZoneTypeSet, *PSCmdZoneTypeSet;
+} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet;
 
 typedef struct tagSWPAResult {
          char  ifname[100];
@@ -145,7 +144,7 @@ typedef struct tagSWPAResult {
        u8 key_mgmt;
        u8 eap_type;
          BOOL authenticated;
-} SWPAResult, *PSWPAResult;
+} __packed SWPAResult, *PSWPAResult;
 
 typedef struct tagSCmdStartAP {
 
@@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP {
     BOOL    bShareKeyAuth;
     u8      byBasicRate;
 
-} SCmdStartAP, *PSCmdStartAP;
+} __packed SCmdStartAP, *PSCmdStartAP;
 
 typedef struct tagSCmdSetWEP {
 
@@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP {
     BOOL    bWepKeyAvailable[WEP_NKEYS];
     u32     auWepKeyLength[WEP_NKEYS];
 
-} SCmdSetWEP, *PSCmdSetWEP;
+} __packed SCmdSetWEP, *PSCmdSetWEP;
 
 typedef struct tagSBSSIDItem {
 
@@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem {
     BOOL    bWEPOn;
     u32     uRSSI;
 
-} SBSSIDItem;
+} __packed SBSSIDItem;
 
 
 typedef struct tagSBSSIDList {
 
        u32                 uItem;
        SBSSIDItem      sBSSIDList[0];
-} SBSSIDList, *PSBSSIDList;
+} __packed SBSSIDList, *PSBSSIDList;
 
 
 typedef struct tagSNodeItem {
@@ -208,7 +207,7 @@ typedef struct tagSNodeItem {
     u32            uTxAttempts;
     u16            wFailureRatio;
 
-} SNodeItem;
+} __packed SNodeItem;
 
 
 typedef struct tagSNodeList {
@@ -216,7 +215,7 @@ typedef struct tagSNodeList {
        u32                 uItem;
        SNodeItem       sNodeList[0];
 
-} SNodeList, *PSNodeList;
+} __packed SNodeList, *PSNodeList;
 
 
 typedef struct tagSCmdLinkStatus {
@@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus {
     u32     uChannel;
     u32     uLinkRate;
 
-} SCmdLinkStatus, *PSCmdLinkStatus;
+} __packed SCmdLinkStatus, *PSCmdLinkStatus;
 
 //
 // 802.11 counter
@@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount {
     u32 ReceivedFragmentCount;
     u32 MulticastReceivedFrameCount;
     u32 FCSErrorCount;
-} SDot11MIBCount, *PSDot11MIBCount;
+} __packed SDot11MIBCount, *PSDot11MIBCount;
 
 
 
@@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount {
     u32   ullTxBroadcastBytes[2];
     u32   ullTxMulticastBytes[2];
     u32   ullTxDirectedBytes[2];
-} SStatMIBCount, *PSStatMIBCount;
+} __packed SStatMIBCount, *PSStatMIBCount;
 
 typedef struct tagSCmdValue {
 
     u32     dwValue;
 
-} SCmdValue,  *PSCmdValue;
+} __packed SCmdValue,  *PSCmdValue;
 
 //
 // hostapd & viawget ioctl related
@@ -431,7 +430,7 @@ struct viawget_hostapd_param {
                        u8 ssid[32];
                } scan_req;
        } u;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
index 959c8868f6e2add1f86531ae68e96e5b58eb83fa..2522ddec718d3dd3f930097d80841ec2b8bdda88 100644 (file)
@@ -67,12 +67,11 @@ enum {
 
 
 
-#pragma pack(1)
 typedef struct viawget_wpa_header {
        u8 type;
        u16 req_ie_len;
        u16 resp_ie_len;
-} viawget_wpa_header;
+} __packed viawget_wpa_header;
 
 struct viawget_wpa_param {
        u32 cmd;
@@ -113,9 +112,8 @@ struct viawget_wpa_param {
                        u8 *buf;
                } scan_results;
        } u;
-};
+} __packed;
 
-#pragma pack(1)
 struct viawget_scan_result {
        u8 bssid[6];
        u8 ssid[32];
@@ -130,7 +128,7 @@ struct viawget_scan_result {
        int noise;
        int level;
        int maxrate;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
index 18c06a59c091b7bb1928cbac9038f5f0809a2288..1d31eab19d16b2d1ef5c2714162046da08c68500 100644 (file)
@@ -638,8 +638,8 @@ int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 }
 
 
-int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
-                       int mbm)
+int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+                       enum nl80211_tx_power_setting type, int mbm)
 {
        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
        wlandevice_t *wlandev = priv->wlandev;
@@ -665,7 +665,8 @@ exit:
        return err;
 }
 
-int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
+int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+                       int *dbm)
 {
        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
        wlandevice_t *wlandev = priv->wlandev;
index 4efa9bc0fcf0d1750152de5342d565144a2427ce..89bfd858bb280949f499c463a6ec26034bddcdad 100644 (file)
@@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
        /* SSID */
        req->ssid.status = P80211ENUM_msgitem_status_data_ok;
        req->ssid.data.len = le16_to_cpu(item->ssid.len);
-       req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN);
+       req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
        memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
 
        /* supported rates */
index fb4a7c94aed36f087cb41cc771f947b1d6776678..f2a73bd739fb94b750e66e1ee2c931e3c971a52a 100644 (file)
@@ -265,7 +265,7 @@ out_cleanup:
 static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                           int offset)
 {
-       int ret;
+       int ret = 0;
        size_t clen;
        unsigned long handle;
        struct page *page;
@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                        goto out;
                }
                ret = zram_decompress_page(zram, uncmem, index);
-               if (ret) {
-                       kfree(uncmem);
+               if (ret)
                        goto out;
-               }
        }
 
        /*
@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 
        user_mem = kmap_atomic(page);
 
-       if (is_partial_io(bvec))
+       if (is_partial_io(bvec)) {
                memcpy(uncmem + offset, user_mem + bvec->bv_offset,
                       bvec->bv_len);
-       else
+               kunmap_atomic(user_mem);
+               user_mem = NULL;
+       } else {
                uncmem = user_mem;
+       }
 
        if (page_zero_filled(uncmem)) {
-               kunmap_atomic(user_mem);
-               if (is_partial_io(bvec))
-                       kfree(uncmem);
+               if (!is_partial_io(bvec))
+                       kunmap_atomic(user_mem);
                zram_stat_inc(&zram->stats.pages_zero);
                zram_set_flag(zram, index, ZRAM_ZERO);
                ret = 0;
@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
        ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
                               zram->compress_workmem);
 
-       kunmap_atomic(user_mem);
-       if (is_partial_io(bvec))
-                       kfree(uncmem);
+       if (!is_partial_io(bvec)) {
+               kunmap_atomic(user_mem);
+               user_mem = NULL;
+               uncmem = NULL;
+       }
 
        if (unlikely(ret != LZO_E_OK)) {
                pr_err("Compression failed! err=%d\n", ret);
@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 
        if (unlikely(clen > max_zpage_size)) {
                zram_stat_inc(&zram->stats.bad_compress);
-               src = uncmem;
                clen = PAGE_SIZE;
+               src = NULL;
+               if (is_partial_io(bvec))
+                       src = uncmem;
        }
 
        handle = zs_malloc(zram->mem_pool, clen);
@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
        }
        cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO);
 
+       if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
+               src = kmap_atomic(page);
        memcpy(cmem, src, clen);
+       if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
+               kunmap_atomic(src);
 
        zs_unmap_object(zram->mem_pool, handle);
 
@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
        if (clen <= PAGE_SIZE / 2)
                zram_stat_inc(&zram->stats.good_compress);
 
-       return 0;
-
 out:
+       if (is_partial_io(bvec))
+               kfree(uncmem);
+
        if (ret)
                zram_stat64_inc(zram, &zram->stats.failed_writes);
        return ret;
index 9ac4c151eae43af4efdaac0b0f36c1ef301f068f..ba6091bf93fcde3c1463d6ba54a8ae07f812ddf0 100644 (file)
@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
                 * made generic here.
                 */
                if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
-                    iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) {
+                    iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
                        list_del(&cmd->i_conn_node);
                        spin_unlock_bh(&conn->cmd_lock);
                        iscsit_free_cmd(cmd);
index 85140f7dde1eec83305d4e41cc0eab665fb87df0..7d4ec02e29a9773d3eb1ddbcd1fc404e5ee334e8 100644 (file)
@@ -212,7 +212,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
        unsigned char *buf;
        unsigned char *ptr;
-       sense_reason_t rc;
+       sense_reason_t rc = TCM_NO_SENSE;
        u32 len = 4; /* Skip over RESERVED area in header */
        int alua_access_state, primary = 0;
        u16 tg_pt_id, rtpi;
index e2695101bb9911f1d02ba03217a3b0f059fbf0ac..f2aa7543d20aca556855c4fbde2ba3aa00b8ffcc 100644 (file)
@@ -941,6 +941,8 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 
 int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 {
+       int block_size = dev->dev_attrib.block_size;
+
        if (dev->export_count) {
                pr_err("dev[%p]: Unable to change SE Device"
                        " fabric_max_sectors while export_count is %d\n",
@@ -978,8 +980,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
        /*
         * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
         */
+       if (!block_size) {
+               block_size = 512;
+               pr_warn("Defaulting to 512 for zero block_size\n");
+       }
        fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors,
-                                                     dev->dev_attrib.block_size);
+                                                     block_size);
 
        dev->dev_attrib.fabric_max_sectors = fabric_max_sectors;
        pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
index 810263dfa4a1d9d272e16a492c5fb44365967a6c..c57bbbc7a7d10c428d750f577a381cd2689291b3 100644 (file)
@@ -754,6 +754,11 @@ static int target_fabric_port_link(
                return -EFAULT;
        }
 
+       if (!(dev->dev_flags & DF_CONFIGURED)) {
+               pr_err("se_device not configured yet, cannot port link\n");
+               return -ENODEV;
+       }
+
        tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;
        se_tpg = container_of(to_config_group(tpg_ci),
                                struct se_portal_group, tpg_group);
index e35dbf85841fa6067094a336ef23d9edbb3427e6..8e0290b38e431ed070f4a84b8db078cf446fd8e3 100644 (file)
@@ -2053,7 +2053,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
        /* Used for APTPL metadata w/ UNREGISTER */
        unsigned char *pr_aptpl_buf = NULL;
        unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
-       sense_reason_t ret;
+       sense_reason_t ret = TCM_NO_SENSE;
        int pr_holder = 0, type;
 
        if (!se_sess || !se_lun) {
index 26a6d183ccb1c3f1f5e9eb6ec213d150a7ebfa6b..a664c664a31ac6accf24d557b66c7ab12e2d9596 100644 (file)
@@ -58,11 +58,10 @@ sbc_emulate_readcapacity(struct se_cmd *cmd)
        buf[7] = dev->dev_attrib.block_size & 0xff;
 
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
@@ -97,11 +96,10 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
                buf[14] = 0x80;
 
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
index 84f9e96e8ace79d41ea71723f8ca92a28c00623a..2d88f087d9616a53ca7dad67cb44c5cf2a3d33e3 100644 (file)
@@ -641,11 +641,10 @@ spc_emulate_inquiry(struct se_cmd *cmd)
 
 out:
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        if (!ret)
                target_complete_cmd(cmd, GOOD);
@@ -851,7 +850,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        char *cdb = cmd->t_task_cdb;
-       unsigned char *buf, *map_buf;
+       unsigned char buf[SE_MODE_PAGE_BUF], *rbuf;
        int type = dev->transport->get_device_type(dev);
        int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
        bool dbd = !!(cdb[1] & 0x08);
@@ -863,26 +862,8 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
        int ret;
        int i;
 
-       map_buf = transport_kmap_data_sg(cmd);
-       if (!map_buf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-       /*
-        * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
-        * know we actually allocated a full page.  Otherwise, if the
-        * data buffer is too small, allocate a temporary buffer so we
-        * don't have to worry about overruns in all our INQUIRY
-        * emulation handling.
-        */
-       if (cmd->data_length < SE_MODE_PAGE_BUF &&
-           (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
-               buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL);
-               if (!buf) {
-                       transport_kunmap_data_sg(cmd);
-                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               }
-       } else {
-               buf = map_buf;
-       }
+       memset(buf, 0, SE_MODE_PAGE_BUF);
+
        /*
         * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for
         * MODE_SENSE_10 and byte 2 for MODE_SENSE (6).
@@ -934,8 +915,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
        if (page == 0x3f) {
                if (subpage != 0x00 && subpage != 0xff) {
                        pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage);
-                       kfree(buf);
-                       transport_kunmap_data_sg(cmd);
                        return TCM_INVALID_CDB_FIELD;
                }
 
@@ -972,7 +951,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
                pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
                       page, subpage);
 
-       transport_kunmap_data_sg(cmd);
        return TCM_UNKNOWN_MODE_PAGE;
 
 set_length:
@@ -981,12 +959,12 @@ set_length:
        else
                buf[0] = length - 1;
 
-       if (buf != map_buf) {
-               memcpy(map_buf, buf, cmd->data_length);
-               kfree(buf);
+       rbuf = transport_kmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length));
+               transport_kunmap_data_sg(cmd);
        }
 
-       transport_kunmap_data_sg(cmd);
        target_complete_cmd(cmd, GOOD);
        return 0;
 }
index c23c76ccef65aa1da973fd2869389a72774daacc..bd587b70661a0ce11f6aaab596f4e46c6ee14c7e 100644 (file)
@@ -541,9 +541,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
 
 void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
-       if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
-               transport_lun_remove_cmd(cmd);
-
        if (transport_cmd_check_stop_to_fabric(cmd))
                return;
        if (remove)
@@ -1396,6 +1393,8 @@ 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_cmd_check_stop_to_fabric(se_cmd);
 }
 
 /**
@@ -1688,6 +1687,7 @@ void target_execute_cmd(struct se_cmd *cmd)
        }
 
        cmd->t_state = TRANSPORT_PROCESSING;
+       cmd->transport_state |= CMD_T_ACTIVE;
        spin_unlock_irq(&cmd->t_state_lock);
 
        if (!target_handle_task_attr(cmd))
@@ -2597,6 +2597,16 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
         * SENSE KEY values from include/scsi/scsi.h
         */
        switch (reason) {
+       case TCM_NO_SENSE:
+               /* CURRENT ERROR */
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* Not Ready */
+               buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
+               /* NO ADDITIONAL SENSE INFORMATION */
+               buffer[SPC_ASC_KEY_OFFSET] = 0;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0;
+               break;
        case TCM_NON_EXISTENT_LUN:
                /* CURRENT ERROR */
                buffer[0] = 0x70;
@@ -2743,7 +2753,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
                /* ILLEGAL REQUEST */
                buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT COMMUNICATION FAILURE */
-               buffer[SPC_ASC_KEY_OFFSET] = 0x80;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x08;
                break;
        }
        /*
@@ -2804,6 +2814,8 @@ void transport_send_task_abort(struct se_cmd *cmd)
        }
        cmd->scsi_status = SAM_STAT_TASK_ABORTED;
 
+       transport_lun_remove_cmd(cmd);
+
        pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x,"
                " ITT: 0x%08x\n", cmd->t_task_cdb[0],
                cmd->se_tfo->get_task_tag(cmd));
index 12d6fa21e5e19b68631dbf5b2d70f98f7cfbf864..6659dd36e806519af35acb47d3a85cf665bd4a38 100644 (file)
@@ -355,11 +355,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
 
        tport = ft_tport_create(rdata->local_port);
        if (!tport)
-               return 0;       /* not a target for this local port */
+               goto not_target;        /* not a target for this local port */
 
        acl = ft_acl_get(tport->tpg, rdata);
        if (!acl)
-               return 0;
+               goto not_target;        /* no target for this remote */
 
        if (!rspp)
                goto fill;
@@ -396,12 +396,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
 
        /*
         * OR in our service parameters with other provider (initiator), if any.
-        * TBD XXX - indicate RETRY capability?
         */
 fill:
        fcp_parm = ntohl(spp->spp_params);
+       fcp_parm &= ~FCP_SPPF_RETRY;
        spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN);
        return FC_SPP_RESP_ACK;
+
+not_target:
+       fcp_parm = ntohl(spp->spp_params);
+       fcp_parm &= ~FCP_SPPF_TARG_FCN;
+       spp->spp_params = htonl(fcp_parm);
+       return 0;
 }
 
 /**
index 7772d160376930ef417da581fc92482d93c01aec..224751e9f5ff3659448796da7d5323ec738f0770 100644 (file)
@@ -832,7 +832,7 @@ static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
        return (struct exynos_tmu_platform_data *)
                        platform_get_device_id(pdev)->driver_data;
 }
-static int __devinit exynos_tmu_probe(struct platform_device *pdev)
+static int exynos_tmu_probe(struct platform_device *pdev)
 {
        struct exynos_tmu_data *data;
        struct exynos_tmu_platform_data *pdata = pdev->dev.platform_data;
@@ -937,7 +937,7 @@ err_clk:
        return ret;
 }
 
-static int __devexit exynos_tmu_remove(struct platform_device *pdev)
+static int exynos_tmu_remove(struct platform_device *pdev)
 {
        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 
@@ -985,7 +985,7 @@ static struct platform_driver exynos_tmu_driver = {
                .of_match_table = exynos_tmu_match,
        },
        .probe = exynos_tmu_probe,
-       .remove = __devexit_p(exynos_tmu_remove),
+       .remove = exynos_tmu_remove,
        .id_table = exynos_tmu_driver_ids,
 };
 
index be6a373601b783677b876a512854edcfb28f3732..79ff3a5e925d6fdc252c6aa6d2f066e959e4637f 100644 (file)
@@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
                return pty_get_pktmode(tty, (int __user *)arg);
        case TIOCSIG:    /* Send signal to other side of pty */
                return pty_signal(tty, (int) arg);
+       case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */
+               return -EINVAL;
        }
        return -ENOIOCTLCMD;
 }
index d085e3a8ec0644bc9760caa0aed026533905c2a4..f9320437a64971c605b3e153d2a8aa4b160155bf 100644 (file)
@@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = {
                                  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
                .flags          = UART_CAP_FIFO,
        },
+       [PORT_BRCM_TRUMANAGE] = {
+               .name           = "TruManage",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1024,
+               .flags          = UART_CAP_HFIFO,
+       },
        [PORT_8250_CIR] = {
                .name           = "CIR port"
        }
@@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up)
                port->icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
+               if (up->capabilities & UART_CAP_HFIFO) {
+                       if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
+                           BOTH_EMPTY)
+                               break;
+               }
        } while (--count > 0);
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
index 3b4ea84898c2e719dc233ecddde63dc3c421bd0d..12caa1292b75c20b3d8221d4576a6f97c69db3d4 100644 (file)
@@ -40,6 +40,7 @@ struct serial8250_config {
 #define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
 #define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
 #define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
+#define UART_CAP_HFIFO (1 << 14)       /* UART has a "hidden" FIFO */
 
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
index 1d0dba2d562d27bb72a3e91f2273176c4cd67f41..096d2ef48b32f6b62abfe5c220a44440545fb0b4 100644 (file)
@@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p)
        } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
                /* Clear the USR and write the LCR again. */
                (void)p->serial_in(p, UART_USR);
-               p->serial_out(p, d->last_lcr, UART_LCR);
+               p->serial_out(p, UART_LCR, d->last_lcr);
 
                return 1;
        }
index 26b9dc012ed0b64ec1f1b3807b573af0f5f82b91..a27a98e1b0667fc8bfd7e379eaaaa1cfa6c9229a 100644 (file)
@@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv,
        return setup_port(priv, port, 2, idx * 8, 0);
 }
 
+static int
+pci_brcm_trumanage_setup(struct serial_private *priv,
+                        const struct pciserial_board *board,
+                        struct uart_8250_port *port, int idx)
+{
+       int ret = pci_default_setup(priv, board, port, idx);
+
+       port->port.type = PORT_BRCM_TRUMANAGE;
+       port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+       return ret;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
                        const struct pciserial_board *board,
                        struct uart_8250_port *port, int idx)
@@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
 #define PCI_VENDOR_ID_AGESTAR          0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375     0x6872
 #define PCI_VENDOR_ID_ASIX             0x9710
-#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
 #define PCI_DEVICE_ID_COMMTECH_4224PCIE        0x0020
 #define PCI_DEVICE_ID_COMMTECH_4228PCIE        0x0021
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE        0x0022
+#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
@@ -1953,6 +1966,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_xr17v35x_setup,
        },
+       /*
+        * Broadcom TruManage (NetXtreme)
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_BROADCOM,
+               .device         = PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_brcm_trumanage_setup,
+       },
+
        /*
         * Default "match everything" terminator entry
         */
@@ -2148,6 +2172,7 @@ enum pci_board_num_t {
        pbn_ce4100_1_115200,
        pbn_omegapci,
        pbn_NETMOS9900_2s_115200,
+       pbn_brcm_trumanage,
 };
 
 /*
@@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = {
 
        [pbn_b0_8_1152000_200] = {
                .flags          = FL_BASE0,
-               .num_ports      = 2,
+               .num_ports      = 8,
                .base_baud      = 1152000,
                .uart_offset    = 0x200,
        },
@@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = {
                .num_ports      = 2,
                .base_baud      = 115200,
        },
+       [pbn_brcm_trumanage] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .reg_shift      = 2,
+               .base_baud      = 115200,
+       },
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -4470,6 +4501,13 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_omegapci },
 
+       /*
+        * Broadcom TruManage
+        */
+       {       PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_brcm_trumanage },
+
        /*
         * AgeStar as-prs2-009
         */
index 675d94ab0aff63f97de2f52e7da565b8e5309013..8cb6d8d66a1362b1b2f5566a875c1f56248a3b29 100644 (file)
@@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port)
 
        clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
        mrdy_set_low(ifx_dev);
+       del_timer(&ifx_dev->spi_timer);
        clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
        tasklet_kill(&ifx_dev->io_work_tasklet);
 }
@@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data)
                ifx_dev->spi_xfer.cs_change = 0;
                ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz;
                /* ifx_dev->spi_xfer.speed_hz = 390625; */
-               ifx_dev->spi_xfer.bits_per_word = spi_bpw;
+               ifx_dev->spi_xfer.bits_per_word =
+                       ifx_dev->spi_dev->bits_per_word;
 
                ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
                ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
index 6db23b035efe0766dcc99e8bddb0a301dd458217..e55615eb34ad32037cf78dc18aef63a00373e1ee 100644 (file)
@@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s)
        struct circ_buf *xmit = &s->port.state->xmit;
 
        if (auart_dma_enabled(s)) {
-               int i = 0;
+               u32 i = 0;
                int size;
                void *buffer = s->tx_dma_buf;
 
@@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
 
        u32 ctrl = readl(u->membase + AUART_CTRL2);
 
-       ctrl &= ~AUART_CTRL2_RTSEN;
+       ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
        if (mctrl & TIOCM_RTS) {
                if (tty_port_cts_enabled(&u->state->port))
                        ctrl |= AUART_CTRL2_RTSEN;
+               else
+                       ctrl |= AUART_CTRL2_RTS;
        }
 
        s->ctrl = mctrl;
index 12e5249d053e79b8d15991daf27614755c03c3bf..e514b3a4dc572069da4df72cba488f6be9cd1c98 100644 (file)
@@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
 
        ucon &= ucon_mask;
        wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
-       wr_regl(port, S3C2410_ULCON, cfg->ulcon);
 
        /* reset both fifos */
        wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
index 8fd181436a6ba246e2247c5be871ac7f3c71c760..d5ed9f61300562c8febbb8a8095304a1c9955899 100644 (file)
@@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 
        vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
-       if (vt8500_port->clk) {
+       if (!IS_ERR(vt8500_port->clk)) {
                vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
        } else {
                /* use the default of 24Mhz if not specified and warn */
index b3c4a250ff86c6ad71b0e91de5cf02892a9d62a2..40e5b3919e279ee771e9c99603b119bf175492c3 100644 (file)
@@ -15,6 +15,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
index 4c90b510d0160c246f1fd5c6c280a88d091c80f8..640ae6c6d2d2ae67f504cb72582c40a8e85c9216 100644 (file)
@@ -37,6 +37,7 @@ config USB_ARCH_HAS_EHCI
        default y if ARCH_W90X900
        default y if ARCH_AT91
        default y if ARCH_MXC
+       default y if ARCH_MXS
        default y if ARCH_OMAP3
        default y if ARCH_CNS3XXX
        default y if ARCH_VT8500
index caecad9213f5cf14f3ef45827548c77e0648dfb9..8e9d31277c436ecce3fdd61ccb78031148a3e53e 100644 (file)
@@ -70,6 +70,9 @@ static int host_start(struct ci13xxx *ci)
        else
                ci->hcd = hcd;
 
+       if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
+               hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
        return ret;
 }
 
index 8d809a811e169fac9ece6259c542c17c4b16f907..2d92cce260d7fd646d13d69e01f2152bbd43a487 100644 (file)
@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
        .driver_info = NO_UNION_NORMAL,
        },
+       { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */
+       .driver_info = NO_UNION_NORMAL,
+       },
        { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
        .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
        },
index 4225d5e721312a6ec87a96352d05c7db8a682593..8e64adf8e4d56de0409909dd143e9de52f4fefb0 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd)
        return retval;
 }
 
+/*
+ * usb_hcd_start_port_resume - a root-hub port is sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal is
+ * being sent to a root-hub port.  The root hub will be prevented from
+ * going into autosuspend until usb_hcd_end_port_resume() is called.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum)
+{
+       unsigned bit = 1 << portnum;
+
+       if (!(bus->resuming_ports & bit)) {
+               bus->resuming_ports |= bit;
+               pm_runtime_get_noresume(&bus->root_hub->dev);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume);
+
+/*
+ * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal has
+ * stopped being sent to a root-hub port.  The root hub will be allowed to
+ * autosuspend again.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum)
+{
+       unsigned bit = 1 << portnum;
+
+       if (bus->resuming_ports & bit) {
+               bus->resuming_ports &= ~bit;
+               pm_runtime_put_noidle(&bus->root_hub->dev);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
 
 /*-------------------------------------------------------------------------*/
 
index a815fd2cc5e729287fe24b8a4b9bb4fc21082d6b..cbf7168e3ce7062c7610e1dfe0c13b6e49f9ff86 100644 (file)
@@ -877,6 +877,60 @@ static int hub_hub_status(struct usb_hub *hub,
        return ret;
 }
 
+static int hub_set_port_link_state(struct usb_hub *hub, int port1,
+                       unsigned int link_status)
+{
+       return set_port_feature(hub->hdev,
+                       port1 | (link_status << 3),
+                       USB_PORT_FEAT_LINK_STATE);
+}
+
+/*
+ * If USB 3.0 ports are placed into the Disabled state, they will no longer
+ * detect any device connects or disconnects.  This is generally not what the
+ * USB core wants, since it expects a disabled port to produce a port status
+ * change event when a new device connects.
+ *
+ * Instead, set the link state to Disabled, wait for the link to settle into
+ * that state, clear any change bits, and then put the port into the RxDetect
+ * state.
+ */
+static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
+{
+       int ret;
+       int total_time;
+       u16 portchange, portstatus;
+
+       if (!hub_is_superspeed(hub->hdev))
+               return -EINVAL;
+
+       ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
+       if (ret) {
+               dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+                               port1, ret);
+               return ret;
+       }
+
+       /* Wait for the link to enter the disabled state. */
+       for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
+               ret = hub_port_status(hub, port1, &portstatus, &portchange);
+               if (ret < 0)
+                       return ret;
+
+               if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+                               USB_SS_PORT_LS_SS_DISABLED)
+                       break;
+               if (total_time >= HUB_DEBOUNCE_TIMEOUT)
+                       break;
+               msleep(HUB_DEBOUNCE_STEP);
+       }
+       if (total_time >= HUB_DEBOUNCE_TIMEOUT)
+               dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n",
+                               port1, total_time);
+
+       return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);
+}
+
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 {
        struct usb_device *hdev = hub->hdev;
@@ -885,8 +939,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
        if (hub->ports[port1 - 1]->child && set_state)
                usb_set_device_state(hub->ports[port1 - 1]->child,
                                USB_STATE_NOTATTACHED);
-       if (!hub->error && !hub_is_superspeed(hub->hdev))
-               ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+       if (!hub->error) {
+               if (hub_is_superspeed(hub->hdev))
+                       ret = hub_usb3_port_disable(hub, port1);
+               else
+                       ret = clear_port_feature(hdev, port1,
+                                       USB_PORT_FEAT_ENABLE);
+       }
        if (ret)
                dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
                                port1, ret);
@@ -2440,7 +2499,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 #define HUB_SHORT_RESET_TIME   10
 #define HUB_BH_RESET_TIME      50
 #define HUB_LONG_RESET_TIME    200
-#define HUB_RESET_TIMEOUT      500
+#define HUB_RESET_TIMEOUT      800
 
 static int hub_port_reset(struct usb_hub *hub, int port1,
                        struct usb_device *udev, unsigned int delay, bool warm);
@@ -2475,6 +2534,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                if (ret < 0)
                        return ret;
 
+               /* The port state is unknown until the reset completes. */
+               if ((portstatus & USB_PORT_STAT_RESET))
+                       goto delay;
+
                /*
                 * Some buggy devices require a warm reset to be issued even
                 * when the port appears not to be connected.
@@ -2520,11 +2583,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                        if ((portchange & USB_PORT_STAT_C_CONNECTION))
                                return -ENOTCONN;
 
-                       /* if we`ve finished resetting, then break out of
-                        * the loop
-                        */
-                       if (!(portstatus & USB_PORT_STAT_RESET) &&
-                           (portstatus & USB_PORT_STAT_ENABLE)) {
+                       if ((portstatus & USB_PORT_STAT_ENABLE)) {
                                if (hub_is_wusb(hub))
                                        udev->speed = USB_SPEED_WIRELESS;
                                else if (hub_is_superspeed(hub->hdev))
@@ -2538,10 +2597,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                                return 0;
                        }
                } else {
-                       if (portchange & USB_PORT_STAT_C_BH_RESET)
-                               return 0;
+                       if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
+                                       hub_port_warm_reset_required(hub,
+                                               portstatus))
+                               return -ENOTCONN;
+
+                       return 0;
                }
 
+delay:
                /* switch to the long delay after two short delay failures */
                if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
                        delay = HUB_LONG_RESET_TIME;
@@ -2565,14 +2629,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1,
                        msleep(10 + 40);
                        update_devnum(udev, 0);
                        hcd = bus_to_hcd(udev->bus);
-                       if (hcd->driver->reset_device) {
-                               *status = hcd->driver->reset_device(hcd, udev);
-                               if (*status < 0) {
-                                       dev_err(&udev->dev, "Cannot reset "
-                                                       "HCD device state\n");
-                                       break;
-                               }
-                       }
+                       /* The xHC may think the device is already reset,
+                        * so ignore the status.
+                        */
+                       if (hcd->driver->reset_device)
+                               hcd->driver->reset_device(hcd, udev);
                }
                /* FALL THROUGH */
        case -ENOTCONN:
@@ -2580,16 +2641,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1,
                clear_port_feature(hub->hdev,
                                port1, USB_PORT_FEAT_C_RESET);
                /* FIXME need disconnect() for NOTATTACHED device */
-               if (warm) {
+               if (hub_is_superspeed(hub->hdev)) {
                        clear_port_feature(hub->hdev, port1,
                                        USB_PORT_FEAT_C_BH_PORT_RESET);
                        clear_port_feature(hub->hdev, port1,
                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
-               } else {
+               }
+               if (!warm)
                        usb_set_device_state(udev, *status
                                        ? USB_STATE_NOTATTACHED
                                        : USB_STATE_DEFAULT);
-               }
                break;
        }
 }
@@ -2777,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev)
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
 
 #ifdef CONFIG_USB_SUSPEND
+/*
+ * usb_disable_function_remotewakeup - disable usb3.0
+ * device's function remote wakeup
+ * @udev: target device
+ *
+ * Assume there's only one function on the USB 3.0
+ * device and disable remote wake for the first
+ * interface. FIXME if the interface association
+ * descriptor shows there's more than one function.
+ */
+static int usb_disable_function_remotewakeup(struct usb_device *udev)
+{
+       return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
+                               USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+}
 
 /*
  * usb_port_suspend - suspend a usb device's upstream port
@@ -2894,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
                /* paranoia:  "should not happen" */
-               if (udev->do_remote_wakeup)
-                       (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                               USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
-                               USB_DEVICE_REMOTE_WAKEUP, 0,
-                               NULL, 0,
-                               USB_CTRL_SET_TIMEOUT);
+               if (udev->do_remote_wakeup) {
+                       if (!hub_is_superspeed(hub->hdev)) {
+                               (void) usb_control_msg(udev,
+                                               usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
+                                               USB_RECIP_DEVICE,
+                                               USB_DEVICE_REMOTE_WAKEUP, 0,
+                                               NULL, 0,
+                                               USB_CTRL_SET_TIMEOUT);
+                       } else
+                               (void) usb_disable_function_remotewakeup(udev);
+
+               }
 
                /* Try to enable USB2 hardware LPM again */
                if (udev->usb2_hw_lpm_capable == 1)
@@ -2939,7 +3024,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 static int finish_port_resume(struct usb_device *udev)
 {
        int     status = 0;
-       u16     devstatus;
+       u16     devstatus = 0;
 
        /* caller owns the udev device lock */
        dev_dbg(&udev->dev, "%s\n",
@@ -2984,21 +3069,37 @@ static int finish_port_resume(struct usb_device *udev)
        if (status) {
                dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
                                status);
-       } else if (udev->actconfig) {
-               le16_to_cpus(&devstatus);
-               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
-                       status = usb_control_msg(udev,
-                                       usb_sndctrlpipe(udev, 0),
-                                       USB_REQ_CLEAR_FEATURE,
+       /*
+        * There are a few quirky devices which violate the standard
+        * by claiming to have remote wakeup enabled after a reset,
+        * which crash if the feature is cleared, hence check for
+        * udev->reset_resume
+        */
+       } else if (udev->actconfig && !udev->reset_resume) {
+               if (!hub_is_superspeed(udev->parent)) {
+                       le16_to_cpus(&devstatus);
+                       if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+                               status = usb_control_msg(udev,
+                                               usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
                                                USB_RECIP_DEVICE,
-                                       USB_DEVICE_REMOTE_WAKEUP, 0,
-                                       NULL, 0,
-                                       USB_CTRL_SET_TIMEOUT);
-                       if (status)
-                               dev_dbg(&udev->dev,
-                                       "disable remote wakeup, status %d\n",
-                                       status);
+                                               USB_DEVICE_REMOTE_WAKEUP, 0,
+                                               NULL, 0,
+                                               USB_CTRL_SET_TIMEOUT);
+               } else {
+                       status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
+                                       &devstatus);
+                       le16_to_cpus(&devstatus);
+                       if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
+                                       | USB_INTRF_STAT_FUNC_RW))
+                               status =
+                                       usb_disable_function_remotewakeup(udev);
                }
+
+               if (status)
+                       dev_dbg(&udev->dev,
+                               "disable remote wakeup, status %d\n",
+                               status);
                status = 0;
        }
        return status;
@@ -4638,9 +4739,14 @@ static void hub_events(void)
                         * SS.Inactive state.
                         */
                        if (hub_port_warm_reset_required(hub, portstatus)) {
+                               int status;
+
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
-                               hub_port_reset(hub, i, NULL,
+                               status = hub_port_reset(hub, i, NULL,
                                                HUB_BH_RESET_TIME, true);
+                               if (status < 0)
+                                       hub_port_disable(hub, i, 1);
+                               connect_change = 0;
                        }
 
                        if (connect_change)
index fdefd9c7f7af089e54428b57625d394c70566561..3113c1d71442953d3f9659afff042064bca8a9b9 100644 (file)
@@ -43,6 +43,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Creative SB Audigy 2 NX */
        { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Microsoft LifeCam-VX700 v2.0 */
+       { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Quickcam Fusion */
        { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
index 92604b4f9712630e83898c83df01b985e8b5a631..5945aadaa1c99a41df4edff373bbfbad080e34fe 100644 (file)
@@ -56,7 +56,7 @@
 #define dump_register(nm)                              \
 {                                                      \
        .name   = __stringify(nm),                      \
-       .offset = DWC3_ ##nm,                           \
+       .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
 }
 
 static const struct debugfs_reg32 dwc3_regs[] = {
index 2e43b332aae8b891a5d0e0988172791e4b7a1f88..2fdd767f8fe890defe831c958d1d723af4b060ae 100644 (file)
@@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 
                if (epnum == 0 || epnum == 1) {
                        dep->endpoint.maxpacket = 512;
+                       dep->endpoint.maxburst = 1;
                        dep->endpoint.ops = &dwc3_gadget_ep0_ops;
                        if (!epnum)
                                dwc->gadget.ep0 = &dep->endpoint;
index fc0ec5e0d58ef43a11f525148dca69d1cb442188..d9f6b9372491d487a817de021f8bfc660d04cd00 100644 (file)
@@ -3231,7 +3231,7 @@ static int udc_pci_probe(
        }
 
        if (!pdev->irq) {
-               dev_err(&dev->pdev->dev, "irq not set\n");
+               dev_err(&pdev->dev, "irq not set\n");
                kfree(dev);
                dev = NULL;
                retval = -ENODEV;
@@ -3250,7 +3250,7 @@ static int udc_pci_probe(
        dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
 
        if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
-               dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
+               dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
                kfree(dev);
                dev = NULL;
                retval = -EBUSY;
index 95d584dbed13b08516f23d90d83acb973d989a3a..8cf0c0f6fa1fb83bab5f26ab4d54a24e7bda3875 100644 (file)
@@ -130,10 +130,7 @@ static const char ep0name[] = "ep0";
 static const char *const ep_name[] = {
        ep0name,                                /* everyone has ep0 */
 
-       /* act like a net2280: high speed, six configurable endpoints */
-       "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f",
-
-       /* or like pxa250: fifteen fixed function endpoints */
+       /* act like a pxa250: fifteen fixed function endpoints */
        "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
        "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
        "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
@@ -141,6 +138,10 @@ static const char *const ep_name[] = {
 
        /* or like sa1100: two fixed function endpoints */
        "ep1out-bulk", "ep2in-bulk",
+
+       /* and now some generic EPs so we have enough in multi config */
+       "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
+       "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
 };
 #define DUMMY_ENDPOINTS        ARRAY_SIZE(ep_name)
 
index 4a6961c517f261103f006259bab366265dde7e4c..8c2f251211491258c2c83396b558132444e7ec9d 100644 (file)
@@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
                                        pr_err("%s: unmapped value: %lu\n", opts, value);
                                        return -EINVAL;
                                }
-                       }
-                       else if (!memcmp(opts, "gid", 3))
+                       } else if (!memcmp(opts, "gid", 3)) {
                                data->perms.gid = make_kgid(current_user_ns(), value);
                                if (!gid_valid(data->perms.gid)) {
                                        pr_err("%s: unmapped value: %lu\n", opts, value);
                                        return -EINVAL;
                                }
-                       else
+                       } else {
                                goto invalid;
+                       }
                        break;
 
                default:
index 1b0f086426bd92648b5b6ad0e743c2530601a2c2..d3bd7b095ba37713dfc3bdf1faaa39ddded393ac 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
-
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;
 
 /* workaround ENGcm09152 for i.MX35 */
-#define USBPHYCTRL_OTGBASE_OFFSET      0x608
+#define MX35_USBPHYCTRL_OFFSET         0x600
+#define USBPHYCTRL_OTGBASE_OFFSET      0x8
 #define USBPHYCTRL_EVDO                        (1 << 23)
 
 int fsl_udc_clk_init(struct platform_device *pdev)
@@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
        clk_prepare_enable(mxc_per_clk);
 
        /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-       if (!cpu_is_mx51()) {
+       if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) {
                freq = clk_get_rate(mxc_per_clk);
                if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
                    (freq < 59999000 || freq > 60001000)) {
@@ -79,27 +78,40 @@ eclkrate:
        return ret;
 }
 
-void fsl_udc_clk_finalize(struct platform_device *pdev)
+int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-       if (cpu_is_mx35()) {
-               unsigned int v;
+       int ret = 0;
 
-               /* workaround ENGcm09152 for i.MX35 */
-               if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-                       v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                       USBPHYCTRL_OTGBASE_OFFSET));
-                       writel(v | USBPHYCTRL_EVDO,
-                               MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                       USBPHYCTRL_OTGBASE_OFFSET));
+       /* workaround ENGcm09152 for i.MX35 */
+       if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+               unsigned int v;
+               struct resource *res = platform_get_resource
+                       (pdev, IORESOURCE_MEM, 0);
+               void __iomem *phy_regs = ioremap(res->start +
+                                               MX35_USBPHYCTRL_OFFSET, 512);
+               if (!phy_regs) {
+                       dev_err(&pdev->dev, "ioremap for phy address fails\n");
+                       ret = -EINVAL;
+                       goto ioremap_err;
                }
+
+               v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+               writel(v | USBPHYCTRL_EVDO,
+                       phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+
+               iounmap(phy_regs);
        }
 
+
+ioremap_err:
        /* ULPI transceivers don't need usbpll */
        if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
                clk_disable_unprepare(mxc_per_clk);
                mxc_per_clk = NULL;
        }
+
+       return ret;
 }
 
 void fsl_udc_clk_release(void)
index c19f7f13790bf5be541b5e854beab49c969443ef..667275cb7bad2fba361bc305348c5536f5116f93 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/fsl_devices.h>
 #include <linux/dmapool.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
        unsigned int i;
        u32 dccparams;
 
-       if (strcmp(pdev->name, driver_name)) {
-               VDBG("Wrong device");
-               return -ENODEV;
-       }
-
        udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
        if (udc_controller == NULL) {
                ERR("malloc udc failed\n");
@@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
                dr_controller_setup(udc_controller);
        }
 
-       fsl_udc_clk_finalize(pdev);
+       ret = fsl_udc_clk_finalize(pdev);
+       if (ret)
+               goto err_free_irq;
 
        /* Setup gadget structure */
        udc_controller->gadget.ops = &fsl_gadget_ops;
@@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev)
 
        return fsl_udc_resume(NULL);
 }
-
 /*-------------------------------------------------------------------------
        Register entry point for the peripheral controller driver
 --------------------------------------------------------------------------*/
-
+static const struct platform_device_id fsl_udc_devtype[] = {
+       {
+               .name = "imx-udc-mx27",
+       }, {
+               .name = "imx-udc-mx51",
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
 static struct platform_driver udc_driver = {
-       .remove  = __exit_p(fsl_udc_remove),
+       .remove         = __exit_p(fsl_udc_remove),
+       /* Just for FSL i.mx SoC currently */
+       .id_table       = fsl_udc_devtype,
        /* these suspend and resume are not usb suspend and resume */
-       .suspend = fsl_udc_suspend,
-       .resume  = fsl_udc_resume,
-       .driver  = {
-               .name = (char *)driver_name,
-               .owner = THIS_MODULE,
-               /* udc suspend/resume called from OTG driver */
-               .suspend = fsl_udc_otg_suspend,
-               .resume  = fsl_udc_otg_resume,
+       .suspend        = fsl_udc_suspend,
+       .resume         = fsl_udc_resume,
+       .driver         = {
+                       .name = (char *)driver_name,
+                       .owner = THIS_MODULE,
+                       /* udc suspend/resume called from OTG driver */
+                       .suspend = fsl_udc_otg_suspend,
+                       .resume  = fsl_udc_otg_resume,
        },
 };
 
index f61a967f70828dd21c7c7e401388610e6b62ce74..c6703bb07b23fcd026f450a581cf974a218013ad 100644 (file)
@@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep)
 struct platform_device;
 #ifdef CONFIG_ARCH_MXC
 int fsl_udc_clk_init(struct platform_device *pdev);
-void fsl_udc_clk_finalize(struct platform_device *pdev);
+int fsl_udc_clk_finalize(struct platform_device *pdev);
 void fsl_udc_clk_release(void);
 #else
 static inline int fsl_udc_clk_init(struct platform_device *pdev)
 {
        return 0;
 }
-static inline void fsl_udc_clk_finalize(struct platform_device *pdev)
+static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
+       return 0;
 }
 static inline void fsl_udc_clk_release(void)
 {
index 379aac7b82fcf62d57b5ef41e1054c2b22e8ae71..6e8b1272ebceb3e1317e092ae7243e584c6eeda4 100644 (file)
@@ -1012,7 +1012,7 @@ static void udc_clock_enable(struct mv_udc *udc)
        unsigned int i;
 
        for (i = 0; i < udc->clknum; i++)
-               clk_enable(udc->clk[i]);
+               clk_prepare_enable(udc->clk[i]);
 }
 
 static void udc_clock_disable(struct mv_udc *udc)
@@ -1020,7 +1020,7 @@ static void udc_clock_disable(struct mv_udc *udc)
        unsigned int i;
 
        for (i = 0; i < udc->clknum; i++)
-               clk_disable(udc->clk[i]);
+               clk_disable_unprepare(udc->clk[i]);
 }
 
 static void udc_stop(struct mv_udc *udc)
index 141971d9051eab7d16dca79f0e652917171336e9..439c3f972f8c28d18fb34c691ab9cf8b51559098 100644 (file)
@@ -3477,12 +3477,11 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 /**
  * s3c_hsotg_release - release callback for hsotg device
  * @dev: Device to for which release is called
+ *
+ * Nothing to do as the resource is allocated using devm_ API.
  */
 static void s3c_hsotg_release(struct device *dev)
 {
-       struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
-
-       kfree(hsotg);
 }
 
 /**
index 4f7f76f00c7452239067a5b5498a500d26093f50..7cacd6ae818e3ef957efe728eeb9641ccbf42071 100644 (file)
@@ -1794,9 +1794,10 @@ static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
        tpg->tpg_nexus = NULL;
 
        kfree(tv_nexus);
+       ret = 0;
 out:
        mutex_unlock(&tpg->tpg_mutex);
-       return 0;
+       return ret;
 }
 
 static ssize_t tcm_usbg_tpg_store_nexus(
index d0f95482f40e8058a24f27b161f33beb55bb3c4d..598dcc1212f0bb231830f0022961f67e37b6b0fa 100644 (file)
@@ -887,7 +887,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
                        port->port_num, tty, file);
 
-       wake_up_interruptible(&port->port.close_wait);
+       wake_up(&port->port.close_wait);
 exit:
        spin_unlock_irq(&port->port_lock);
 }
index d6bb128ce21ee424a02dfb7db31c96bc88c9af44..3a21c5d683c04f0380aa1606045b35375d26143c 100644 (file)
@@ -148,7 +148,7 @@ config USB_EHCI_FSL
          Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_MXC
-       bool "Support for Freescale i.MX on-chip EHCI USB controller"
+       tristate "Support for Freescale i.MX on-chip EHCI USB controller"
        depends on USB_EHCI_HCD && ARCH_MXC
        select USB_EHCI_ROOT_HUB_TT
        ---help---
index 1eb4c3006e9eab8b7d2588c0322d38b9ad724327..001fbff2fdefedbb346f71db705f8e687201e454 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI)             += pci-quirks.o
 obj-$(CONFIG_USB_EHCI_HCD)     += ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)     += ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)    += ehci-platform.o
+obj-$(CONFIG_USB_EHCI_MXC)     += ehci-mxc.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)  += isp116x-hcd.o
index fd9b5424b860a20e7d04c54fe3cf4fc76ca3be2d..d81d2fcbff1894d79f0606d831d91b628c44f71e 100644 (file)
@@ -230,7 +230,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 
        switch (phy_mode) {
        case FSL_USB2_PHY_ULPI:
-               if (pdata->controller_ver) {
+               if (pdata->have_sysif_regs && pdata->controller_ver) {
                        /* controller version 1.6 or above */
                        setbits32(non_ehci + FSL_SOC_USB_CTRL,
                                        ULPI_PHY_CLK_SEL);
@@ -251,7 +251,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
                portsc |= PORT_PTS_PTW;
                /* fall through */
        case FSL_USB2_PHY_UTMI:
-               if (pdata->controller_ver) {
+               if (pdata->have_sysif_regs && pdata->controller_ver) {
                        /* controller version 1.6 or above */
                        setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
                        mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
@@ -267,7 +267,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
                break;
        }
 
-       if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
+       if (pdata->have_sysif_regs && pdata->controller_ver &&
+           (phy_mode == FSL_USB2_PHY_ULPI)) {
                /* check PHY_CLK_VALID to get phy clk valid */
                if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
                                PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
@@ -278,7 +279,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 
        ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 
-       if (phy_mode != FSL_USB2_PHY_ULPI)
+       if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
                setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
 
        return 0;
index c97503bb0b0e064a027575f9eb0d28094d3fda80..b416a3fc99594f30afbb15995191313f6c9315a6 100644 (file)
@@ -74,10 +74,6 @@ static const char    hcd_name [] = "ehci_hcd";
 #undef VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
-#ifdef DEBUG
-#define EHCI_STATS
-#endif
-
 /* magic numbers that can affect system performance */
 #define        EHCI_TUNE_CERR          3       /* 0-3 qtd retries; 0 == don't stop */
 #define        EHCI_TUNE_RL_HS         4       /* nak throttle; see 4.9 */
@@ -801,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                        ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
                        set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+                       usb_hcd_start_port_resume(&hcd->self, i);
                        mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
                }
        }
@@ -1250,11 +1247,6 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_fsl_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MXC
-#include "ehci-mxc.c"
-#define PLATFORM_DRIVER                ehci_mxc_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
@@ -1352,7 +1344,8 @@ MODULE_LICENSE ("GPL");
 
 #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
        !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
-       !defined(CONFIG_USB_CHIPIDEA_HOST) && \
+       !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
        !defined(PLATFORM_DRIVER) && \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
        !defined(OF_PLATFORM_DRIVER) && \
index 4ccb97c0678f93fd8379af59584bd79e8b8d10ef..4d3b294f203e3acefe469db340d695786b2ffc3f 100644 (file)
@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                        status = STS_PCD;
                }
        }
-       /* FIXME autosuspend idle root hubs */
+
+       /* If a resume is in progress, make sure it can finish */
+       if (ehci->resuming_ports)
+               mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25));
+
        spin_unlock_irqrestore (&ehci->lock, flags);
        return status ? retval : 0;
 }
@@ -851,6 +855,7 @@ static int ehci_hub_control (
                                /* resume signaling for 20 msec */
                                ehci->reset_done[wIndex] = jiffies
                                                + msecs_to_jiffies(20);
+                               usb_hcd_start_port_resume(&hcd->self, wIndex);
                                /* check the port again */
                                mod_timer(&ehci_to_hcd(ehci)->rh_timer,
                                                ehci->reset_done[wIndex]);
@@ -862,6 +867,7 @@ static int ehci_hub_control (
                                clear_bit(wIndex, &ehci->suspended_ports);
                                set_bit(wIndex, &ehci->port_c_suspend);
                                ehci->reset_done[wIndex] = 0;
+                               usb_hcd_end_port_resume(&hcd->self, wIndex);
 
                                /* stop resume signaling */
                                temp = ehci_readl(ehci, status_reg);
@@ -950,6 +956,7 @@ static int ehci_hub_control (
                        ehci->reset_done[wIndex] = 0;
                        if (temp & PORT_PE)
                                set_bit(wIndex, &ehci->port_c_suspend);
+                       usb_hcd_end_port_resume(&hcd->self, wIndex);
                }
 
                if (temp & PORT_OC)
index f7bfc0b898b97a90dfece792fe40ca16ef4a2f73..6c56297ea16b8f59bd887f9025cd68ca46a2be96 100644 (file)
@@ -43,7 +43,7 @@ static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
        unsigned int i;
 
        for (i = 0; i < ehci_mv->clknum; i++)
-               clk_enable(ehci_mv->clk[i]);
+               clk_prepare_enable(ehci_mv->clk[i]);
 }
 
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
@@ -51,7 +51,7 @@ static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
        unsigned int i;
 
        for (i = 0; i < ehci_mv->clknum; i++)
-               clk_disable(ehci_mv->clk[i]);
+               clk_disable_unprepare(ehci_mv->clk[i]);
 }
 
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
index ec7f5d2c90de3464f66a000583fa151fde29946e..dedb80bb8d40a5c37132fbdb0d0c569534aeb9c8 100644 (file)
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include <linux/platform_data/usb-ehci-mxc.h>
 
 #include <asm/mach-types.h>
 
+#include "ehci.h"
+
+#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
+
+static const char hcd_name[] = "ehci-mxc";
+
 #define ULPI_VIEWPORT_OFFSET   0x170
 
 struct ehci_mxc_priv {
        struct clk *usbclk, *ahbclk, *phyclk;
-       struct usb_hcd *hcd;
 };
 
-/* called during probe() after chip reset completes */
-static int ehci_mxc_setup(struct usb_hcd *hcd)
-{
-       hcd->has_tt = 1;
-
-       return ehci_setup(hcd);
-}
+static struct hc_driver __read_mostly ehci_mxc_hc_driver;
 
-static const struct hc_driver ehci_mxc_hc_driver = {
-       .description = hcd_name,
-       .product_desc = "Freescale On-Chip EHCI Host Controller",
-       .hcd_priv_size = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq = ehci_irq,
-       .flags = HCD_USB2 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset = ehci_mxc_setup,
-       .start = ehci_run,
-       .stop = ehci_stop,
-       .shutdown = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue = ehci_urb_enqueue,
-       .urb_dequeue = ehci_urb_dequeue,
-       .endpoint_disable = ehci_endpoint_disable,
-       .endpoint_reset = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data = ehci_hub_status_data,
-       .hub_control = ehci_hub_control,
-       .bus_suspend = ehci_bus_suspend,
-       .bus_resume = ehci_bus_resume,
-       .relinquish_port = ehci_relinquish_port,
-       .port_handed_over = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
+       .extra_priv_size =      sizeof(struct ehci_mxc_priv),
 };
 
 static int ehci_mxc_drv_probe(struct platform_device *pdev)
@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
        if (!hcd)
                return -ENOMEM;
 
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               ret = -ENOMEM;
-               goto err_alloc;
-       }
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "Found HC with no register addr. Check setup!\n");
@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
+       hcd->has_tt = 1;
+       ehci = hcd_to_ehci(hcd);
+       priv = (struct ehci_mxc_priv *) ehci->priv;
+
        /* enable clocks */
        priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(priv->usbclk)) {
@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                mdelay(10);
        }
 
-       ehci = hcd_to_ehci(hcd);
-
        /* EHCI registers start at offset 0x100 */
        ehci->caps = hcd->regs + 0x100;
        ehci->regs = hcd->regs + 0x100 +
@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                }
        }
 
-       priv->hcd = hcd;
-       platform_set_drvdata(pdev, priv);
+       platform_set_drvdata(pdev, hcd);
 
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (ret)
@@ -244,8 +202,11 @@ err_alloc:
 static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
 {
        struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
-       struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = priv->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
+
+       usb_remove_hcd(hcd);
 
        if (pdata && pdata->exit)
                pdata->exit(pdev);
@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
        if (pdata->otg)
                usb_phy_shutdown(pdata->otg);
 
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
        clk_disable_unprepare(priv->usbclk);
        clk_disable_unprepare(priv->ahbclk);
 
        if (priv->phyclk)
                clk_disable_unprepare(priv->phyclk);
 
+       usb_put_hcd(hcd);
+       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
 static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
 {
-       struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = priv->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
        if (hcd->driver->shutdown)
                hcd->driver->shutdown(hcd);
@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci");
 
 static struct platform_driver ehci_mxc_driver = {
        .probe = ehci_mxc_drv_probe,
-       .remove = __exit_p(ehci_mxc_drv_remove),
+       .remove = ehci_mxc_drv_remove,
        .shutdown = ehci_mxc_drv_shutdown,
        .driver = {
                   .name = "mxc-ehci",
        },
 };
+
+static int __init ehci_mxc_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
+       return platform_driver_register(&ehci_mxc_driver);
+}
+module_init(ehci_mxc_init);
+
+static void __exit ehci_mxc_cleanup(void)
+{
+       platform_driver_unregister(&ehci_mxc_driver);
+}
+module_exit(ehci_mxc_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Sascha Hauer");
+MODULE_LICENSE("GPL");
index a7d1f5b4c4eda4446d0fac523f72b7e068852d06..914a3ecfb5d361501a9a9e939d82388e34b795bc 100644 (file)
@@ -325,7 +325,7 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:orion-ehci");
 
-static const struct of_device_id ehci_orion_dt_ids[] __devinitdata = {
+static const struct of_device_id ehci_orion_dt_ids[] = {
        { .compatible = "marvell,orion-ehci", },
        {},
 };
index dabb20494826f1be237c9a08b6cea7569be46dd7..170b9399e09f34b42ec798b8e02985c5b0f71190 100644 (file)
@@ -200,6 +200,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        }
 
+       /* optional debug port, normally in the first BAR */
+       temp = pci_find_capability(pdev, PCI_CAP_ID_DBG);
+       if (temp) {
+               pci_read_config_dword(pdev, temp, &temp);
+               temp >>= 16;
+               if (((temp >> 13) & 7) == 1) {
+                       u32 hcs_params = ehci_readl(ehci,
+                                                   &ehci->caps->hcs_params);
+
+                       temp &= 0x1fff;
+                       ehci->debug = hcd->regs + temp;
+                       temp = ehci_readl(ehci, &ehci->debug->control);
+                       ehci_info(ehci, "debug port %d%s\n",
+                                 HCS_DEBUG_PORT(hcs_params),
+                                 (temp & DBGP_ENABLED) ? " IN USE" : "");
+                       if (!(temp & DBGP_ENABLED))
+                               ehci->debug = NULL;
+               }
+       }
+
        retval = ehci_setup(hcd);
        if (retval)
                return retval;
@@ -228,25 +248,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        }
 
-       /* optional debug port, normally in the first BAR */
-       temp = pci_find_capability(pdev, 0x0a);
-       if (temp) {
-               pci_read_config_dword(pdev, temp, &temp);
-               temp >>= 16;
-               if ((temp & (3 << 13)) == (1 << 13)) {
-                       temp &= 0x1fff;
-                       ehci->debug = hcd->regs + temp;
-                       temp = ehci_readl(ehci, &ehci->debug->control);
-                       ehci_info(ehci, "debug port %d%s\n",
-                               HCS_DEBUG_PORT(ehci->hcs_params),
-                               (temp & DBGP_ENABLED)
-                                       ? " IN USE"
-                                       : "");
-                       if (!(temp & DBGP_ENABLED))
-                               ehci->debug = NULL;
-               }
-       }
-
        /* at least the Genesys GL880S needs fixup here */
        temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
        temp &= 0x0f;
index 3d989028c8365e6644b86428fea2f24cfba9be6e..fd252f0cfb3a7873ec7bad8226a036a9668b182e 100644 (file)
@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
        if (ehci->async_iaa || ehci->async_unlinking)
                return;
 
-       /* Do all the waiting QHs at once */
-       ehci->async_iaa = ehci->async_unlink;
-       ehci->async_unlink = NULL;
-
        /* If the controller isn't running, we don't have to wait for it */
        if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+
+               /* Do all the waiting QHs */
+               ehci->async_iaa = ehci->async_unlink;
+               ehci->async_unlink = NULL;
+
                if (!nested)            /* Avoid recursion */
                        end_unlink_async(ehci);
 
        /* Otherwise start a new IAA cycle */
        } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+               struct ehci_qh          *qh;
+
+               /* Do only the first waiting QH (nVidia bug?) */
+               qh = ehci->async_unlink;
+               ehci->async_iaa = qh;
+               ehci->async_unlink = qh->unlink_next;
+               qh->unlink_next = NULL;
+
                /* Make sure the unlinks are all visible to the hardware */
                wmb();
 
@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)
        }
 }
 
+static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
 static void unlink_empty_async(struct ehci_hcd *ehci)
 {
-       struct ehci_qh          *qh, *next;
-       bool                    stopped = (ehci->rh_state < EHCI_RH_RUNNING);
+       struct ehci_qh          *qh;
+       struct ehci_qh          *qh_to_unlink = NULL;
        bool                    check_unlinks_later = false;
+       int                     count = 0;
 
-       /* Unlink all the async QHs that have been empty for a timer cycle */
-       next = ehci->async->qh_next.qh;
-       while (next) {
-               qh = next;
-               next = qh->qh_next.qh;
-
+       /* Find the last async QH which has been empty for a timer cycle */
+       for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {
                if (list_empty(&qh->qtd_list) &&
                                qh->qh_state == QH_STATE_LINKED) {
-                       if (!stopped && qh->unlink_cycle ==
-                                       ehci->async_unlink_cycle)
+                       ++count;
+                       if (qh->unlink_cycle == ehci->async_unlink_cycle)
                                check_unlinks_later = true;
                        else
-                               single_unlink_async(ehci, qh);
+                               qh_to_unlink = qh;
                }
        }
 
-       /* Start a new IAA cycle if any QHs are waiting for it */
-       if (ehci->async_unlink)
-               start_iaa_cycle(ehci, false);
+       /* If nothing else is being unlinked, unlink the last empty QH */
+       if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+               start_unlink_async(ehci, qh_to_unlink);
+               --count;
+       }
 
-       /* QHs that haven't been empty for long enough will be handled later */
-       if (check_unlinks_later) {
+       /* Other QHs will be handled later */
+       if (count > 0) {
                ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
                ++ehci->async_unlink_cycle;
        }
index 69ebee73c0c153581895dbd7860ab75024784394..b476daf49f6f3c6cf226b920f5c8ff01ca5d23aa 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 }
 
 static const unsigned char
-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
 
 /* carryover low/fullspeed bandwidth that crosses uframe boundries */
 static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
        }
        ehci->now_frame = now_frame;
 
+       frame = ehci->last_iso_frame;
        for (;;) {
                union ehci_shadow       q, *q_p;
                __hc32                  type, *hw_p;
 
-               frame = ehci->last_iso_frame;
 restart:
                /* scan each element in frame's queue for completions */
                q_p = &ehci->pshadow [frame];
@@ -2321,6 +2321,9 @@ restart:
                /* Stop when we have reached the current frame */
                if (frame == now_frame)
                        break;
-               ehci->last_iso_frame = (frame + 1) & fmask;
+
+               /* The last frame may still have active siTDs */
+               ehci->last_iso_frame = frame;
+               frame = (frame + 1) & fmask;
        }
 }
index 20dbdcbe9b0fc1fb1330da115bebb3546e45b8f2..f904071d70df2d1cb2d46710c44820ffbd3a90dc 100644 (file)
@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->ASS_poll_count++ < 20) {
-                       ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
-                       return;
-               }
-               ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
-                               want, actual);
+               /* Poll again later */
+               ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+               ++ehci->ASS_poll_count;
+               return;
        }
+
+       if (ehci->ASS_poll_count > 20)
+               ehci_dbg(ehci, "ASS poll count reached %d\n",
+                               ehci->ASS_poll_count);
        ehci->ASS_poll_count = 0;
 
        /* The status is up-to-date; restart or stop the schedule as needed */
@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->PSS_poll_count++ < 20) {
-                       ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
-                       return;
-               }
-               ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
-                               want, actual);
+               /* Poll again later */
+               ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+               return;
        }
+
+       if (ehci->PSS_poll_count > 20)
+               ehci_dbg(ehci, "PSS poll count reached %d\n",
+                               ehci->PSS_poll_count);
        ehci->PSS_poll_count = 0;
 
        /* The status is up-to-date; restart or stop the schedule as needed */
index 9dadc7118d68e13a84e793a10171a500e6d52fad..36c3a82105953ba2433d12845e7e02a293fa6d35 100644 (file)
@@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16;
 #endif
 
 /* statistics can be kept for tuning/monitoring */
+#ifdef DEBUG
+#define EHCI_STATS
+#endif
+
 struct ehci_stats {
        /* irq usage */
        unsigned long           normal;
@@ -221,6 +225,9 @@ struct ehci_hcd {                   /* one per controller */
 #ifdef DEBUG
        struct dentry           *debug_dir;
 #endif
+
+       /* platform-specific data -- must come last */
+       unsigned long           priv[0] __aligned(sizeof(s64));
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
index 5105127c1d4b3e4c3ac06953c25ac959fdc24a6c..11e0b79ff9d52a8d703c3b2134b8960768123246 100644 (file)
@@ -142,6 +142,9 @@ static int usb_get_ver_info(struct device_node *np)
                        return ver;
        }
 
+       if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr"))
+               return FSL_USB_VER_OLD;
+
        if (of_device_is_compatible(np, "fsl-usb2-mph")) {
                if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6"))
                        ver = FSL_USB_VER_1_6;
index bd6a7447ccc9efc41cd28e9a2c39b576c92fb6a3..f0ebe8e7c58b4dced4d50617b7a6235d90143cac 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #include "imx21-hcd.h"
 
index d370245a4ee22af7716983da3b48a9791251a4ff..5e3a6deb62b1e7d37b30f0f8a4f534f9e740fda9 100644 (file)
@@ -128,7 +128,8 @@ static void tmio_start_hc(struct platform_device *dev)
        tmio_iowrite8(2, tmio->ccr + CCR_INTC);
 
        dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n",
-                       tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq);
+                       tmio_ioread8(tmio->ccr + CCR_REVID),
+                       (u64) hcd->rsrc_start, hcd->irq);
 }
 
 static int ohci_tmio_start(struct usb_hcd *hcd)
index a3b6d7104ae237f17846fdd7d41f4f14fcc7e4b5..4c338ec03a07d1bfa72ceea172f07e19f151f54b 100644 (file)
@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
                                "defaulting to EHCI.\n");
                dev_warn(&xhci_pdev->dev,
                                "USB 3.0 devices will work at USB 2.0 speeds.\n");
+               usb_disable_xhci_ports(xhci_pdev);
                return;
        }
 
index 4b9e9aba26654e3f70f5801bf2ada2438a739c94..4f64d24eebc82b7927afbf1d7bace3d3eb433160 100644 (file)
@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                return IRQ_NONE;
        uhci_writew(uhci, status, USBSTS);              /* Clear it */
 
+       spin_lock(&uhci->lock);
+       if (unlikely(!uhci->is_initialized))    /* not yet configured */
+               goto done;
+
        if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
                if (status & USBSTS_HSE)
                        dev_err(uhci_dev(uhci), "host system error, "
@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                        dev_err(uhci_dev(uhci), "host controller process "
                                        "error, something bad happened!\n");
                if (status & USBSTS_HCH) {
-                       spin_lock(&uhci->lock);
                        if (uhci->rh_state >= UHCI_RH_RUNNING) {
                                dev_err(uhci_dev(uhci),
                                        "host controller halted, "
@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                                 * pending unlinks */
                                mod_timer(&hcd->rh_timer, jiffies);
                        }
-                       spin_unlock(&uhci->lock);
                }
        }
 
-       if (status & USBSTS_RD)
+       if (status & USBSTS_RD) {
+               spin_unlock(&uhci->lock);
                usb_hcd_poll_rh_status(hcd);
-       else {
-               spin_lock(&uhci->lock);
+       } else {
                uhci_scan_schedule(uhci);
+ done:
                spin_unlock(&uhci->lock);
        }
 
@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd)
         */
        mb();
 
+       spin_lock_irq(&uhci->lock);
        configure_hc(uhci);
        uhci->is_initialized = 1;
-       spin_lock_irq(&uhci->lock);
        start_rh(uhci);
        spin_unlock_irq(&uhci->lock);
        return 0;
index 768d54295a20742a8f38d6224ce1a9bb1de85556..15d13229ddbb6860d41e706bfaf716fe49b93067 100644 (file)
@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
                }
        }
        clear_bit(port, &uhci->resuming_ports);
+       usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);
 }
 
 /* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
                                set_bit(port, &uhci->resuming_ports);
                                uhci->ports_timeout = jiffies +
                                                msecs_to_jiffies(25);
+                               usb_hcd_start_port_resume(
+                                               &uhci_to_hcd(uhci)->self, port);
 
                                /* Make sure we see the port again
                                 * after the resuming period is over. */
index a686cf4905bb80ae3e4c7b206c05d7cd2b960920..68914429482f30ff4afed47180aae563d07c5784 100644 (file)
@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        break;
                case USB_PORT_FEAT_LINK_STATE:
                        temp = xhci_readl(xhci, port_array[wIndex]);
+
+                       /* Disable port */
+                       if (link_state == USB_SS_PORT_LS_SS_DISABLED) {
+                               xhci_dbg(xhci, "Disable port %d\n", wIndex);
+                               temp = xhci_port_state_to_neutral(temp);
+                               /*
+                                * Clear all change bits, so that we get a new
+                                * connection event.
+                                */
+                               temp |= PORT_CSC | PORT_PEC | PORT_WRC |
+                                       PORT_OCC | PORT_RC | PORT_PLC |
+                                       PORT_CEC;
+                               xhci_writel(xhci, temp | PORT_PE,
+                                       port_array[wIndex]);
+                               temp = xhci_readl(xhci, port_array[wIndex]);
+                               break;
+                       }
+
+                       /* Put link in RxDetect (enable port) */
+                       if (link_state == USB_SS_PORT_LS_RX_DETECT) {
+                               xhci_dbg(xhci, "Enable port %d\n", wIndex);
+                               xhci_set_link_state(xhci, port_array, wIndex,
+                                               link_state);
+                               temp = xhci_readl(xhci, port_array[wIndex]);
+                               break;
+                       }
+
                        /* Software should not attempt to set
-                        * port link state above '5' (Rx.Detect) and the port
+                        * port link state above '3' (U3) and the port
                         * must be enabled.
                         */
                        if ((temp & PORT_PE) == 0 ||
-                               (link_state > USB_SS_PORT_LS_RX_DETECT)) {
+                               (link_state > USB_SS_PORT_LS_U3)) {
                                xhci_warn(xhci, "Cannot set link state.\n");
                                goto error;
                        }
@@ -957,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
        int max_ports;
        __le32 __iomem **port_array;
        struct xhci_bus_state *bus_state;
+       bool reset_change = false;
 
        max_ports = xhci_get_ports(hcd, &port_array);
        bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -988,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
                        buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
                        status = 1;
                }
+               if ((temp & PORT_RC))
+                       reset_change = true;
+       }
+       if (!status && !reset_change) {
+               xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+               clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        }
        spin_unlock_irqrestore(&xhci->lock, flags);
        return status ? retval : 0;
index fb51c7085ad0d19c7159afd9a069c82846afd405..35616ffbe3ae7435155bf29196d295f35a719b71 100644 (file)
@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
 static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
+       if (ep->desc.bInterval == 0)
+               return 0;
        return xhci_microframes_to_exponent(udev, ep,
                        ep->desc.bInterval, 0, 15);
 }
index cbb44b7b9d6553e01f9c2f45da23c8fad1b7fe92..7f76a49e90d384fdee83d0f87607113c9ebcf272 100644 (file)
@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                                faked_port_index + 1);
                if (slot_id && xhci->devs[slot_id])
                        xhci_ring_device(xhci, slot_id);
-               if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
+               if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {
                        bus_state->port_remote_wakeup &=
                                ~(1 << faked_port_index);
                        xhci_test_and_clear_bit(xhci, port_array,
@@ -1725,6 +1725,15 @@ cleanup:
        if (bogus_port_status)
                return;
 
+       /*
+        * xHCI port-status-change events occur when the "or" of all the
+        * status-change bits in the portsc register changes from 0 to 1.
+        * New status changes won't cause an event if any other change
+        * bits are still set.  When an event occurs, switch over to
+        * polling to avoid losing status changes.
+        */
+       xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+       set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        spin_unlock(&xhci->lock);
        /* Pass this up to the core */
        usb_hcd_poll_rh_status(hcd);
@@ -2580,6 +2589,8 @@ cleanup:
                                (trb_comp_code != COMP_STALL &&
                                        trb_comp_code != COMP_BABBLE))
                                xhci_urb_free_priv(xhci, urb_priv);
+                       else
+                               kfree(urb_priv);
 
                        usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
                        if ((urb->actual_length != urb->transfer_buffer_length &&
@@ -3099,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
         * running_total.
         */
        packets_transferred = (running_total + trb_buff_len) /
-               usb_endpoint_maxp(&urb->ep->desc);
+               GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
 
        if ((total_packet_count - packets_transferred) > 31)
                return 31 << 17;
@@ -3633,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                td_len = urb->iso_frame_desc[i].length;
                td_remain_len = td_len;
                total_packet_count = DIV_ROUND_UP(td_len,
-                               usb_endpoint_maxp(&urb->ep->desc));
+                               GET_MAX_PACKET(
+                                       usb_endpoint_maxp(&urb->ep->desc)));
                /* A zero-length transfer still involves at least one packet. */
                if (total_packet_count == 0)
                        total_packet_count++;
@@ -3655,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                td = urb_priv->td[i];
                for (j = 0; j < trbs_per_td; j++) {
                        u32 remainder = 0;
-                       field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
+                       field = 0;
 
                        if (first_trb) {
+                               field = TRB_TBC(burst_count) |
+                                       TRB_TLBPC(residue);
                                /* Queue the isoc TRB */
                                field |= TRB_TYPE(TRB_ISOC);
                                /* Assume URB_ISO_ASAP is set */
index 5c72c431bab18da941ec9a1a235c134086065482..f1f01a834ba792cee0935c5ffb9373d53fb368bd 100644 (file)
@@ -884,6 +884,11 @@ int xhci_suspend(struct xhci_hcd *xhci)
                        xhci->shared_hcd->state != HC_STATE_SUSPENDED)
                return -EINVAL;
 
+       /* Don't poll the roothubs on bus suspend. */
+       xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+       clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+       del_timer_sync(&hcd->rh_timer);
+
        spin_lock_irq(&xhci->lock);
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
@@ -1069,6 +1074,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
                compliance_mode_recovery_timer_init(xhci);
 
+       /* Re-enable port polling. */
+       xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+       set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+       usb_hcd_poll_rh_status(hcd);
+
        return retval;
 }
 #endif /* CONFIG_PM */
index 7667b12f2ff5b0a0a32cd236d6d6e5d970e6cc47..268148de97147d7f77652914cd46660954c83525 100644 (file)
@@ -2179,7 +2179,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                if (dev->out_pipe == 0 || !param->length || param->sglen < 4)
                        break;
                retval = 0;
-               dev_info(&intf->dev, "TEST 17:  unlink from %d queues of "
+               dev_info(&intf->dev, "TEST 24:  unlink from %d queues of "
                                "%d %d-byte writes\n",
                                param->iterations, param->sglen, param->length);
                for (i = param->iterations; retval == 0 && i > 0; --i) {
index 0968dd7a859def7e04496d525bc51bdecb87cea0..f522000e8f0659b11124f48ef94f6f0c1bdb104c 100644 (file)
@@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr)
        musb_writel(&tx->tx_complete, 0, ptr);
 }
 
-static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
+static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
 {
        int     j;
 
@@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c)
        c->last_processed = NULL;
 }
 
-static int __init cppi_controller_start(struct dma_controller *c)
+static int cppi_controller_start(struct dma_controller *c)
 {
        struct cppi     *controller;
        void __iomem    *tibase;
index f1c6c5470b92550831cbe6551cf8cb090b2d491d..fd3486745e64bcdecd3aeea4843971e5e1795c22 100644 (file)
@@ -2298,10 +2298,7 @@ static int __init musb_init(void)
        if (usb_disabled())
                return 0;
 
-       pr_info("%s: version " MUSB_VERSION ", "
-               "?dma?"
-               ", "
-               "otg (peripheral+host)",
+       pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
                musb_driver_name);
        return platform_driver_register(&musb_driver);
 }
index e6f2ae8368bb8b046b34716698b553156df30a99..f7d764de6fdab988bde6124a8a9cd8657a0ea0ff 100644 (file)
@@ -134,6 +134,11 @@ static const resource_size_t dsps_control_module_phys[] = {
        DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
 };
 
+#define USBPHY_CM_PWRDN                (1 << 0)
+#define USBPHY_OTG_PWRDN       (1 << 1)
+#define USBPHY_OTGVDET_EN      (1 << 19)
+#define USBPHY_OTGSESSEND_EN   (1 << 20)
+
 /**
  * musb_dsps_phy_control - phy on/off
  * @glue: struct dsps_glue *
index 6223062d5d1b5487534dc29724508d2e5df68793..37962c99ff1e9ace79bd89fdadfe4103649909e6 100644 (file)
@@ -110,7 +110,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
        select USB_OTG
        select USB_OTG_UTILS
        help
index 1dd57504186db5225b28b353527001b4e1914b2e..eace975991a873a938983da7c3dbb5abc2ce2df5 100644 (file)
@@ -240,7 +240,7 @@ static void otg_clock_enable(struct mv_otg *mvotg)
        unsigned int i;
 
        for (i = 0; i < mvotg->clknum; i++)
-               clk_enable(mvotg->clk[i]);
+               clk_prepare_enable(mvotg->clk[i]);
 }
 
 static void otg_clock_disable(struct mv_otg *mvotg)
@@ -248,7 +248,7 @@ static void otg_clock_disable(struct mv_otg *mvotg)
        unsigned int i;
 
        for (i = 0; i < mvotg->clknum; i++)
-               clk_disable(mvotg->clk[i]);
+               clk_disable_unprepare(mvotg->clk[i]);
 }
 
 static int mv_otg_enable_internal(struct mv_otg *mvotg)
index dd41f61893ef87484fbfc233dc338427bcfcede6..f2985cd88021c0bd52178ee48cc64c4c7c97bc00 100644 (file)
@@ -545,15 +545,6 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
        return 0;
 }
 
-static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv)
-{
-       int i;
-       struct usbhsg_uep *uep;
-
-       usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
-               uep->pipe = NULL;
-}
-
 /*
  *
  *             usb_ep_ops
@@ -610,7 +601,12 @@ static int usbhsg_ep_disable(struct usb_ep *ep)
 {
        struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 
-       return usbhsg_pipe_disable(uep);
+       usbhsg_pipe_disable(uep);
+
+       uep->pipe->mod_private  = NULL;
+       uep->pipe               = NULL;
+
+       return 0;
 }
 
 static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
@@ -761,9 +757,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
        usbhs_pipe_init(priv,
                        usbhsg_dma_map_ctrl);
        usbhs_fifo_init(priv);
-       usbhsg_uep_init(gpriv);
 
-       /* dcp init */
+       /* dcp init instead of usbhsg_ep_enable() */
        dcp->pipe               = usbhs_dcp_malloc(priv);
        dcp->pipe->mod_private  = dcp;
        usbhs_pipe_config_update(dcp->pipe, 0, 0, 64);
@@ -825,7 +820,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
        usbhs_sys_set_test_mode(priv, 0);
        usbhs_sys_function_ctrl(priv, 0);
 
-       usbhsg_pipe_disable(dcp);
+       usbhsg_ep_disable(&dcp->ep);
 
        dev_dbg(dev, "stop gadget\n");
 
@@ -998,6 +993,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
         */
        usbhsg_for_each_uep_with_dcp(uep, gpriv, i) {
                uep->gpriv      = gpriv;
+               uep->pipe       = NULL;
                snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i);
 
                uep->ep.name            = uep->ep_name;
index 3d3cd6ca2689894a497efefeb6ffc1edf6002cba..b86815421c8d4b6bbf86a54f39bd0e83c82d8bda 100644 (file)
@@ -661,9 +661,10 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
                status = -ESHUTDOWN;
 
        urb->actual_length = pkt->actual;
-       usbhsh_ureq_free(hpriv, ureq);
 
        usbhsh_endpoint_sequence_save(hpriv, urb, pkt);
+       usbhsh_ureq_free(hpriv, ureq);
+
        usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep));
 
        usb_hcd_unlink_urb_from_ep(hcd, urb);
index f14736f647ff28ca31e583e08c1914879836978d..edc0f0dcad8378f4298d68815d2935404d8fedac 100644 (file)
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
        { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+       { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
        { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
index 0a373b3ae96a77c5f43afbc316c5faaba82e0609..90ceef1776c34197c65fb58988e0fc5771184a35 100644 (file)
@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = {
        /*
         * ELV devices:
         */
+       { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
@@ -875,6 +877,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
+       /* Crucible Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
index 049b6e715fa470921748a9d29a236946e148ec7a..9d359e189a645f7dcd13222433b9377787f81a34 100644 (file)
 #define XSENS_CONVERTER_6_PID  0xD38E
 #define XSENS_CONVERTER_7_PID  0xD38F
 
+/**
+ * Zolix (www.zolix.com.cb) product ids
+ */
+#define FTDI_OMNI1509                  0xD491  /* Omni1509 embedded USB-serial */
+
 /*
  * NDI (www.ndigital.com) product ids
  */
 
 /*
  * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
+ * Almost all of these devices use FTDI's vendor ID (0x0403).
  * Further IDs taken from ELV Windows .inf file.
  *
  * The previously included PID for the UO 100 module was incorrect.
  *
  * Armin Laeuger originally sent the PID for the UM 100 module.
  */
+#define FTDI_ELV_VID   0x1B1F  /* ELV AG */
+#define FTDI_ELV_WS300_PID     0xC006  /* eQ3 WS 300 PC II */
 #define FTDI_ELV_USR_PID       0xE000  /* ELV Universal-Sound-Recorder */
 #define FTDI_ELV_MSM1_PID      0xE001  /* ELV Mini-Sound-Modul */
 #define FTDI_ELV_KL100_PID     0xE002  /* ELV Kfz-Leistungsmesser KL 100 */
  * ATI command output: Cinterion MC55i
  */
 #define FTDI_CINTERION_MC55I_PID       0xA951
+
+/*
+ * Product: Comet Caller ID decoder
+ * Manufacturer: Crucible Technologies
+ */
+#define FTDI_CT_COMET_PID      0x8e08
index 58184f3de6867bfa9ebbbc6d6afbe074d80a8f12..82afc4d6a327d6bdbebc4707507684c966f11f9f 100644 (file)
@@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
        wait_queue_t wait;
        unsigned long flags;
 
+       if (!tty)
+               return;
+
        if (!timeout)
                timeout = (HZ * EDGE_CLOSING_WAIT)/100;
 
index e6f87b76c7156914dac281684e6130fde3b85ac0..567bc77d63970357b2dc9224f04c635ab727fc85 100644 (file)
@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_CC864_DUAL               0x1005
 #define TELIT_PRODUCT_CC864_SINGLE             0x1006
 #define TELIT_PRODUCT_DE910_DUAL               0x1010
+#define TELIT_PRODUCT_LE920                    0x1200
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID                          0x19d2
@@ -288,6 +289,7 @@ static void option_instat_callback(struct urb *urb);
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200             0x0000
 #define ALCATEL_PRODUCT_X220_X500D             0x0017
+#define ALCATEL_PRODUCT_L100V                  0x011e
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -429,9 +431,12 @@ static void option_instat_callback(struct urb *urb);
 #define MEDIATEK_VENDOR_ID                     0x0e8d
 #define MEDIATEK_PRODUCT_DC_1COM               0x00a0
 #define MEDIATEK_PRODUCT_DC_4COM               0x00a5
+#define MEDIATEK_PRODUCT_DC_4COM2              0x00a7
 #define MEDIATEK_PRODUCT_DC_5COM               0x00a4
 #define MEDIATEK_PRODUCT_7208_1COM             0x7101
 #define MEDIATEK_PRODUCT_7208_2COM             0x7102
+#define MEDIATEK_PRODUCT_7103_2COM             0x7103
+#define MEDIATEK_PRODUCT_7106_2COM             0x7106
 #define MEDIATEK_PRODUCT_FP_1COM               0x0003
 #define MEDIATEK_PRODUCT_FP_2COM               0x0023
 #define MEDIATEK_PRODUCT_FPDC_1COM             0x0043
@@ -441,6 +446,18 @@ static void option_instat_callback(struct urb *urb);
 #define CELLIENT_VENDOR_ID                     0x2692
 #define CELLIENT_PRODUCT_MEN200                        0x9005
 
+/* Hyundai Petatel Inc. products */
+#define PETATEL_VENDOR_ID                      0x1ff4
+#define PETATEL_PRODUCT_NP10T                  0x600e
+
+/* TP-LINK Incorporated products */
+#define TPLINK_VENDOR_ID                       0x2357
+#define TPLINK_PRODUCT_MA180                   0x0201
+
+/* Changhong products */
+#define CHANGHONG_VENDOR_ID                    0x2077
+#define CHANGHONG_PRODUCT_CH690                        0x7001
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -522,6 +539,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
        .reserved = BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info telit_le920_blacklist = {
+       .sendsetup = BIT(0),
+       .reserved = BIT(1) | BIT(5),
+};
+
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -772,6 +794,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+               .driver_info = (kernel_ulong_t)&telit_le920_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -922,8 +946,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
        { 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, 0x0265, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
@@ -1190,6 +1216,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { 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),
@@ -1294,7 +1322,15 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
        { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
+       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
+       { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index aa148c21ea40e82a6f49b58b855ed2278f53cf3a..24662547dc5b2e60ffc51abc846e930e0afc1182 100644 (file)
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_G1K(0x05c6, 0x9221)},   /* Generic Gobi QDL device */
        {DEVICE_G1K(0x05c6, 0x9231)},   /* Generic Gobi QDL device */
        {DEVICE_G1K(0x1f45, 0x0001)},   /* Unknown Gobi QDL device */
+       {DEVICE_G1K(0x1bc7, 0x900e)},   /* Telit Gobi QDL device */
 
        /* Gobi 2000 devices */
        {USB_DEVICE(0x1410, 0xa010)},   /* Novatel Gobi 2000 QDL device */
index 105d900150c1a80155c2afcec6a61f4fb07fd0b4..16b0bf055eeb08427436841fc784b07554dd27cc 100644 (file)
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        return 0;
 }
 
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us)
+/* This places the HUAWEI usb dongles in multi-port mode */
+static int usb_stor_huawei_feature_init(struct us_data *us)
 {
        int result;
 
@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us)
        US_DEBUGP("Huawei mode set result is %d\n", result);
        return 0;
 }
+
+/*
+ * It will send a scsi switch command called rewind' to huawei dongle.
+ * When the dongle receives this command at the first time,
+ * it will reboot immediately. After rebooted, it will ignore this command.
+ * So it is  unnecessary to read its response.
+ */
+static int usb_stor_huawei_scsi_init(struct us_data *us)
+{
+       int result = 0;
+       int act_len = 0;
+       struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
+       char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
+                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+       bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcbw->Tag = 0;
+       bcbw->DataTransferLength = 0;
+       bcbw->Flags = bcbw->Lun = 0;
+       bcbw->Length = sizeof(rewind_cmd);
+       memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
+       memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
+
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
+                                       US_BULK_CB_WRAP_LEN, &act_len);
+       US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
+       return result;
+}
+
+/*
+ * It tries to find the supported Huawei USB dongles.
+ * In Huawei, they assign the following product IDs
+ * for all of their mobile broadband dongles,
+ * including the new dongles in the future.
+ * So if the product ID is not included in this list,
+ * it means it is not Huawei's mobile broadband dongles.
+ */
+static int usb_stor_huawei_dongles_pid(struct us_data *us)
+{
+       struct usb_interface_descriptor *idesc;
+       int idProduct;
+
+       idesc = &us->pusb_intf->cur_altsetting->desc;
+       idProduct = us->pusb_dev->descriptor.idProduct;
+       /* The first port is CDROM,
+        * means the dongle in the single port mode,
+        * and a switch command is required to be sent. */
+       if (idesc && idesc->bInterfaceNumber == 0) {
+               if ((idProduct == 0x1001)
+                       || (idProduct == 0x1003)
+                       || (idProduct == 0x1004)
+                       || (idProduct >= 0x1401 && idProduct <= 0x1500)
+                       || (idProduct >= 0x1505 && idProduct <= 0x1600)
+                       || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+int usb_stor_huawei_init(struct us_data *us)
+{
+       int result = 0;
+
+       if (usb_stor_huawei_dongles_pid(us)) {
+               if (us->pusb_dev->descriptor.idProduct >= 0x1446)
+                       result = usb_stor_huawei_scsi_init(us);
+               else
+                       result = usb_stor_huawei_feature_init(us);
+       }
+       return result;
+}
index 529327fbb06be1b6876e8802b84bd281287291c3..5376d4fc76f04c25092244765237f94f44456ba1 100644 (file)
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
 
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us);
+/* This places the HUAWEI usb dongles in multi-port mode */
+int usb_stor_huawei_init(struct us_data *us);
index d305a5aa3a5d7683a5bcd1c2e60c4a0262f35f65..72923b56bbf6b871a6da926168d43cf8db3e6383 100644 (file)
@@ -1527,335 +1527,10 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 /* Reported by fangxiaozhi <huananhu@huawei.com>
  * This brings the HUAWEI data card devices into multi-port mode
  */
-UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
+UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
                "HUAWEI MOBILE",
                "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
                0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
index 31b3e1a61bbdda035d5ce1e5ef63ac05e36b5b26..cf09b6ba71ff49f5be0e367811f72e3794630f32 100644 (file)
@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
        .useTransport = use_transport,  \
 }
 
+#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
+               vendor_name, product_name, use_protocol, use_transport, \
+               init_function, Flags) \
+{ \
+       .vendorName = vendor_name,      \
+       .productName = product_name,    \
+       .useProtocol = use_protocol,    \
+       .useTransport = use_transport,  \
+       .initFunction = init_function,  \
+}
+
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids =
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
 
 #ifdef CONFIG_LOCKDEP
 
index b78a526910fb31ac257a13800c593236c0e21a27..5ef8ce74aae456c741bdff0856b564e9edb156a0 100644 (file)
 #define USUAL_DEV(useProto, useTrans) \
 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) }
 
+/* Define the device is matched with Vendor ID and interface descriptors */
+#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \
+                       vendorName, productName, useProtocol, useTransport, \
+                       initFunction, flags) \
+{ \
+       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+                               | USB_DEVICE_ID_MATCH_VENDOR, \
+       .idVendor    = (id_vendor), \
+       .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), \
+       .bInterfaceProtocol = (pr), \
+       .driver_info = (flags) \
+}
+
 struct usb_device_id usb_storage_usb_ids[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
 
 /*
  * The table of devices to ignore
index 6c119944bbb6e8c03f7e15424494b17d4fbdd5db..b28e66c4376ab3c320e144714f6f38a02e05fc9a 100644 (file)
@@ -43,6 +43,10 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
        u16 cmd;
        u8 msix_pos;
 
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
        vdev->reset_works = (pci_reset_function(pdev) == 0);
        pci_save_state(pdev);
        vdev->pci_saved_state = pci_store_saved_state(pdev);
@@ -51,8 +55,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
                         __func__, dev_name(&pdev->dev));
 
        ret = vfio_config_init(vdev);
-       if (ret)
-               goto out;
+       if (ret) {
+               pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state);
+               pci_disable_device(pdev);
+               return ret;
+       }
 
        if (likely(!nointxmask))
                vdev->pci_2_3 = pci_intx_mask_supported(pdev);
@@ -77,24 +84,15 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
        } else
                vdev->msix_bar = 0xFF;
 
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto out;
-
-       return ret;
-
-out:
-       kfree(vdev->pci_saved_state);
-       vdev->pci_saved_state = NULL;
-       vfio_config_free(vdev);
-       return ret;
+       return 0;
 }
 
 static void vfio_pci_disable(struct vfio_pci_device *vdev)
 {
+       struct pci_dev *pdev = vdev->pdev;
        int bar;
 
-       pci_disable_device(vdev->pdev);
+       pci_disable_device(pdev);
 
        vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE |
                                VFIO_IRQ_SET_ACTION_TRIGGER,
@@ -104,22 +102,40 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
 
        vfio_config_free(vdev);
 
-       pci_reset_function(vdev->pdev);
-
-       if (pci_load_and_free_saved_state(vdev->pdev,
-                                         &vdev->pci_saved_state) == 0)
-               pci_restore_state(vdev->pdev);
-       else
-               pr_info("%s: Couldn't reload %s saved state\n",
-                       __func__, dev_name(&vdev->pdev->dev));
-
        for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) {
                if (!vdev->barmap[bar])
                        continue;
-               pci_iounmap(vdev->pdev, vdev->barmap[bar]);
-               pci_release_selected_regions(vdev->pdev, 1 << bar);
+               pci_iounmap(pdev, vdev->barmap[bar]);
+               pci_release_selected_regions(pdev, 1 << bar);
                vdev->barmap[bar] = NULL;
        }
+
+       /*
+        * If we have saved state, restore it.  If we can reset the device,
+        * even better.  Resetting with current state seems better than
+        * nothing, but saving and restoring current state without reset
+        * is just busy work.
+        */
+       if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
+               pr_info("%s: Couldn't reload %s saved state\n",
+                       __func__, dev_name(&pdev->dev));
+
+               if (!vdev->reset_works)
+                       return;
+
+               pci_save_state(pdev);
+       }
+
+       /*
+        * Disable INTx and MSI, presumably to avoid spurious interrupts
+        * during reset.  Stolen from pci_reset_function()
+        */
+       pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
+
+       if (vdev->reset_works)
+               __pci_reset_function(pdev);
+
+       pci_restore_state(pdev);
 }
 
 static void vfio_pci_release(void *device_data)
@@ -327,15 +343,10 @@ static long vfio_pci_ioctl(void *device_data,
                            hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
                                return -EINVAL;
 
-                       data = kmalloc(hdr.count * size, GFP_KERNEL);
-                       if (!data)
-                               return -ENOMEM;
-
-                       if (copy_from_user(data, (void __user *)(arg + minsz),
-                                          hdr.count * size)) {
-                               kfree(data);
-                               return -EFAULT;
-                       }
+                       data = memdup_user((void __user *)(arg + minsz),
+                                          hdr.count * size);
+                       if (IS_ERR(data))
+                               return PTR_ERR(data);
                }
 
                mutex_lock(&vdev->igate);
@@ -562,9 +573,9 @@ static int __init vfio_pci_init(void)
 
        return 0;
 
-out_virqfd:
-       vfio_pci_virqfd_exit();
 out_driver:
+       vfio_pci_virqfd_exit();
+out_virqfd:
        vfio_pci_uninit_perm_bits();
        return ret;
 }
index 4362d9e7baa355a971ed5935a486757b49699154..f72323ef618fbd99ce88d0c99480d165b94e2f42 100644 (file)
@@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf,
                        filled = 1;
                } else {
                        /* Drop writes, fill reads with FF */
+                       filled = min((size_t)(x_end - pos), count);
                        if (!iswrite) {
                                char val = 0xFF;
                                size_t i;
 
-                               for (i = 0; i < x_end - pos; i++) {
+                               for (i = 0; i < filled; i++) {
                                        if (put_user(val, buf + i))
                                                goto out;
                                }
                        }
 
-                       filled = x_end - pos;
                }
 
                count -= filled;
index 56097c6d072d0797ecc9c13c9d2d231aa3e9afa8..12c264d3b058bf1bb7884a484aaf7631f5aa0d16 100644 (file)
@@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container)
        kref_put(&container->kref, vfio_container_release);
 }
 
+static void vfio_group_unlock_and_free(struct vfio_group *group)
+{
+       mutex_unlock(&vfio.group_lock);
+       /*
+        * Unregister outside of lock.  A spurious callback is harmless now
+        * that the group is no longer in vfio.group_list.
+        */
+       iommu_group_unregister_notifier(group->iommu_group, &group->nb);
+       kfree(group);
+}
+
 /**
  * Group objects - create, release, get, put, search
  */
@@ -229,8 +240,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 
        minor = vfio_alloc_group_minor(group);
        if (minor < 0) {
-               mutex_unlock(&vfio.group_lock);
-               kfree(group);
+               vfio_group_unlock_and_free(group);
                return ERR_PTR(minor);
        }
 
@@ -239,8 +249,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
                if (tmp->iommu_group == iommu_group) {
                        vfio_group_get(tmp);
                        vfio_free_group_minor(minor);
-                       mutex_unlock(&vfio.group_lock);
-                       kfree(group);
+                       vfio_group_unlock_and_free(group);
                        return tmp;
                }
        }
@@ -249,8 +258,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
                            group, "%d", iommu_group_id(iommu_group));
        if (IS_ERR(dev)) {
                vfio_free_group_minor(minor);
-               mutex_unlock(&vfio.group_lock);
-               kfree(group);
+               vfio_group_unlock_and_free(group);
                return (struct vfio_group *)dev; /* ERR_PTR */
        }
 
@@ -274,16 +282,7 @@ static void vfio_group_release(struct kref *kref)
        device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor));
        list_del(&group->vfio_next);
        vfio_free_group_minor(group->minor);
-
-       mutex_unlock(&vfio.group_lock);
-
-       /*
-        * Unregister outside of lock.  A spurious callback is harmless now
-        * that the group is no longer in vfio.group_list.
-        */
-       iommu_group_unregister_notifier(group->iommu_group, &group->nb);
-
-       kfree(group);
+       vfio_group_unlock_and_free(group);
 }
 
 static void vfio_group_put(struct vfio_group *group)
@@ -466,8 +465,9 @@ static int vfio_dev_viable(struct device *dev, void *data)
 {
        struct vfio_group *group = data;
        struct vfio_device *device;
+       struct device_driver *drv = ACCESS_ONCE(dev->driver);
 
-       if (!dev->driver || vfio_whitelisted_driver(dev->driver))
+       if (!drv || vfio_whitelisted_driver(drv))
                return 0;
 
        device = vfio_group_get_device(group, dev);
index ebd08b21b23432696047487367d44f76d4fa4f02..959b1cd89e6a5be5a402a79089077609f8e30716 100644 (file)
@@ -165,12 +165,16 @@ static void tx_poll_stop(struct vhost_net *net)
 }
 
 /* Caller must have TX VQ lock */
-static void tx_poll_start(struct vhost_net *net, struct socket *sock)
+static int tx_poll_start(struct vhost_net *net, struct socket *sock)
 {
+       int ret;
+
        if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED))
-               return;
-       vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
-       net->tx_poll_state = VHOST_NET_POLL_STARTED;
+               return 0;
+       ret = vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
+       if (!ret)
+               net->tx_poll_state = VHOST_NET_POLL_STARTED;
+       return ret;
 }
 
 /* In case of DMA done not in order in lower device driver for some reason.
@@ -642,20 +646,23 @@ static void vhost_net_disable_vq(struct vhost_net *n,
                vhost_poll_stop(n->poll + VHOST_NET_VQ_RX);
 }
 
-static void vhost_net_enable_vq(struct vhost_net *n,
+static int vhost_net_enable_vq(struct vhost_net *n,
                                struct vhost_virtqueue *vq)
 {
        struct socket *sock;
+       int ret;
 
        sock = rcu_dereference_protected(vq->private_data,
                                         lockdep_is_held(&vq->mutex));
        if (!sock)
-               return;
+               return 0;
        if (vq == n->vqs + VHOST_NET_VQ_TX) {
                n->tx_poll_state = VHOST_NET_POLL_STOPPED;
-               tx_poll_start(n, sock);
+               ret = tx_poll_start(n, sock);
        } else
-               vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+               ret = vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+
+       return ret;
 }
 
 static struct socket *vhost_net_stop_vq(struct vhost_net *n,
@@ -827,15 +834,18 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
                        r = PTR_ERR(ubufs);
                        goto err_ubufs;
                }
-               oldubufs = vq->ubufs;
-               vq->ubufs = ubufs;
+
                vhost_net_disable_vq(n, vq);
                rcu_assign_pointer(vq->private_data, sock);
-               vhost_net_enable_vq(n, vq);
-
                r = vhost_init_used(vq);
                if (r)
-                       goto err_vq;
+                       goto err_used;
+               r = vhost_net_enable_vq(n, vq);
+               if (r)
+                       goto err_used;
+
+               oldubufs = vq->ubufs;
+               vq->ubufs = ubufs;
 
                n->tx_packets = 0;
                n->tx_zcopy_err = 0;
@@ -859,6 +869,11 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        mutex_unlock(&n->dev.mutex);
        return 0;
 
+err_used:
+       rcu_assign_pointer(vq->private_data, oldsock);
+       vhost_net_enable_vq(n, vq);
+       if (ubufs)
+               vhost_ubuf_put_and_wait(ubufs);
 err_ubufs:
        fput(sock->file);
 err_vq:
index b20df5c829f5036042008d37f6ab20d424e977cd..22321cf84fbe2ce4c19090928ba5ecb83b8e5486 100644 (file)
@@ -575,10 +575,8 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs)
 
        /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */
        tv_tpg = vs->vs_tpg;
-       if (unlikely(!tv_tpg)) {
-               pr_err("%s endpoint not set\n", __func__);
+       if (unlikely(!tv_tpg))
                return;
-       }
 
        mutex_lock(&vq->mutex);
        vhost_disable_notify(&vs->dev, vq);
index 34389f75fe65693a4ad5baa36715159fd5759bbb..9759249e6d908867cf72f53e5bb8e4ecc30db8ae 100644 (file)
@@ -77,26 +77,38 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
        init_poll_funcptr(&poll->table, vhost_poll_func);
        poll->mask = mask;
        poll->dev = dev;
+       poll->wqh = NULL;
 
        vhost_work_init(&poll->work, fn);
 }
 
 /* Start polling a file. We add ourselves to file's wait queue. The caller must
  * keep a reference to a file until after vhost_poll_stop is called. */
-void vhost_poll_start(struct vhost_poll *poll, struct file *file)
+int vhost_poll_start(struct vhost_poll *poll, struct file *file)
 {
        unsigned long mask;
+       int ret = 0;
 
        mask = file->f_op->poll(file, &poll->table);
        if (mask)
                vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
+       if (mask & POLLERR) {
+               if (poll->wqh)
+                       remove_wait_queue(poll->wqh, &poll->wait);
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
 
 /* Stop polling a file. After this function returns, it becomes safe to drop the
  * file reference. You must also flush afterwards. */
 void vhost_poll_stop(struct vhost_poll *poll)
 {
-       remove_wait_queue(poll->wqh, &poll->wait);
+       if (poll->wqh) {
+               remove_wait_queue(poll->wqh, &poll->wait);
+               poll->wqh = NULL;
+       }
 }
 
 static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work,
@@ -792,7 +804,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
                fput(filep);
 
        if (pollstart && vq->handle_kick)
-               vhost_poll_start(&vq->poll, vq->kick);
+               r = vhost_poll_start(&vq->poll, vq->kick);
 
        mutex_unlock(&vq->mutex);
 
index 2639c58b23ab497ace850895f3322df661a965df..17261e277c022abbffe8effc6a8492336ea7edef 100644 (file)
@@ -42,7 +42,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);
 
 void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
                     unsigned long mask, struct vhost_dev *dev);
-void vhost_poll_start(struct vhost_poll *poll, struct file *file);
+int vhost_poll_start(struct vhost_poll *poll, struct file *file);
 void vhost_poll_stop(struct vhost_poll *poll);
 void vhost_poll_flush(struct vhost_poll *poll);
 void vhost_poll_queue(struct vhost_poll *poll);
index b303f17150654a8a4d0237f41977421a29cd715b..6488a7351a6055adbe1c80c6cdc68390aa4c4d25 100644 (file)
@@ -66,7 +66,7 @@
  * have.  Allow 1% either way on the nominal for TVs.
  */
 #define NR_MONTYPES    6
-static struct fb_monspecs monspecs[NR_MONTYPES] __devinitdata = {
+static struct fb_monspecs monspecs[NR_MONTYPES] = {
        {       /* TV           */
                .hfmin  = 15469,
                .hfmax  = 15781,
@@ -874,7 +874,7 @@ static struct fb_ops acornfb_ops = {
 /*
  * Everything after here is initialisation!!!
  */
-static struct fb_videomode modedb[] __devinitdata = {
+static struct fb_videomode modedb[] = {
        {       /* 320x256 @ 50Hz */
                NULL, 50,  320,  256, 125000,  92,  62,  35, 19,  38, 2,
                FB_SYNC_COMP_HIGH_ACT,
@@ -926,7 +926,7 @@ static struct fb_videomode modedb[] __devinitdata = {
        }
 };
 
-static struct fb_videomode acornfb_default_mode __devinitdata = {
+static struct fb_videomode acornfb_default_mode = {
        .name =         NULL,
        .refresh =      60,
        .xres =         640,
@@ -942,7 +942,7 @@ static struct fb_videomode acornfb_default_mode __devinitdata = {
        .vmode =        FB_VMODE_NONINTERLACED
 };
 
-static void __devinit acornfb_init_fbinfo(void)
+static void acornfb_init_fbinfo(void)
 {
        static int first = 1;
 
@@ -1018,7 +1018,7 @@ static void __devinit acornfb_init_fbinfo(void)
  *     size can optionally be followed by 'M' or 'K' for
  *     MB or KB respectively.
  */
-static void __devinit acornfb_parse_mon(char *opt)
+static void acornfb_parse_mon(char *opt)
 {
        char *p = opt;
 
@@ -1065,7 +1065,7 @@ bad:
        current_par.montype = -1;
 }
 
-static void __devinit acornfb_parse_montype(char *opt)
+static void acornfb_parse_montype(char *opt)
 {
        current_par.montype = -2;
 
@@ -1106,7 +1106,7 @@ static void __devinit acornfb_parse_montype(char *opt)
        }
 }
 
-static void __devinit acornfb_parse_dram(char *opt)
+static void acornfb_parse_dram(char *opt)
 {
        unsigned int size;
 
@@ -1131,14 +1131,14 @@ static void __devinit acornfb_parse_dram(char *opt)
 static struct options {
        char *name;
        void (*parse)(char *opt);
-} opt_table[] __devinitdata = {
+} opt_table[] = {
        { "mon",     acornfb_parse_mon     },
        { "montype", acornfb_parse_montype },
        { "dram",    acornfb_parse_dram    },
        { NULL, NULL }
 };
 
-static int __devinit acornfb_setup(char *options)
+static int acornfb_setup(char *options)
 {
        struct options *optp;
        char *opt;
@@ -1175,7 +1175,7 @@ static int __devinit acornfb_setup(char *options)
  * Detect type of monitor connected
  *  For now, we just assume SVGA
  */
-static int __devinit acornfb_detect_monitortype(void)
+static int acornfb_detect_monitortype(void)
 {
        return 4;
 }
@@ -1216,7 +1216,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
        printk("acornfb: freed %dK memory\n", mb_freed);
 }
 
-static int __devinit acornfb_probe(struct platform_device *dev)
+static int acornfb_probe(struct platform_device *dev)
 {
        unsigned long size;
        u_int h_sync, v_sync;
index 4659d5da6ff88d2a59270b9b2db69aec0c14908d..e43401afdd03f56d8c5b57efe935b6bda19b0fff 100644 (file)
@@ -79,7 +79,7 @@ struct arcfb_par {
        spinlock_t lock;
 };
 
-static struct fb_fix_screeninfo arcfb_fix __devinitdata = {
+static struct fb_fix_screeninfo arcfb_fix = {
        .id =           "arcfb",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_MONO01,
@@ -89,7 +89,7 @@ static struct fb_fix_screeninfo arcfb_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo arcfb_var __devinitdata = {
+static struct fb_var_screeninfo arcfb_var = {
        .xres           = 128,
        .yres           = 64,
        .xres_virtual   = 128,
@@ -502,7 +502,7 @@ static struct fb_ops arcfb_ops = {
        .fb_ioctl       = arcfb_ioctl,
 };
 
-static int __devinit arcfb_probe(struct platform_device *dev)
+static int arcfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        int retval = -ENOMEM;
@@ -587,7 +587,7 @@ err:
        return retval;
 }
 
-static int __devexit arcfb_remove(struct platform_device *dev)
+static int arcfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -601,7 +601,7 @@ static int __devexit arcfb_remove(struct platform_device *dev)
 
 static struct platform_driver arcfb_driver = {
        .probe  = arcfb_probe,
-       .remove = __devexit_p(arcfb_remove),
+       .remove = arcfb_remove,
        .driver = {
                .name   = "arcfb",
        },
index 555dd4c64f5be24a1a13986f84fe19360f1d9102..94a51f1ef904d55515fb56d02570eb86502e3e01 100644 (file)
@@ -100,7 +100,7 @@ static const struct svga_timing_regs ark_timing_regs     = {
 
 /* Module parameters */
 
-static char *mode_option __devinitdata = "640x480-8@60";
+static char *mode_option = "640x480-8@60";
 
 #ifdef CONFIG_MTRR
 static int mtrr = 1;
@@ -950,7 +950,7 @@ static struct fb_ops arkfb_ops = {
 
 
 /* PCI probe */
-static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct pci_bus_region bus_reg;
        struct resource vga_res;
@@ -1086,7 +1086,7 @@ err_enable_device:
 
 /* PCI remove */
 
-static void __devexit ark_pci_remove(struct pci_dev *dev)
+static void ark_pci_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -1184,7 +1184,7 @@ fail:
 
 /* List of boards that we are trying to support */
 
-static struct pci_device_id ark_devices[] __devinitdata = {
+static struct pci_device_id ark_devices[] = {
        {PCI_DEVICE(0xEDD8, 0xA099)},
        {0, 0, 0, 0, 0, 0, 0}
 };
@@ -1196,7 +1196,7 @@ static struct pci_driver arkfb_pci_driver = {
        .name           = "arkfb",
        .id_table       = ark_devices,
        .probe          = ark_pci_probe,
-       .remove         = __devexit_p(ark_pci_remove),
+       .remove         = ark_pci_remove,
        .suspend        = ark_pci_suspend,
        .resume         = ark_pci_resume,
 };
index 8cdf88e20b4b649136439aef85af97be7baf2d91..d5a37d62847bd934c5d0b6c56638da9482a1347b 100644 (file)
@@ -451,7 +451,7 @@ static struct chips_init_reg chips_init_xr[] =
        {0xd1, 0x01},
 };
 
-static void __devinit chips_hw_init(struct fb_info *p)
+static void chips_hw_init(struct fb_info *p)
 {
        int i;
 
@@ -474,7 +474,7 @@ static void __devinit chips_hw_init(struct fb_info *p)
                write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 }
 
-static struct fb_fix_screeninfo asiliantfb_fix __devinitdata = {
+static struct fb_fix_screeninfo asiliantfb_fix = {
        .id =           "Asiliant 69000",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -483,7 +483,7 @@ static struct fb_fix_screeninfo asiliantfb_fix __devinitdata = {
        .smem_len =     0x200000,       /* 2MB */
 };
 
-static struct fb_var_screeninfo asiliantfb_var __devinitdata = {
+static struct fb_var_screeninfo asiliantfb_var = {
        .xres           = 640,
        .yres           = 480,
        .xres_virtual   = 640,
@@ -504,7 +504,7 @@ static struct fb_var_screeninfo asiliantfb_var __devinitdata = {
        .vsync_len      = 2,
 };
 
-static int __devinit init_asiliant(struct fb_info *p, unsigned long addr)
+static int init_asiliant(struct fb_info *p, unsigned long addr)
 {
        int err;
 
@@ -535,8 +535,8 @@ static int __devinit init_asiliant(struct fb_info *p, unsigned long addr)
        return 0;
 }
 
-static int __devinit
-asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
+static int asiliantfb_pci_init(struct pci_dev *dp,
+                              const struct pci_device_id *ent)
 {
        unsigned long addr, size;
        struct fb_info *p;
@@ -581,7 +581,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        return 0;
 }
 
-static void __devexit asiliantfb_remove(struct pci_dev *dp)
+static void asiliantfb_remove(struct pci_dev *dp)
 {
        struct fb_info *p = pci_get_drvdata(dp);
 
@@ -593,7 +593,7 @@ static void __devexit asiliantfb_remove(struct pci_dev *dp)
        framebuffer_release(p);
 }
 
-static struct pci_device_id asiliantfb_pci_tbl[] __devinitdata = {
+static struct pci_device_id asiliantfb_pci_tbl[] = {
        { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID },
        { 0 }
 };
@@ -604,7 +604,7 @@ static struct pci_driver asiliantfb_driver = {
        .name =         "asiliantfb",
        .id_table =     asiliantfb_pci_tbl,
        .probe =        asiliantfb_pci_init,
-       .remove =       __devexit_p(asiliantfb_remove),
+       .remove =       asiliantfb_remove,
 };
 
 static int __init asiliantfb_init(void)
index 0fefa84ed9aef06c8df664c289d42cbecc8dac76..8c55011313dc7c382a17f8e552ea3b4a536b3457 100644 (file)
@@ -98,7 +98,7 @@
 
 #ifndef CONFIG_PPC_PMAC
 /* default mode */
-static struct fb_var_screeninfo default_var __devinitdata = {
+static struct fb_var_screeninfo default_var = {
        /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
        640, 480, 640, 480, 0, 0, 8, 0,
        {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -121,7 +121,7 @@ static struct fb_var_screeninfo default_var = {
 
 /* default modedb mode */
 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode defaultmode __devinitdata = {
+static struct fb_videomode defaultmode = {
        .refresh =      60,
        .xres =         640,
        .yres =         480,
@@ -149,7 +149,7 @@ enum {
 };
 
 /* Must match above enum */
-static char * const r128_family[] __devinitconst = {
+static char * const r128_family[] = {
        "AGP",
        "PCI",
        "PRO AGP",
@@ -275,7 +275,7 @@ static struct pci_driver aty128fb_driver = {
        .name           = "aty128fb",
        .id_table       = aty128_pci_tbl,
        .probe          = aty128_probe,
-       .remove         = __devexit_p(aty128_remove),
+       .remove         = aty128_remove,
        .suspend        = aty128_pci_suspend,
        .resume         = aty128_pci_resume,
 };
@@ -333,7 +333,7 @@ static const struct aty128_meminfo sdr_sgram =
 static const struct aty128_meminfo ddr_sgram =
        { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
 
-static struct fb_fix_screeninfo aty128fb_fix __devinitdata = {
+static struct fb_fix_screeninfo aty128fb_fix = {
        .id             = "ATY Rage128",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_PSEUDOCOLOR,
@@ -343,24 +343,24 @@ static struct fb_fix_screeninfo aty128fb_fix __devinitdata = {
        .accel          = FB_ACCEL_ATI_RAGE128,
 };
 
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
 #ifdef CONFIG_PPC_PMAC
-static int default_vmode __devinitdata = VMODE_1024_768_60;
-static int default_cmode __devinitdata = CMODE_8;
+static int default_vmode = VMODE_1024_768_60;
+static int default_cmode = CMODE_8;
 #endif
 
-static int default_crt_on __devinitdata = 0;
-static int default_lcd_on __devinitdata = 1;
+static int default_crt_on = 0;
+static int default_lcd_on = 1;
 
 #ifdef CONFIG_MTRR
 static bool mtrr = true;
 #endif
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight __devinitdata = 1;
+static int backlight = 1;
 #else
-static int backlight __devinitdata = 0;
+static int backlight = 0;
 #endif
 
 /* PLL constants */
@@ -449,10 +449,9 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
 static int aty128_decode_var(struct fb_var_screeninfo *var,
                              struct aty128fb_par *par);
 #if 0
-static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
-                                        void __iomem *bios);
-static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev,
-                                             const struct aty128fb_par *par);
+static void aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios);
+static void __iomem *aty128_map_ROM(struct pci_dev *pdev,
+                                   const struct aty128fb_par *par);
 #endif
 static void aty128_timings(struct aty128fb_par *par);
 static void aty128_init_engine(struct aty128fb_par *par);
@@ -582,7 +581,7 @@ static void aty_pll_writeupdate(const struct aty128fb_par *par)
 
 
 /* write to the scratch register to test r/w functionality */
-static int __devinit register_test(const struct aty128fb_par *par)
+static int register_test(const struct aty128fb_par *par)
 {
        u32 val;
        int flag = 0;
@@ -781,8 +780,8 @@ static u32 depth_to_dst(u32 depth)
 
 
 #ifndef __sparc__
-static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par,
-                                              struct pci_dev *dev)
+static void __iomem *aty128_map_ROM(const struct aty128fb_par *par,
+                                   struct pci_dev *dev)
 {
        u16 dptr;
        u8 rom_type;
@@ -868,8 +867,8 @@ static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par,
        return NULL;
 }
 
-static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
-                                        unsigned char __iomem *bios)
+static void aty128_get_pllinfo(struct aty128fb_par *par,
+                              unsigned char __iomem *bios)
 {
        unsigned int bios_hdr;
        unsigned int bios_pll;
@@ -891,7 +890,7 @@ static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
 }           
 
 #ifdef CONFIG_X86
-static void __iomem *  __devinit aty128_find_mem_vbios(struct aty128fb_par *par)
+static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
 {
        /* I simplified this code as we used to miss the signatures in
         * a lot of case. It's now closer to XFree, we just don't check
@@ -916,7 +915,7 @@ static void __iomem *  __devinit aty128_find_mem_vbios(struct aty128fb_par *par)
 #endif /* ndef(__sparc__) */
 
 /* fill in known card constants if pll_block is not available */
-static void __devinit aty128_timings(struct aty128fb_par *par)
+static void aty128_timings(struct aty128fb_par *par)
 {
 #ifdef CONFIG_PPC_OF
        /* instead of a table lookup, assume OF has properly
@@ -1658,7 +1657,7 @@ static int aty128fb_sync(struct fb_info *info)
 }
 
 #ifndef MODULE
-static int __devinit aty128fb_setup(char *options)
+static int aty128fb_setup(char *options)
 {
        char *this_opt;
 
@@ -1888,8 +1887,7 @@ static void aty128_early_resume(void *data)
 }
 #endif /* CONFIG_PPC_PMAC */
 
-static int __devinit aty128_init(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct aty128fb_par *par = info->par;
@@ -2039,8 +2037,7 @@ static int __devinit aty128_init(struct pci_dev *pdev,
 
 #ifdef CONFIG_PCI
 /* register a card    ++ajoshi */
-static int __devinit aty128_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned long fb_addr, reg_addr;
        struct aty128fb_par *par;
@@ -2156,7 +2153,7 @@ err_free_fb:
        return -ENODEV;
 }
 
-static void __devexit aty128_remove(struct pci_dev *pdev)
+static void aty128_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct aty128fb_par *par;
@@ -2558,7 +2555,7 @@ static int aty128_pci_resume(struct pci_dev *pdev)
 }
 
 
-static int __devinit aty128fb_init(void)
+static int aty128fb_init(void)
 {
 #ifndef MODULE
        char *option = NULL;
index 868932f904ef21b85e12b4de1b260bed1c662065..4f27fdc58d8463650fec54d9020496c89810b9bc 100644 (file)
@@ -214,7 +214,7 @@ struct pci_mmap_map {
        unsigned long prot_mask;
 };
 
-static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
+static struct fb_fix_screeninfo atyfb_fix = {
        .id             = "ATY Mach64",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_PSEUDOCOLOR,
@@ -309,18 +309,18 @@ static int vram;
 static int pll;
 static int mclk;
 static int xclk;
-static int comp_sync __devinitdata = -1;
+static int comp_sync = -1;
 static char *mode;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight __devinitdata = 1;
+static int backlight = 1;
 #else
-static int backlight __devinitdata = 0;
+static int backlight = 0;
 #endif
 
 #ifdef CONFIG_PPC
-static int default_vmode __devinitdata = VMODE_CHOOSE;
-static int default_cmode __devinitdata = CMODE_CHOOSE;
+static int default_vmode = VMODE_CHOOSE;
+static int default_cmode = CMODE_CHOOSE;
 
 module_param_named(vmode, default_vmode, int, 0);
 MODULE_PARM_DESC(vmode, "int: video mode for mac");
@@ -329,10 +329,10 @@ MODULE_PARM_DESC(cmode, "int: color mode for mac");
 #endif
 
 #ifdef CONFIG_ATARI
-static unsigned int mach64_count __devinitdata = 0;
-static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, };
-static unsigned long phys_size[FB_MAX] __devinitdata = { 0, };
-static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
+static unsigned int mach64_count = 0;
+static unsigned long phys_vmembase[FB_MAX] = { 0, };
+static unsigned long phys_size[FB_MAX] = { 0, };
+static unsigned long phys_guiregbase[FB_MAX] = { 0, };
 #endif
 
 /* top -> down is an evolution of mach64 chipset, any corrections? */
@@ -371,7 +371,7 @@ static struct {
        const char *name;
        int pll, mclk, xclk, ecp_max;
        u32 features;
-} aty_chips[] __devinitdata = {
+} aty_chips[] = {
 #ifdef CONFIG_FB_ATY_GX
        /* Mach64 GX */
        { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
@@ -426,7 +426,7 @@ static struct {
 #endif /* CONFIG_FB_ATY_CT */
 };
 
-static int __devinit correct_chipset(struct atyfb_par *par)
+static int correct_chipset(struct atyfb_par *par)
 {
        u8 rev;
        u16 type;
@@ -531,34 +531,34 @@ static int __devinit correct_chipset(struct atyfb_par *par)
        return 0;
 }
 
-static char ram_dram[] __devinitdata = "DRAM";
-static char ram_resv[] __devinitdata = "RESV";
+static char ram_dram[] = "DRAM";
+static char ram_resv[] = "RESV";
 #ifdef CONFIG_FB_ATY_GX
-static char ram_vram[] __devinitdata = "VRAM";
+static char ram_vram[] = "VRAM";
 #endif /* CONFIG_FB_ATY_GX */
 #ifdef CONFIG_FB_ATY_CT
-static char ram_edo[] __devinitdata = "EDO";
-static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
-static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
-static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
-static char ram_wram[] __devinitdata = "WRAM";
-static char ram_off[] __devinitdata = "OFF";
+static char ram_edo[] = "EDO";
+static char ram_sdram[] = "SDRAM (1:1)";
+static char ram_sgram[] = "SGRAM (1:1)";
+static char ram_sdram32[] = "SDRAM (2:1) (32-bit)";
+static char ram_wram[] = "WRAM";
+static char ram_off[] = "OFF";
 #endif /* CONFIG_FB_ATY_CT */
 
 
 #ifdef CONFIG_FB_ATY_GX
-static char *aty_gx_ram[8] __devinitdata = {
+static char *aty_gx_ram[8] = {
        ram_dram, ram_vram, ram_vram, ram_dram,
        ram_dram, ram_vram, ram_vram, ram_resv
 };
 #endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
-static char *aty_ct_ram[8] __devinitdata = {
+static char *aty_ct_ram[8] = {
        ram_off, ram_dram, ram_edo, ram_edo,
        ram_sdram, ram_sgram, ram_wram, ram_resv
 };
-static char *aty_xl_ram[8] __devinitdata = {
+static char *aty_xl_ram[8] = {
        ram_off, ram_dram, ram_edo, ram_edo,
        ram_sdram, ram_sgram, ram_sdram32, ram_resv
 };
@@ -588,7 +588,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var,
  * Apple monitor sense
  */
 
-static int __devinit read_aty_sense(const struct atyfb_par *par)
+static int read_aty_sense(const struct atyfb_par *par)
 {
        int sense, i;
 
@@ -2273,7 +2273,7 @@ static void aty_bl_exit(struct backlight_device *bd)
 
 #endif /* CONFIG_FB_ATY_BACKLIGHT */
 
-static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
+static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
 {
        const int ragepro_tbl[] = {
                44, 50, 55, 66, 75, 80, 100
@@ -2307,8 +2307,8 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
 static struct fb_info *fb_list = NULL;
 
 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
-static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
-                                               struct fb_var_screeninfo *var)
+static int atyfb_get_timings_from_lcd(struct atyfb_par *par,
+                                     struct fb_var_screeninfo *var)
 {
        int ret = -EINVAL;
 
@@ -2333,7 +2333,7 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
 }
 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
 
-static int __devinit aty_init(struct fb_info *info)
+static int aty_init(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        const char *ramname = NULL, *xtal;
@@ -2787,7 +2787,7 @@ aty_init_exit:
 }
 
 #if defined(CONFIG_ATARI) && !defined(MODULE)
-static int __devinit store_video_par(char *video_str, unsigned char m64_num)
+static int store_video_par(char *video_str, unsigned char m64_num)
 {
        char *p;
        unsigned long vmembase, size, guiregbase;
@@ -2961,9 +2961,8 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 
 #ifdef __sparc__
 
-static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
-                                      struct fb_info *info,
-                                      unsigned long addr)
+static int atyfb_setup_sparc(struct pci_dev *pdev, struct fb_info *info,
+                            unsigned long addr)
 {
        struct atyfb_par *par = info->par;
        struct device_node *dp;
@@ -3161,7 +3160,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 
 #ifdef __i386__
 #ifdef CONFIG_FB_ATY_GENERIC_LCD
-static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
 {
        u32 driv_inf_tab, sig;
        u16 lcd_ofs;
@@ -3392,7 +3391,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
 }
 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
 
-static int __devinit init_from_bios(struct atyfb_par *par)
+static int init_from_bios(struct atyfb_par *par)
 {
        u32 bios_base, rom_addr;
        int ret;
@@ -3445,9 +3444,8 @@ static int __devinit init_from_bios(struct atyfb_par *par)
 }
 #endif /* __i386__ */
 
-static int __devinit atyfb_setup_generic(struct pci_dev *pdev,
-                                        struct fb_info *info,
-                                        unsigned long addr)
+static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
+                              unsigned long addr)
 {
        struct atyfb_par *par = info->par;
        u16 tmp;
@@ -3525,8 +3523,8 @@ atyfb_setup_generic_fail:
 
 #endif /* !__sparc__ */
 
-static int __devinit atyfb_pci_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int atyfb_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        unsigned long addr, res_start, res_size;
        struct fb_info *info;
@@ -3714,7 +3712,7 @@ static int __init atyfb_atari_probe(void)
 
 #ifdef CONFIG_PCI
 
-static void __devexit atyfb_remove(struct fb_info *info)
+static void atyfb_remove(struct fb_info *info)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
 
@@ -3762,7 +3760,7 @@ static void __devexit atyfb_remove(struct fb_info *info)
 }
 
 
-static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
+static void atyfb_pci_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
 
@@ -3834,7 +3832,7 @@ static struct pci_driver atyfb_driver = {
        .name           = "atyfb",
        .id_table       = atyfb_pci_tbl,
        .probe          = atyfb_pci_probe,
-       .remove         = __devexit_p(atyfb_pci_remove),
+       .remove         = atyfb_pci_remove,
 #ifdef CONFIG_PM
        .suspend        = atyfb_pci_suspend,
        .resume         = atyfb_pci_resume,
index 2745b853948529415b885a91a5104c3d6e3ad026..51f29d627cebce988e18b8a535c12db82fe4e09c 100644 (file)
@@ -373,8 +373,7 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
 #endif
 }
 
-static void __devinit aty_get_pll_ct(const struct fb_info *info,
-                                    union aty_pll *pll)
+static void aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        u8 tmp, clock;
@@ -397,8 +396,7 @@ static void __devinit aty_get_pll_ct(const struct fb_info *info,
        }
 }
 
-static int __devinit aty_init_pll_ct(const struct fb_info *info,
-                                    union aty_pll *pll)
+static int aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
        u8 mpost_div, xpost_div, sclk_post_div_real;
index 46f72ed5351065dadcce9703e012ae92ea1e7d23..95ec042ddbf8ee4f93eda9592ee55f0f6a3c6063 100644 (file)
@@ -183,7 +183,7 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        return 0;
 }
 
-int __devinit aty_init_cursor(struct fb_info *info)
+int aty_init_cursor(struct fb_info *info)
 {
        unsigned long addr;
 
index 9e279ee38da8e976ac1e70a8555fa04f16950212..1e30b2b3e79f3f0cf939272f9d43ce00d692b1d0 100644 (file)
@@ -293,7 +293,7 @@ static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
        pci_unmap_rom(dev, rinfo->bios_seg);
 }
 
-static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
+static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
 {
        void __iomem *rom;
        u16 dptr;
@@ -388,7 +388,7 @@ static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev
 }
 
 #ifdef CONFIG_X86
-static int  __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo)
+static int  radeon_find_mem_vbios(struct radeonfb_info *rinfo)
 {
        /* I simplified this code as we used to miss the signatures in
         * a lot of case. It's now closer to XFree, we just don't check
@@ -423,7 +423,7 @@ static int  __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo)
  * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
  * tree. Hopefully, ATI OF driver is kind enough to fill these
  */
-static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
+static int radeon_read_xtal_OF(struct radeonfb_info *rinfo)
 {
        struct device_node *dp = rinfo->of_node;
        const u32 *val;
@@ -453,7 +453,7 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
 /*
  * Read PLL infos from chip registers
  */
-static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
+static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
 {
        unsigned char ppll_div_sel;
        unsigned Ns, Nm, M;
@@ -591,7 +591,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
 /*
  * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
  */
-static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
 {
        /*
         * In the case nothing works, these are defaults; they are mostly
@@ -1868,7 +1868,7 @@ static struct fb_ops radeonfb_ops = {
 };
 
 
-static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
+static int radeon_set_fbinfo(struct radeonfb_info *rinfo)
 {
        struct fb_info *info = rinfo->info;
 
@@ -2143,8 +2143,8 @@ static struct bin_attribute edid2_attr = {
 };
 
 
-static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int radeonfb_pci_register(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct radeonfb_info *rinfo;
@@ -2407,7 +2407,7 @@ err_out:
 
 
 
-static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
+static void radeonfb_pci_unregister(struct pci_dev *pdev)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
@@ -2465,7 +2465,7 @@ static struct pci_driver radeonfb_driver = {
        .name           = "radeonfb",
        .id_table       = radeonfb_pci_table,
        .probe          = radeonfb_pci_register,
-       .remove         = __devexit_p(radeonfb_pci_unregister),
+       .remove         = radeonfb_pci_unregister,
 #ifdef CONFIG_PM
        .suspend        = radeonfb_pci_suspend,
        .resume         = radeonfb_pci_resume,
index 5c23eac0eb9afe185b27ee871df22db61e78aa3b..bc078d50d8f1b8dd11e8621a9437f9537e55cc67 100644 (file)
@@ -62,8 +62,8 @@ static char *radeon_get_mon_name(int type)
  * models with broken OF probing by hard-coding known EDIDs for some Mac
  * laptops internal LVDS panel. (XXX: not done yet)
  */
-static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
-                                              int hdno)
+static int radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
+                                    int hdno)
 {
         static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
                                     "EDID1", "EDID2",  NULL };
@@ -115,8 +115,8 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
        return mt;
 }
 
-static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
-                                         u8 **out_EDID)
+static int radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
+                               u8 **out_EDID)
 {
         struct device_node *dp;
 
@@ -163,7 +163,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
 #endif /* CONFIG_PPC_OF || CONFIG_SPARC */
 
 
-static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+static int radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
 {
        unsigned long tmp, tmp0;
        char stmp[30];
@@ -251,7 +251,7 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
  * doesn't quite work yet, but it's output is still useful for
  * debugging
  */
-static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo)
+static void radeon_parse_connector_info(struct radeonfb_info *rinfo)
 {
        int offset, chips, connectors, tmp, i, conn, type;
 
@@ -297,7 +297,7 @@ static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo)
  * as well and currently is only implemented for the CRT DAC, the
  * code for the TVDAC is commented out in XFree as "non working"
  */
-static int __devinit radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)
+static int radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)
 {
     int                  connected = 0;
 
@@ -369,8 +369,8 @@ static int __devinit radeon_crt_is_connected(struct radeonfb_info *rinfo, int is
  * Parse the "monitor_layout" string if any. This code is mostly
  * copied from XFree's radeon driver
  */
-static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
-                                                const char *monitor_layout)
+static int radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
+                                      const char *monitor_layout)
 {
        char s1[5], s2[5];
        int i = 0, second = 0;
@@ -433,8 +433,8 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
  * try to retrieve EDID. The algorithm here comes from XFree's radeon
  * driver
  */
-void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
-                                   const char *monitor_layout, int ignore_edid)
+void radeon_probe_screens(struct radeonfb_info *rinfo,
+                         const char *monitor_layout, int ignore_edid)
 {
 #ifdef CONFIG_FB_RADEON_I2C
        int ddc_crt2_used = 0;  
@@ -753,7 +753,7 @@ static int is_powerblade(const char *model)
  * Build the modedb for head 1 (head 2 will come later), check panel infos
  * from either BIOS or EDID, and pick up the default mode
  */
-void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
+void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
 {
        struct fb_info * info = rinfo->info;
        int has_default_mode = 0;
index fe3b6ec87122eefb6f2b8d1d36ed3303a6d754e3..ddabaa867b0dc38e24ab090d6e62108c88a02a2c 100644 (file)
@@ -83,7 +83,7 @@ struct fb_bitfield rgb_bitfields[][4] =
        { { 8, 4, 0 },  { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
 };
 
-static struct fb_fix_screeninfo au1100fb_fix __devinitdata = {
+static struct fb_fix_screeninfo au1100fb_fix = {
        .id             = "AU1100 FB",
        .xpanstep       = 1,
        .ypanstep       = 1,
@@ -91,7 +91,7 @@ static struct fb_fix_screeninfo au1100fb_fix __devinitdata = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo au1100fb_var __devinitdata = {
+static struct fb_var_screeninfo au1100fb_var = {
        .activate       = FB_ACTIVATE_NOW,
        .height         = -1,
        .width          = -1,
@@ -469,7 +469,7 @@ static int au1100fb_setup(struct au1100fb_device *fbdev)
        return 0;
 }
 
-static int __devinit au1100fb_drv_probe(struct platform_device *dev)
+static int au1100fb_drv_probe(struct platform_device *dev)
 {
        struct au1100fb_device *fbdev = NULL;
        struct resource *regs_res;
index 7ca79f02056ebc9d967af326800687529dae37a8..1b59054fc6a4ccb5b2c2c12ca9ceb6070ed53bd2 100644 (file)
@@ -1673,7 +1673,7 @@ out:
 }
 
 /* AU1200 LCD controller device driver */
-static int __devinit au1200fb_drv_probe(struct platform_device *dev)
+static int au1200fb_drv_probe(struct platform_device *dev)
 {
        struct au1200fb_device *fbdev;
        struct au1200fb_platdata *pd;
@@ -1798,7 +1798,7 @@ failed:
        return ret;
 }
 
-static int __devexit au1200fb_drv_remove(struct platform_device *dev)
+static int au1200fb_drv_remove(struct platform_device *dev)
 {
        struct au1200fb_platdata *pd = platform_get_drvdata(dev);
        struct au1200fb_device *fbdev;
@@ -1876,7 +1876,7 @@ static struct platform_driver au1200fb_driver = {
                .pm     = AU1200FB_PMOPS,
        },
        .probe          = au1200fb_drv_probe,
-       .remove         = __devexit_p(au1200fb_drv_remove),
+       .remove         = au1200fb_drv_remove,
 };
 
 /*-------------------------------------------------------------------------*/
index c36cf961dcb2df0bf555dc0729aca43263db0d09..1a9ac6e1f4b3657101834736ca24c80543a067fb 100644 (file)
@@ -156,7 +156,7 @@ static bool auok1900fb_need_refresh(struct auok190xfb_par *par)
        return (par->update_cnt > 10);
 }
 
-static int __devinit auok1900fb_probe(struct platform_device *pdev)
+static int auok1900fb_probe(struct platform_device *pdev)
 {
        struct auok190x_init_data init;
        struct auok190x_board *board;
@@ -177,14 +177,14 @@ static int __devinit auok1900fb_probe(struct platform_device *pdev)
        return auok190x_common_probe(pdev, &init);
 }
 
-static int __devexit auok1900fb_remove(struct platform_device *pdev)
+static int auok1900fb_remove(struct platform_device *pdev)
 {
        return auok190x_common_remove(pdev);
 }
 
 static struct platform_driver auok1900fb_driver = {
        .probe  = auok1900fb_probe,
-       .remove = __devexit_p(auok1900fb_remove),
+       .remove = auok1900fb_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "auo_k1900fb",
index 1c054c18616e38c6fc55cca8bd9679c017b1170a..d1db1653cd88546bb0855786093c367ad3887c37 100644 (file)
@@ -209,7 +209,7 @@ static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
        return (par->update_cnt > 10);
 }
 
-static int __devinit auok1901fb_probe(struct platform_device *pdev)
+static int auok1901fb_probe(struct platform_device *pdev)
 {
        struct auok190x_init_data init;
        struct auok190x_board *board;
@@ -230,14 +230,14 @@ static int __devinit auok1901fb_probe(struct platform_device *pdev)
        return auok190x_common_probe(pdev, &init);
 }
 
-static int __devexit auok1901fb_remove(struct platform_device *pdev)
+static int auok1901fb_remove(struct platform_device *pdev)
 {
        return auok190x_common_remove(pdev);
 }
 
 static struct platform_driver auok1901fb_driver = {
        .probe  = auok1901fb_probe,
-       .remove = __devexit_p(auok1901fb_remove),
+       .remove = auok1901fb_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "auo_k1901fb",
index c03ecdd31e4c6133f31a54c143038682c694dc87..97f79356141e535de24886dbae9e2873da0f4095 100644 (file)
@@ -773,8 +773,8 @@ EXPORT_SYMBOL_GPL(auok190x_pm);
  * Common probe and remove code
  */
 
-int __devinit auok190x_common_probe(struct platform_device *pdev,
-                                   struct auok190x_init_data *init)
+int auok190x_common_probe(struct platform_device *pdev,
+                         struct auok190x_init_data *init)
 {
        struct auok190x_board *board = init->board;
        struct auok190xfb_par *par;
@@ -1006,7 +1006,7 @@ err_reg:
 }
 EXPORT_SYMBOL_GPL(auok190x_common_probe);
 
-int  __devexit auok190x_common_remove(struct platform_device *pdev)
+int  auok190x_common_remove(struct platform_device *pdev)
 {
        struct fb_info *info = platform_get_drvdata(pdev);
        struct auok190xfb_par *par = info->par;
index 7347aa1e5e4ac1e9957510b19889d1d3446784e0..a82d2578d976e9ad67b862ab66ddef64cb46029e 100644 (file)
@@ -87,8 +87,8 @@ static void set_vcomm(void)
                pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
 }
 
-static int __devinit ad5280_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
+static int ad5280_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        int ret;
        if (!i2c_check_functionality(client->adapter,
@@ -108,7 +108,7 @@ static int __devinit ad5280_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit ad5280_remove(struct i2c_client *client)
+static int ad5280_remove(struct i2c_client *client)
 {
        ad5280_client = NULL;
        return 0;
@@ -126,7 +126,7 @@ static struct i2c_driver ad5280_driver = {
                .name = "bf537-lq035-ad5280",
        },
        .probe = ad5280_probe,
-       .remove = __devexit_p(ad5280_remove),
+       .remove = ad5280_remove,
        .id_table = ad5280_id,
 };
 
@@ -360,7 +360,7 @@ static int config_dma(void)
        return 0;
 }
 
-static int __devinit request_ports(void)
+static int request_ports(void)
 {
        u16 tmr_req[] = TIMERS;
 
@@ -443,7 +443,7 @@ static struct fb_var_screeninfo bfin_lq035_fb_defined = {
        .transp         = {0, 0, 0},
 };
 
-static struct fb_fix_screeninfo bfin_lq035_fb_fix __devinitdata = {
+static struct fb_fix_screeninfo bfin_lq035_fb_fix = {
        .id             = KBUILD_MODNAME,
        .smem_len       = ACTIVE_VIDEO_MEM_SIZE,
        .type           = FB_TYPE_PACKED_PIXELS,
@@ -686,7 +686,7 @@ static struct lcd_ops bfin_lcd_ops = {
 
 static struct lcd_device *lcd_dev;
 
-static int __devinit bfin_lq035_probe(struct platform_device *pdev)
+static int bfin_lq035_probe(struct platform_device *pdev)
 {
        struct backlight_properties props;
        dma_addr_t dma_handle;
@@ -816,7 +816,7 @@ out_ports:
        return ret;
 }
 
-static int __devexit bfin_lq035_remove(struct platform_device *pdev)
+static int bfin_lq035_remove(struct platform_device *pdev)
 {
        if (fb_buffer != NULL)
                dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
@@ -889,7 +889,7 @@ static int bfin_lq035_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_lq035_driver = {
        .probe = bfin_lq035_probe,
-       .remove = __devexit_p(bfin_lq035_remove),
+       .remove = bfin_lq035_remove,
        .suspend = bfin_lq035_suspend,
        .resume = bfin_lq035_resume,
        .driver = {
index ff5663f5c64f5d1dbb97448b27658c8f3ea62272..2726a5b6674129ef8b16938f669577929572ba8e 100644 (file)
@@ -497,7 +497,7 @@ static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
+static int bfin_bf54x_probe(struct platform_device *pdev)
 {
 #ifndef NO_BL_SUPPORT
        struct backlight_properties props;
@@ -686,7 +686,7 @@ out1:
        return ret;
 }
 
-static int __devexit bfin_bf54x_remove(struct platform_device *pdev)
+static int bfin_bf54x_remove(struct platform_device *pdev)
 {
 
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
@@ -754,7 +754,7 @@ static int bfin_bf54x_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_bf54x_driver = {
        .probe = bfin_bf54x_probe,
-       .remove = __devexit_p(bfin_bf54x_remove),
+       .remove = bfin_bf54x_remove,
        .suspend = bfin_bf54x_suspend,
        .resume = bfin_bf54x_resume,
        .driver = {
index 6fbc75c2f0a10bc77c8176e5bd05e6eb1dfc940c..29d8c0443a1f618203e70e65402f5557d679a000 100644 (file)
@@ -137,7 +137,7 @@ static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned s
        return ret;
 }
 
-static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
+static int lq035q1_spidev_probe(struct spi_device *spi)
 {
        int ret;
        struct spi_control *ctl;
@@ -358,8 +358,8 @@ static inline void bfin_lq035q1_free_ports(unsigned ppi16)
                gpio_free(P_IDENT(P_PPI0_FS3));
 }
 
-static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev,
-                                               unsigned ppi16)
+static int bfin_lq035q1_request_ports(struct platform_device *pdev,
+                                     unsigned ppi16)
 {
        int ret;
        /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
@@ -555,7 +555,7 @@ static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
+static int bfin_lq035q1_probe(struct platform_device *pdev)
 {
        struct bfin_lq035q1fb_info *info;
        struct fb_info *fbinfo;
@@ -706,7 +706,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
 
        info->spidrv.driver.name = DRIVER_NAME"-spi";
        info->spidrv.probe    = lq035q1_spidev_probe;
-       info->spidrv.remove   = __devexit_p(lq035q1_spidev_remove);
+       info->spidrv.remove   = lq035q1_spidev_remove;
        info->spidrv.shutdown = lq035q1_spidev_shutdown;
        info->spidrv.suspend  = lq035q1_spidev_suspend;
        info->spidrv.resume   = lq035q1_spidev_resume;
@@ -764,7 +764,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit bfin_lq035q1_remove(struct platform_device *pdev)
+static int bfin_lq035q1_remove(struct platform_device *pdev)
 {
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
        struct bfin_lq035q1fb_info *info = fbinfo->par;
@@ -845,7 +845,7 @@ static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
 
 static struct platform_driver bfin_lq035q1_driver = {
        .probe   = bfin_lq035q1_probe,
-       .remove  = __devexit_p(bfin_lq035q1_remove),
+       .remove  = bfin_lq035q1_remove,
        .driver = {
                .name = DRIVER_NAME,
 #ifdef CONFIG_PM
index ae0fb24b8b4330a6228db62081faf52b0cf8fad6..d46da01c31ae5536ddf10dfa3b0b443c2ff6dc2f 100644 (file)
@@ -418,7 +418,7 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
+static int bfin_t350mcqb_probe(struct platform_device *pdev)
 {
 #ifndef NO_BL_SUPPORT
        struct backlight_properties props;
@@ -583,7 +583,7 @@ out1:
        return ret;
 }
 
-static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)
+static int bfin_t350mcqb_remove(struct platform_device *pdev)
 {
 
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
@@ -658,7 +658,7 @@ static int bfin_t350mcqb_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_t350mcqb_driver = {
        .probe = bfin_t350mcqb_probe,
-       .remove = __devexit_p(bfin_t350mcqb_remove),
+       .remove = bfin_t350mcqb_remove,
        .suspend = bfin_t350mcqb_suspend,
        .resume = bfin_t350mcqb_resume,
        .driver = {
index d0f121bd8b25d113567751cee8d562cd4bfa58f7..8d411a3c9966763a84ad4d1f4025b94593481f70 100644 (file)
@@ -88,7 +88,7 @@ static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
        .transp = {0, 0, 0},
 };
 
-static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = {
+static struct fb_fix_screeninfo bfin_adv7393_fb_fix = {
        .id = "BFIN ADV7393",
        .smem_len = 720 * 480 * 2,
        .type = FB_TYPE_PACKED_PIXELS,
@@ -368,8 +368,8 @@ adv7393_write_proc(struct file *file, const char __user * buffer,
        return count;
 }
 
-static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
-                                          const struct i2c_device_id *id)
+static int bfin_adv7393_fb_probe(struct i2c_client *client,
+                                const struct i2c_device_id *id)
 {
        int ret = 0;
        struct proc_dir_entry *entry;
@@ -719,7 +719,7 @@ static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
        return 0;
 }
 
-static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client)
+static int bfin_adv7393_fb_remove(struct i2c_client *client)
 {
        struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
 
@@ -794,7 +794,7 @@ static struct i2c_driver bfin_adv7393_fb_driver = {
 #endif
        },
        .probe = bfin_adv7393_fb_probe,
-       .remove = __devexit_p(bfin_adv7393_fb_remove),
+       .remove = bfin_adv7393_fb_remove,
        .id_table = bfin_adv7393_id,
 };
 
index c95b417d0d41ae037cbcb4a01ff01c575e1b0aab..b09701c7943272abc934afd7c6821620d319ac51 100644 (file)
@@ -91,7 +91,7 @@ static struct panel_info panel_table[] = {
 #define DPY_W 800
 #define DPY_H 600
 
-static struct fb_fix_screeninfo broadsheetfb_fix __devinitdata = {
+static struct fb_fix_screeninfo broadsheetfb_fix = {
        .id =           "broadsheetfb",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_STATIC_PSEUDOCOLOR,
@@ -102,7 +102,7 @@ static struct fb_fix_screeninfo broadsheetfb_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo broadsheetfb_var __devinitdata = {
+static struct fb_var_screeninfo broadsheetfb_var = {
        .xres           = DPY_W,
        .yres           = DPY_H,
        .xres_virtual   = DPY_W,
@@ -774,7 +774,7 @@ static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
                        broadsheet_loadstore_waveform);
 
 /* upper level functions that manipulate the display and other stuff */
-static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
+static void broadsheet_init_display(struct broadsheetfb_par *par)
 {
        u16 args[5];
        int xres = par->info->var.xres;
@@ -834,7 +834,7 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
        par->board->wait_for_rdy(par);
 }
 
-static void __devinit broadsheet_identify(struct broadsheetfb_par *par)
+static void broadsheet_identify(struct broadsheetfb_par *par)
 {
        u16 rev, prc;
        struct device *dev = par->info->device;
@@ -849,7 +849,7 @@ static void __devinit broadsheet_identify(struct broadsheetfb_par *par)
                dev_warn(dev, "Unrecognized Broadsheet Revision\n");
 }
 
-static void __devinit broadsheet_init(struct broadsheetfb_par *par)
+static void broadsheet_init(struct broadsheetfb_par *par)
 {
        broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
        /* the controller needs a second */
@@ -1058,7 +1058,7 @@ static struct fb_deferred_io broadsheetfb_defio = {
        .deferred_io    = broadsheetfb_dpy_deferred_io,
 };
 
-static int __devinit broadsheetfb_probe(struct platform_device *dev)
+static int broadsheetfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct broadsheet_board *board;
@@ -1190,7 +1190,7 @@ err:
 
 }
 
-static int __devexit broadsheetfb_remove(struct platform_device *dev)
+static int broadsheetfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -1211,7 +1211,7 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev)
 
 static struct platform_driver broadsheetfb_driver = {
        .probe  = broadsheetfb_probe,
-       .remove = __devexit_p(broadsheetfb_remove),
+       .remove = broadsheetfb_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "broadsheetfb",
index 6bea9a9367989f314aaf389ca07d9d5ef24d0833..60017fc634b57462a92f388f531dbb17efeda235 100644 (file)
@@ -179,7 +179,7 @@ static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  *  Initialisation
  */
 
-static void __devinit bw2_init_fix(struct fb_info *info, int linebytes)
+static void bw2_init_fix(struct fb_info *info, int linebytes)
 {
        strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
 
@@ -191,44 +191,43 @@ static void __devinit bw2_init_fix(struct fb_info *info, int linebytes)
        info->fix.accel = FB_ACCEL_SUN_BWTWO;
 }
 
-static u8 bw2regs_1600[] __devinitdata = {
+static u8 bw2regs_1600[] = {
        0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
        0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
        0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x21,     0
 };
 
-static u8 bw2regs_ecl[] __devinitdata = {
+static u8 bw2regs_ecl[] = {
        0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
        0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
        0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x20,     0
 };
 
-static u8 bw2regs_analog[] __devinitdata = {
+static u8 bw2regs_analog[] = {
        0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
        0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
        0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x20,     0
 };
 
-static u8 bw2regs_76hz[] __devinitdata = {
+static u8 bw2regs_76hz[] = {
        0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
        0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
        0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x24,     0
 };
 
-static u8 bw2regs_66hz[] __devinitdata = {
+static u8 bw2regs_66hz[] = {
        0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
        0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
        0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x20,     0
 };
 
-static int __devinit bw2_do_default_mode(struct bw2_par *par,
-                                        struct fb_info *info,
-                                        int *linebytes)
+static int bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
+                              int *linebytes)
 {
        u8 status, mon;
        u8 *p;
@@ -273,7 +272,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
        return 0;
 }
 
-static int __devinit bw2_probe(struct platform_device *op)
+static int bw2_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -352,7 +351,7 @@ out_err:
        return err;
 }
 
-static int __devexit bw2_remove(struct platform_device *op)
+static int bw2_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct bw2_par *par = info->par;
@@ -384,7 +383,7 @@ static struct platform_driver bw2_driver = {
                .of_match_table = bw2_match,
        },
        .probe          = bw2_probe,
-       .remove         = __devexit_p(bw2_remove),
+       .remove         = bw2_remove,
 };
 
 static int __init bw2_init(void)
index 2c76fdf23f2ac5347989e1783beed7789872aac0..153dd65b0ae80c32ebcbe857cb43fb768820ffb8 100644 (file)
@@ -78,7 +78,7 @@ struct carmine_fb {
        u32 pseudo_palette[16];
 };
 
-static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
+static struct fb_fix_screeninfo carminefb_fix = {
        .id = "Carmine",
        .type = FB_TYPE_PACKED_PIXELS,
        .visual = FB_VISUAL_TRUECOLOR,
@@ -537,8 +537,9 @@ static struct fb_ops carminefb_ops = {
        .fb_setcolreg   = carmine_setcolreg,
 };
 
-static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
-               int smem_offset, struct device *device, struct fb_info **rinfo)
+static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+                           int smem_offset, struct device *device,
+                           struct fb_info **rinfo)
 {
        int ret;
        struct fb_info *info;
@@ -606,8 +607,7 @@ static void cleanup_fb_device(struct fb_info *info)
        }
 }
 
-static int __devinit carminefb_probe(struct pci_dev *dev,
-               const struct pci_device_id *ent)
+static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct carmine_hw *hw;
        struct device *device = &dev->dev;
@@ -721,7 +721,7 @@ err_enable_pci:
        return ret;
 }
 
-static void __devexit carminefb_remove(struct pci_dev *dev)
+static void carminefb_remove(struct pci_dev *dev)
 {
        struct carmine_hw *hw = pci_get_drvdata(dev);
        struct fb_fix_screeninfo fix;
@@ -752,7 +752,7 @@ static void __devexit carminefb_remove(struct pci_dev *dev)
 }
 
 #define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
-static struct pci_device_id carmine_devices[] __devinitdata = {
+static struct pci_device_id carmine_devices[] = {
 {
        PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
        {0, 0, 0, 0, 0, 0, 0}
@@ -764,7 +764,7 @@ static struct pci_driver carmine_pci_driver = {
        .name           = "carminefb",
        .id_table       = carmine_devices,
        .probe          = carminefb_probe,
-       .remove         = __devexit_p(carminefb_remove),
+       .remove         = carminefb_remove,
 };
 
 static int __init carminefb_init(void)
index f1889500662757d337d066648964e685d53e7f78..ed3b8891e0068e25cf0ba7a22b416536b8ff91ee 100644 (file)
@@ -352,8 +352,8 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  *  Initialisation
  */
 
-static void __devinit cg14_init_fix(struct fb_info *info, int linebytes,
-                                   struct device_node *dp)
+static void cg14_init_fix(struct fb_info *info, int linebytes,
+                         struct device_node *dp)
 {
        const char *name = dp->name;
 
@@ -367,7 +367,7 @@ static void __devinit cg14_init_fix(struct fb_info *info, int linebytes,
        info->fix.accel = FB_ACCEL_SUN_CG14;
 }
 
-static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
+static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = {
        {
                .voff   = CG14_REGS,
                .poff   = 0x80000000,
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
                           info->screen_base, info->fix.smem_len);
 }
 
-static int __devinit cg14_probe(struct platform_device *op)
+static int cg14_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -571,7 +571,7 @@ out_err:
        return err;
 }
 
-static int __devexit cg14_remove(struct platform_device *op)
+static int cg14_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct cg14_par *par = info->par;
@@ -603,7 +603,7 @@ static struct platform_driver cg14_driver = {
                .of_match_table = cg14_match,
        },
        .probe          = cg14_probe,
-       .remove         = __devexit_p(cg14_remove),
+       .remove         = cg14_remove,
 };
 
 static int __init cg14_init(void)
index c5e7612ff8760609152eea65fc6f7bb6e6db872c..9f63507ded373621cfa74524fd0f27ddd205cacc 100644 (file)
@@ -243,8 +243,8 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  *  Initialisation
  */
 
-static void __devinit cg3_init_fix(struct fb_info *info, int linebytes,
-                                  struct device_node *dp)
+static void cg3_init_fix(struct fb_info *info, int linebytes,
+                        struct device_node *dp)
 {
        strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
 
@@ -256,8 +256,8 @@ static void __devinit cg3_init_fix(struct fb_info *info, int linebytes,
        info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 }
 
-static void __devinit cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
-                                             struct device_node *dp)
+static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
+                                   struct device_node *dp)
 {
        const char *params;
        char *p;
@@ -279,36 +279,36 @@ static void __devinit cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
        }
 }
 
-static u8 cg3regvals_66hz[] __devinitdata = {  /* 1152 x 900, 66 Hz */
+static u8 cg3regvals_66hz[] = {        /* 1152 x 900, 66 Hz */
        0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
        0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
        0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x20,     0
 };
 
-static u8 cg3regvals_76hz[] __devinitdata = {  /* 1152 x 900, 76 Hz */
+static u8 cg3regvals_76hz[] = {        /* 1152 x 900, 76 Hz */
        0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
        0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
        0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x24,     0
 };
 
-static u8 cg3regvals_rdi[] __devinitdata = {   /* 640 x 480, cgRDI */
+static u8 cg3regvals_rdi[] = { /* 640 x 480, cgRDI */
        0x14, 0x70,     0x15, 0x20,     0x16, 0x08,     0x17, 0x10,
        0x18, 0x06,     0x19, 0x02,     0x1a, 0x31,     0x1b, 0x51,
        0x1c, 0x06,     0x1d, 0x0c,     0x1e, 0xff,     0x1f, 0x01,
        0x10, 0x22,     0
 };
 
-static u8 *cg3_regvals[] __devinitdata = {
+static u8 *cg3_regvals[] = {
        cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
 };
 
-static u_char cg3_dacvals[] __devinitdata = {
+static u_char cg3_dacvals[] = {
        4, 0xff,        5, 0x00,        6, 0x70,        7, 0x00,        0
 };
 
-static int __devinit cg3_do_default_mode(struct cg3_par *par)
+static int cg3_do_default_mode(struct cg3_par *par)
 {
        enum cg3_type type;
        u8 *p;
@@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
        return 0;
 }
 
-static int __devinit cg3_probe(struct platform_device *op)
+static int cg3_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -433,7 +433,7 @@ out_err:
        return err;
 }
 
-static int __devexit cg3_remove(struct platform_device *op)
+static int cg3_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct cg3_par *par = info->par;
@@ -469,7 +469,7 @@ static struct platform_driver cg3_driver = {
                .of_match_table = cg3_match,
        },
        .probe          = cg3_probe,
-       .remove         = __devexit_p(cg3_remove),
+       .remove         = cg3_remove,
 };
 
 static int __init cg3_init(void)
index 179e96cdb323fa9e91f22f42be016f55a32993ea..3545decc748528b4cec5c16369da88a0f6e4469a 100644 (file)
@@ -607,7 +607,7 @@ static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  *  Initialisation
  */
 
-static void __devinit cg6_init_fix(struct fb_info *info, int linebytes)
+static void cg6_init_fix(struct fb_info *info, int linebytes)
 {
        struct cg6_par *par = (struct cg6_par *)info->par;
        const char *cg6_cpu_name, *cg6_card_name;
@@ -649,7 +649,7 @@ static void __devinit cg6_init_fix(struct fb_info *info, int linebytes)
 }
 
 /* Initialize Brooktree DAC */
-static void __devinit cg6_bt_init(struct cg6_par *par)
+static void cg6_bt_init(struct cg6_par *par)
 {
        struct bt_regs __iomem *bt = par->bt;
 
@@ -663,7 +663,7 @@ static void __devinit cg6_bt_init(struct cg6_par *par)
        sbus_writel(0x00 << 24, &bt->control);
 }
 
-static void __devinit cg6_chip_init(struct fb_info *info)
+static void cg6_chip_init(struct fb_info *info)
 {
        struct cg6_par *par = (struct cg6_par *)info->par;
        struct cg6_tec __iomem *tec = par->tec;
@@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
                           info->fix.smem_len);
 }
 
-static int __devinit cg6_probe(struct platform_device *op)
+static int cg6_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -827,7 +827,7 @@ out_err:
        return err;
 }
 
-static int __devexit cg6_remove(struct platform_device *op)
+static int cg6_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct cg6_par *par = info->par;
@@ -862,7 +862,7 @@ static struct platform_driver cg6_driver = {
                .of_match_table = cg6_match,
        },
        .probe          = cg6_probe,
-       .remove         = __devexit_p(cg6_remove),
+       .remove         = cg6_remove,
 };
 
 static int __init cg6_init(void)
index cff742abdc5d4ce998e9e7819487cee271761f80..206a66b61072f5d1bd97c6d21453b0a9e6f99f18 100644 (file)
@@ -292,7 +292,7 @@ static void __init chips_hw_init(void)
                write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 }
 
-static struct fb_fix_screeninfo chipsfb_fix __devinitdata = {
+static struct fb_fix_screeninfo chipsfb_fix = {
        .id =           "C&T 65550",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -309,7 +309,7 @@ static struct fb_fix_screeninfo chipsfb_fix __devinitdata = {
        .smem_len =     0x100000,       /* 1MB */
 };
 
-static struct fb_var_screeninfo chipsfb_var __devinitdata = {
+static struct fb_var_screeninfo chipsfb_var = {
        .xres = 800,
        .yres = 600,
        .xres_virtual = 800,
@@ -330,7 +330,7 @@ static struct fb_var_screeninfo chipsfb_var __devinitdata = {
        .vsync_len = 8,
 };
 
-static void __devinit init_chips(struct fb_info *p, unsigned long addr)
+static void init_chips(struct fb_info *p, unsigned long addr)
 {
        memset(p->screen_base, 0, 0x100000);
 
@@ -347,8 +347,7 @@ static void __devinit init_chips(struct fb_info *p, unsigned long addr)
        chips_hw_init();
 }
 
-static int __devinit
-chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
+static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
 {
        struct fb_info *p;
        unsigned long addr, size;
@@ -438,7 +437,7 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        return rc;
 }
 
-static void __devexit chipsfb_remove(struct pci_dev *dp)
+static void chipsfb_remove(struct pci_dev *dp)
 {
        struct fb_info *p = pci_get_drvdata(dp);
 
@@ -495,7 +494,7 @@ static struct pci_driver chipsfb_driver = {
        .name =         "chipsfb",
        .id_table =     chipsfb_pci_tbl,
        .probe =        chipsfb_pci_init,
-       .remove =       __devexit_p(chipsfb_remove),
+       .remove =       chipsfb_remove,
 #ifdef CONFIG_PM
        .suspend =      chipsfb_pci_suspend,
        .resume =       chipsfb_pci_resume,
index bc67d05cad60f0d31b34548f17a1176891710bf2..c3dbbe6e3acf42f9353fe6d79e6eee929acc3560 100644 (file)
@@ -290,34 +290,34 @@ struct zorrocl {
        zorro_id ramid2;        /* Zorro ID of optional second RAM device */
 };
 
-static const struct zorrocl zcl_sd64 __devinitconst = {
+static const struct zorrocl zcl_sd64 = {
        .type           = BT_SD64,
        .ramid          = ZORRO_PROD_HELFRICH_SD64_RAM,
 };
 
-static const struct zorrocl zcl_piccolo __devinitconst = {
+static const struct zorrocl zcl_piccolo = {
        .type           = BT_PICCOLO,
        .ramid          = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
 };
 
-static const struct zorrocl zcl_picasso __devinitconst = {
+static const struct zorrocl zcl_picasso = {
        .type           = BT_PICASSO,
        .ramid          = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
 };
 
-static const struct zorrocl zcl_spectrum __devinitconst = {
+static const struct zorrocl zcl_spectrum = {
        .type           = BT_SPECTRUM,
        .ramid          = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
 };
 
-static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
+static const struct zorrocl zcl_picasso4_z3 = {
        .type           = BT_PICASSO4,
        .regoffset      = 0x00600000,
        .ramsize        = 4 * MB_,
        .ramoffset      = 0x01000000,   /* 0x02000000 for 64 MiB boards */
 };
 
-static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
+static const struct zorrocl zcl_picasso4_z2 = {
        .type           = BT_PICASSO4,
        .regoffset      = 0x10000,
        .ramid          = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
@@ -325,7 +325,7 @@ static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
 };
 
 
-static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
+static const struct zorro_device_id cirrusfb_zorro_table[] = {
        {
                .id             = ZORRO_PROD_HELFRICH_SD64_REG,
                .driver_data    = (unsigned long)&zcl_sd64,
@@ -372,8 +372,8 @@ struct cirrusfb_info {
        void (*unmap)(struct fb_info *info);
 };
 
-static bool noaccel __devinitdata;
-static char *mode_option __devinitdata = "640x480@60";
+static bool noaccel;
+static char *mode_option = "640x480@60";
 
 /****************************************************************************/
 /**** BEGIN PROTOTYPES ******************************************************/
@@ -1892,8 +1892,8 @@ static int release_io_ports;
  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
  * seem to have. */
-static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info,
-                                                  u8 __iomem *regbase)
+static unsigned int cirrusfb_get_memsize(struct fb_info *info,
+                                        u8 __iomem *regbase)
 {
        unsigned long mem;
        struct cirrusfb_info *cinfo = info->par;
@@ -2003,7 +2003,7 @@ static struct fb_ops cirrusfb_ops = {
        .fb_imageblit   = cirrusfb_imageblit,
 };
 
-static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
+static int cirrusfb_set_fbinfo(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
        struct fb_var_screeninfo *var = &info->var;
@@ -2052,7 +2052,7 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
        return 0;
 }
 
-static int __devinit cirrusfb_register(struct fb_info *info)
+static int cirrusfb_register(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
        int err;
@@ -2096,7 +2096,7 @@ err_dealloc_cmap:
        return err;
 }
 
-static void __devexit cirrusfb_cleanup(struct fb_info *info)
+static void cirrusfb_cleanup(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
 
@@ -2109,8 +2109,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info)
 }
 
 #ifdef CONFIG_PCI
-static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
-                                          const struct pci_device_id *ent)
+static int cirrusfb_pci_register(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
@@ -2215,7 +2215,7 @@ err_out:
        return ret;
 }
 
-static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev)
+static void cirrusfb_pci_unregister(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
 
@@ -2226,7 +2226,7 @@ static struct pci_driver cirrusfb_pci_driver = {
        .name           = "cirrusfb",
        .id_table       = cirrusfb_pci_table,
        .probe          = cirrusfb_pci_register,
-       .remove         = __devexit_p(cirrusfb_pci_unregister),
+       .remove         = cirrusfb_pci_unregister,
 #ifdef CONFIG_PM
 #if 0
        .suspend        = cirrusfb_pci_suspend,
@@ -2237,8 +2237,8 @@ static struct pci_driver cirrusfb_pci_driver = {
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_ZORRO
-static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
-                                            const struct zorro_device_id *ent)
+static int cirrusfb_zorro_register(struct zorro_dev *z,
+                                  const struct zorro_device_id *ent)
 {
        struct fb_info *info;
        int error;
@@ -2352,7 +2352,7 @@ err_release_fb:
        return error;
 }
 
-void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
+void cirrusfb_zorro_unregister(struct zorro_dev *z)
 {
        struct fb_info *info = zorro_get_drvdata(z);
 
@@ -2364,7 +2364,7 @@ static struct zorro_driver cirrusfb_zorro_driver = {
        .name           = "cirrusfb",
        .id_table       = cirrusfb_zorro_table,
        .probe          = cirrusfb_zorro_register,
-       .remove         = __devexit_p(cirrusfb_zorro_unregister),
+       .remove         = cirrusfb_zorro_unregister,
 };
 #endif /* CONFIG_ZORRO */
 
index 63ecdf8f7baf185fd863ef1c0c64acc291cbcb43..5a7af0deced2607383200118cb7c66d89b6219af 100644 (file)
@@ -178,7 +178,7 @@ static struct fb_ops clps7111fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static void __devinit clps711x_guess_lcd_params(struct fb_info *info)
+static void clps711x_guess_lcd_params(struct fb_info *info)
 {
        unsigned int lcdcon, syscon, size;
        unsigned long phys_base = PAGE_OFFSET;
@@ -266,7 +266,7 @@ static void __devinit clps711x_guess_lcd_params(struct fb_info *info)
        info->fix.type       = FB_TYPE_PACKED_PIXELS;
 }
 
-static int __devinit clps711x_fb_probe(struct platform_device *pdev)
+static int clps711x_fb_probe(struct platform_device *pdev)
 {
        int err = -ENOMEM;
 
@@ -291,7 +291,7 @@ static int __devinit clps711x_fb_probe(struct platform_device *pdev)
 out:   return err;
 }
 
-static int __devexit clps711x_fb_remove(struct platform_device *pdev)
+static int clps711x_fb_remove(struct platform_device *pdev)
 {
        unregister_framebuffer(cfb);
        kfree(cfb);
@@ -305,7 +305,7 @@ static struct platform_driver clps711x_fb_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = clps711x_fb_probe,
-       .remove = __devexit_p(clps711x_fb_remove),
+       .remove = clps711x_fb_remove,
 };
 module_platform_driver(clps711x_fb_driver);
 
index 01a4ee7cc6b1b069be59593fa9baef0ec37c3176..a9031498e10c9f38b45b39bdfa848a528bd58128 100644 (file)
@@ -167,7 +167,7 @@ static void lcd_clear(struct fb_info *info)
        lcd_write_control(info, LCD_RESET);
 }
 
-static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = {
+static struct fb_fix_screeninfo cobalt_lcdfb_fix = {
        .id             = "cobalt-lcd",
        .type           = FB_TYPE_TEXT,
        .type_aux       = FB_AUX_TEXT_MDA,
@@ -331,7 +331,7 @@ static struct fb_ops cobalt_lcd_fbops = {
        .fb_cursor      = cobalt_lcdfb_cursor,
 };
 
-static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
+static int cobalt_lcdfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct resource *res;
@@ -374,7 +374,7 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
        return 0;
 }
 
-static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
+static int cobalt_lcdfb_remove(struct platform_device *dev)
 {
        struct fb_info *info;
 
@@ -389,7 +389,7 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
 
 static struct platform_driver cobalt_lcdfb_driver = {
        .probe  = cobalt_lcdfb_probe,
-       .remove = __devexit_p(cobalt_lcdfb_remove),
+       .remove = cobalt_lcdfb_remove,
        .driver = {
                .name   = "cobalt-lcd",
                .owner  = THIS_MODULE,
index 39571f9e01628fb697a171c55b57558fac504a20..35687fd56456a82318b631e4ffc3df81b74759ca 100644 (file)
@@ -238,8 +238,7 @@ static void sti_flush(unsigned long start, unsigned long end)
        flush_icache_range(start, end);
 }
 
-static void __devinit sti_rom_copy(unsigned long base, unsigned long count,
-                                  void *dest)
+static void sti_rom_copy(unsigned long base, unsigned long count, void *dest)
 {
        unsigned long dest_start = (unsigned long) dest;
 
@@ -266,7 +265,7 @@ static void __devinit sti_rom_copy(unsigned long base, unsigned long count,
 static char default_sti_path[21] __read_mostly;
 
 #ifndef MODULE
-static int __devinit sti_setup(char *str)
+static int sti_setup(char *str)
 {
        if (str)
                strlcpy (default_sti_path, str, sizeof (default_sti_path));
@@ -285,12 +284,12 @@ __setup("sti=", sti_setup);
 
 
 
-static char __devinitdata      *font_name[MAX_STI_ROMS] = { "VGA8x16", };
-static int __devinitdata       font_index[MAX_STI_ROMS],
-                               font_height[MAX_STI_ROMS],
-                               font_width[MAX_STI_ROMS];
+static char *font_name[MAX_STI_ROMS] = { "VGA8x16", };
+static int font_index[MAX_STI_ROMS],
+          font_height[MAX_STI_ROMS],
+          font_width[MAX_STI_ROMS];
 #ifndef MODULE
-static int __devinit sti_font_setup(char *str)
+static int sti_font_setup(char *str)
 {
        char *x;
        int i = 0;
@@ -343,8 +342,8 @@ __setup("sti_font=", sti_font_setup);
 
 
        
-static void __devinit
-sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
+static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
+                            unsigned int sti_mem_request)
 {
        struct sti_glob_cfg_ext *cfg;
        
@@ -383,8 +382,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
                cfg->sti_mem_addr, sti_mem_request));
 }
 
-static void __devinit
-sti_dump_outptr(struct sti_struct *sti)
+static void sti_dump_outptr(struct sti_struct *sti)
 {
        DPRINTK((KERN_INFO
                "%d bits per pixel\n"
@@ -397,9 +395,8 @@ sti_dump_outptr(struct sti_struct *sti)
                 sti->outptr.attributes));
 }
 
-static int __devinit
-sti_init_glob_cfg(struct sti_struct *sti,
-           unsigned long rom_address, unsigned long hpa)
+static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
+                            unsigned long hpa)
 {
        struct sti_glob_cfg *glob_cfg;
        struct sti_glob_cfg_ext *glob_cfg_ext;
@@ -479,8 +476,8 @@ sti_init_glob_cfg(struct sti_struct *sti,
 }
 
 #ifdef CONFIG_FB
-static struct sti_cooked_font __devinit
-*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
+static struct sti_cooked_font *
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
        const struct font_desc *fbfont;
        unsigned int size, bpc;
@@ -535,16 +532,15 @@ static struct sti_cooked_font __devinit
        return cooked_font;
 }
 #else
-static struct sti_cooked_font __devinit
-*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
+static struct sti_cooked_font *
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
        return NULL;
 }
 #endif
 
-static struct sti_cooked_font __devinit
-*sti_select_font(struct sti_cooked_rom *rom,
-                int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
+static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom,
+               int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
 {
        struct sti_cooked_font *font;
        int i;
@@ -569,8 +565,7 @@ static struct sti_cooked_font __devinit
 }
 
 
-static void __devinit
-sti_dump_rom(struct sti_rom *rom)
+static void sti_dump_rom(struct sti_rom *rom)
 {
        printk(KERN_INFO "    id %04x-%04x, conforms to spec rev. %d.%02x\n",
                rom->graphics_id[0], 
@@ -587,9 +582,8 @@ sti_dump_rom(struct sti_rom *rom)
 }
 
 
-static int __devinit
-sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
-                       struct sti_rom *raw_rom)
+static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+                         struct sti_rom *raw_rom)
 {
        struct sti_rom_font *raw_font, *font_start;
        struct sti_cooked_font *cooked_font;
@@ -622,8 +616,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
 }
 
 
-static int __devinit
-sti_search_font(struct sti_cooked_rom *rom, int height, int width)
+static int sti_search_font(struct sti_cooked_rom *rom, int height, int width)
 {
        struct sti_cooked_font *font;
        int i = 0;
@@ -639,8 +632,7 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width)
 #define BMODE_RELOCATE(offset)         offset = (offset) / 4;
 #define BMODE_LAST_ADDR_OFFS           0x50
 
-static void * __devinit
-sti_bmode_font_raw(struct sti_cooked_font *f)
+static void *sti_bmode_font_raw(struct sti_cooked_font *f)
 {
        unsigned char *n, *p, *q;
        int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
@@ -657,8 +649,8 @@ sti_bmode_font_raw(struct sti_cooked_font *f)
        return n + 3;
 }
 
-static void __devinit
-sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
+static void sti_bmode_rom_copy(unsigned long base, unsigned long count,
+                              void *dest)
 {
        unsigned long dest_start = (unsigned long) dest;
 
@@ -672,8 +664,7 @@ sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
        sti_flush(dest_start, (unsigned long)dest);
 }
 
-static struct sti_rom * __devinit
-sti_get_bmode_rom (unsigned long address)
+static struct sti_rom *sti_get_bmode_rom (unsigned long address)
 {
        struct sti_rom *raw;
        u32 size;
@@ -708,7 +699,7 @@ sti_get_bmode_rom (unsigned long address)
        return raw;
 }
 
-static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address)
+static struct sti_rom *sti_get_wmode_rom(unsigned long address)
 {
        struct sti_rom *raw;
        unsigned long size;
@@ -723,8 +714,8 @@ static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address)
        return raw;
 }
 
-static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti,
-                                 unsigned long address)
+static int sti_read_rom(int wordmode, struct sti_struct *sti,
+                       unsigned long address)
 {
        struct sti_cooked_rom *cooked;
        struct sti_rom *raw = NULL;
@@ -806,8 +797,9 @@ out_err:
        return 0;
 }
 
-static struct sti_struct * __devinit
-sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd)
+static struct sti_struct *sti_try_rom_generic(unsigned long address,
+                                             unsigned long hpa,
+                                             struct pci_dev *pd)
 {
        struct sti_struct *sti;
        int ok;
@@ -921,7 +913,7 @@ out_err:
        return NULL;
 }
 
-static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char *path)
+static void sticore_check_for_default_sti(struct sti_struct *sti, char *path)
 {
        if (strcmp (path, default_sti_path) == 0)
                default_sti = sti;
@@ -932,7 +924,7 @@ static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char
  * in the additional address field addr[1] while on
  * older Systems the PDC stores it in page0->proc_sti 
  */
-static int __devinit sticore_pa_init(struct parisc_device *dev)
+static int sticore_pa_init(struct parisc_device *dev)
 {
        char pa_path[21];
        struct sti_struct *sti = NULL;
@@ -953,8 +945,7 @@ static int __devinit sticore_pa_init(struct parisc_device *dev)
 }
 
 
-static int __devinit sticore_pci_init(struct pci_dev *pd,
-               const struct pci_device_id *ent)
+static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent)
 {
 #ifdef CONFIG_PCI
        unsigned long fb_base, rom_base;
@@ -1001,7 +992,7 @@ static int __devinit sticore_pci_init(struct pci_dev *pd,
 }
 
 
-static void __devexit sticore_pci_remove(struct pci_dev *pd)
+static void sticore_pci_remove(struct pci_dev *pd)
 {
        BUG();
 }
@@ -1043,7 +1034,7 @@ static struct parisc_driver pa_sti_driver = {
 
 static int sticore_initialized __read_mostly;
 
-static void __devinit sti_init_roms(void)
+static void sti_init_roms(void)
 {
        if (sticore_initialized)
                return;
index e40125cb313e95080e49abdcad344195707c4232..57886787ead020687d1f05d40230d62c1db096fa 100644 (file)
@@ -1230,7 +1230,7 @@ static int cyber2000fb_ddc_getsda(void *data)
        return retval;
 }
 
-static int __devinit cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
+static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
 {
        strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->ddc_adapter.name));
@@ -1305,7 +1305,7 @@ static int cyber2000fb_i2c_getscl(void *data)
        return ret;
 }
 
-static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb)
+static int cyber2000fb_i2c_register(struct cfb_info *cfb)
 {
        strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->i2c_adapter.name));
@@ -1336,7 +1336,7 @@ static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
  * These parameters give
  * 640x480, hsync 31.5kHz, vsync 60Hz
  */
-static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
+static struct fb_videomode cyber2000fb_default_mode = {
        .refresh        = 60,
        .xres           = 640,
        .yres           = 480,
@@ -1404,8 +1404,7 @@ static void cyberpro_init_hw(struct cfb_info *cfb)
        }
 }
 
-static struct cfb_info __devinit *cyberpro_alloc_fb_info(unsigned int id,
-                                                        char *name)
+static struct cfb_info *cyberpro_alloc_fb_info(unsigned int id, char *name)
 {
        struct cfb_info *cfb;
 
@@ -1524,7 +1523,7 @@ static int cyber2000fb_setup(char *options)
  *  - memory mapped access to the registers
  *  - initialised mem_ctl1 and mem_ctl2 appropriately.
  */
-static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
+static int cyberpro_common_probe(struct cfb_info *cfb)
 {
        u_long smem_size;
        u_int h_sync, v_sync;
@@ -1615,7 +1614,7 @@ failed:
        return err;
 }
 
-static void __devexit cyberpro_common_remove(struct cfb_info *cfb)
+static void cyberpro_common_remove(struct cfb_info *cfb)
 {
        unregister_framebuffer(&cfb->fb);
 #ifdef CONFIG_FB_CYBER2000_DDC
@@ -1646,7 +1645,7 @@ static void cyberpro_common_resume(struct cfb_info *cfb)
 
 #include <mach/framebuffer.h>
 
-static int __devinit cyberpro_vl_probe(void)
+static int cyberpro_vl_probe(void)
 {
        struct cfb_info *cfb;
        int err = -ENOMEM;
@@ -1780,8 +1779,8 @@ static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
        return 0;
 }
 
-static int __devinit
-cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int cyberpro_pci_probe(struct pci_dev *dev,
+                             const struct pci_device_id *id)
 {
        struct cfb_info *cfb;
        char name[16];
@@ -1863,7 +1862,7 @@ failed_release:
        return err;
 }
 
-static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
+static void cyberpro_pci_remove(struct pci_dev *dev)
 {
        struct cfb_info *cfb = pci_get_drvdata(dev);
 
@@ -1923,7 +1922,7 @@ MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
 static struct pci_driver cyberpro_driver = {
        .name           = "CyberPro",
        .probe          = cyberpro_pci_probe,
-       .remove         = __devexit_p(cyberpro_pci_remove),
+       .remove         = cyberpro_pci_remove,
        .suspend        = cyberpro_pci_suspend,
        .resume         = cyberpro_pci_resume,
        .id_table       = cyberpro_pci_table
index 46534e00fe01eb575ae565fb5930b1c2d36ffa20..0810939936f4137037bbdc975967111b5b4cc9ca 100644 (file)
@@ -185,7 +185,7 @@ struct da8xx_fb_par {
 };
 
 /* Variable Screen Information */
-static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
+static struct fb_var_screeninfo da8xx_fb_var = {
        .xoffset = 0,
        .yoffset = 0,
        .transp = {0, 0, 0},
@@ -202,7 +202,7 @@ static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
        .vmode = FB_VMODE_NONINTERLACED
 };
 
-static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
+static struct fb_fix_screeninfo da8xx_fb_fix = {
        .id = "DA8xx FB Drv",
        .type = FB_TYPE_PACKED_PIXELS,
        .type_aux = 0,
@@ -993,7 +993,7 @@ static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
 }
 #endif
 
-static int __devexit fb_remove(struct platform_device *dev)
+static int fb_remove(struct platform_device *dev)
 {
        struct fb_info *info = dev_get_drvdata(&dev->dev);
 
@@ -1211,7 +1211,7 @@ static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
        return pix_clk_period_picosec;
 }
 
-static int __devinit fb_probe(struct platform_device *device)
+static int fb_probe(struct platform_device *device)
 {
        struct da8xx_lcdc_platform_data *fb_pdata =
                                                device->dev.platform_data;
@@ -1580,7 +1580,7 @@ static int fb_resume(struct platform_device *dev)
 
 static struct platform_driver da8xx_fb_driver = {
        .probe = fb_probe,
-       .remove = __devexit_p(fb_remove),
+       .remove = fb_remove,
        .suspend = fb_suspend,
        .resume = fb_resume,
        .driver = {
index 49e3dda1a361f72344a051bc7725dd3eebfc53b0..3526899da61b93e2c40532b6edb337cc5be53300 100644 (file)
@@ -115,7 +115,7 @@ static struct fb_ops dn_fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-struct fb_var_screeninfo dnfb_var __devinitdata = {
+struct fb_var_screeninfo dnfb_var = {
        .xres           = 1280,
        .yres           = 1024,
        .xres_virtual   = 2048,
@@ -126,7 +126,7 @@ struct fb_var_screeninfo dnfb_var __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo dnfb_fix __devinitdata = {
+static struct fb_fix_screeninfo dnfb_fix = {
        .id             = "Apollo Mono",
        .smem_start     = (FRAME_BUFFER_START + IO_BASE),
        .smem_len       = FRAME_BUFFER_LEN,
@@ -224,7 +224,7 @@ void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
  * Initialization
  */
 
-static int __devinit dnfb_probe(struct platform_device *dev)
+static int dnfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        int err = 0;
index 932abaa58a89af3bc63f03fc3a2f80c078b3eeaa..50fe668c617277cccadd5330af318bfb51e9d18b 100644 (file)
@@ -20,7 +20,7 @@ static bool request_mem_succeeded = false;
 
 static struct pci_dev *default_vga;
 
-static struct fb_var_screeninfo efifb_defined __devinitdata = {
+static struct fb_var_screeninfo efifb_defined = {
        .activate               = FB_ACTIVATE_NOW,
        .height                 = -1,
        .width                  = -1,
@@ -31,7 +31,7 @@ static struct fb_var_screeninfo efifb_defined __devinitdata = {
        .vmode                  = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo efifb_fix __devinitdata = {
+static struct fb_fix_screeninfo efifb_fix = {
        .id                     = "EFI VGA",
        .type                   = FB_TYPE_PACKED_PIXELS,
        .accel                  = FB_ACCEL_NONE,
index 755ef3e65caf4c980b8791cdfb2603dc3b576942..3f2519d3071574bd42dbe646afbf24dd1ba3d034 100644 (file)
@@ -484,7 +484,7 @@ static void ep93xxfb_dealloc_videomem(struct fb_info *info)
                                  info->screen_base, info->fix.smem_start);
 }
 
-static int __devinit ep93xxfb_probe(struct platform_device *pdev)
+static int ep93xxfb_probe(struct platform_device *pdev)
 {
        struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data;
        struct fb_info *info;
@@ -599,7 +599,7 @@ failed_cmap:
        return err;
 }
 
-static int __devexit ep93xxfb_remove(struct platform_device *pdev)
+static int ep93xxfb_remove(struct platform_device *pdev)
 {
        struct fb_info *info = platform_get_drvdata(pdev);
        struct ep93xx_fbi *fbi = info->par;
@@ -620,14 +620,14 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)
 
 static struct platform_driver ep93xxfb_driver = {
        .probe          = ep93xxfb_probe,
-       .remove         = __devexit_p(ep93xxfb_remove),
+       .remove         = ep93xxfb_remove,
        .driver = {
                .name   = "ep93xx-fb",
                .owner  = THIS_MODULE,
        },
 };
 
-static int __devinit ep93xxfb_init(void)
+static int ep93xxfb_init(void)
 {
        return platform_driver_register(&ep93xxfb_driver);
 }
index 28fd686c6b8199429b98ca7d7c6014fc7225cf1b..4ef18e2e90ccc41ffd89bc1d4c5dc1abf8626f1d 100644 (file)
@@ -1033,7 +1033,7 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 }
 #endif /* CONFIG_OF */
 
-static int __devinit exynos_dp_probe(struct platform_device *pdev)
+static int exynos_dp_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct exynos_dp_device *dp;
@@ -1114,7 +1114,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit exynos_dp_remove(struct platform_device *pdev)
+static int exynos_dp_remove(struct platform_device *pdev)
 {
        struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
        struct exynos_dp_device *dp = platform_get_drvdata(pdev);
@@ -1195,7 +1195,7 @@ MODULE_DEVICE_TABLE(of, exynos_dp_match);
 
 static struct platform_driver exynos_dp_driver = {
        .probe          = exynos_dp_probe,
-       .remove         = __devexit_p(exynos_dp_remove),
+       .remove         = exynos_dp_remove,
        .driver         = {
                .name   = "exynos-dp",
                .owner  = THIS_MODULE,
index 07d70a3a628bfc987018131538281b1b6484ed17..4a17cdccef3466f616178688436b39a856ded206 100644 (file)
@@ -490,7 +490,7 @@ err_platform_get_irq:
        return ret;
 }
 
-static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
+static int exynos_mipi_dsi_remove(struct platform_device *pdev)
 {
        struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
        struct mipi_dsim_ddi *dsim_ddi, *next;
@@ -595,7 +595,7 @@ static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
 
 static struct platform_driver exynos_mipi_dsi_driver = {
        .probe = exynos_mipi_dsi_probe,
-       .remove = __devexit_p(exynos_mipi_dsi_remove),
+       .remove = exynos_mipi_dsi_remove,
        .driver = {
                   .name = "exynos-mipi-dsim",
                   .owner = THIS_MODULE,
index 14102a3f70f5cc69bd19963919bad3522a2cda06..6d2744794dd13f779ab6c6b2a6f02595c2017451 100644 (file)
@@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
        info->fix.accel = FB_ACCEL_SUN_CREATOR;
 }
 
-static int __devinit ffb_probe(struct platform_device *op)
+static int ffb_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct ffb_fbc __iomem *fbc;
@@ -1022,7 +1022,7 @@ out_err:
        return err;
 }
 
-static int __devexit ffb_remove(struct platform_device *op)
+static int ffb_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct ffb_par *par = info->par;
@@ -1058,7 +1058,7 @@ static struct platform_driver ffb_driver = {
                .of_match_table = ffb_match,
        },
        .probe          = ffb_probe,
-       .remove         = __devexit_p(ffb_remove),
+       .remove         = ffb_remove,
 };
 
 static int __init ffb_init(void)
index d0533b7aad79908f600232677166ee042201fe05..c99c9671302ba8998a94f9ba39c43c1ff730565f 100644 (file)
 
 static volatile unsigned char *fm2fb_reg;
 
-static struct fb_fix_screeninfo fb_fix __devinitdata = {
+static struct fb_fix_screeninfo fb_fix = {
        .smem_len =     FRAMEMASTER_REG,
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_TRUECOLOR,
@@ -136,12 +136,12 @@ static struct fb_fix_screeninfo fb_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static int fm2fb_mode __devinitdata = -1;
+static int fm2fb_mode = -1;
 
 #define FM2FB_MODE_PAL 0
 #define FM2FB_MODE_NTSC        1
 
-static struct fb_var_screeninfo fb_var_modes[] __devinitdata = {
+static struct fb_var_screeninfo fb_var_modes[] = {
     {
        /* 768 x 576, 32 bpp (PAL) */
        768, 576, 768, 576, 0, 0, 32, 0,
@@ -211,10 +211,9 @@ static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
      *  Initialisation
      */
 
-static int __devinit fm2fb_probe(struct zorro_dev *z,
-                                const struct zorro_device_id *id);
+static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id);
 
-static struct zorro_device_id fm2fb_devices[] __devinitdata = {
+static struct zorro_device_id fm2fb_devices[] = {
        { ZORRO_PROD_BSC_FRAMEMASTER_II },
        { ZORRO_PROD_HELFRICH_RAINBOW_II },
        { 0 }
@@ -227,8 +226,7 @@ static struct zorro_driver fm2fb_driver = {
        .probe          = fm2fb_probe,
 };
 
-static int __devinit fm2fb_probe(struct zorro_dev *z,
-                                const struct zorro_device_id *id)
+static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id)
 {
        struct fb_info *info;
        unsigned long *ptr;
index d3fc92eaee8939bc0f35981342fbc6f5e2a47a28..19cfd7a925638f305c7e349490ade67cf6dd425c 100644 (file)
@@ -55,7 +55,7 @@
  * order if increasing resolution and frequency.  The 320x240-60 mode is
  * the initial AOI for the second and third planes.
  */
-static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
+static struct fb_videomode fsl_diu_mode_db[] = {
        {
                .refresh        = 60,
                .xres           = 1024,
@@ -1307,7 +1307,7 @@ static struct fb_ops fsl_diu_ops = {
        .fb_release = fsl_diu_release,
 };
 
-static int __devinit install_fb(struct fb_info *info)
+static int install_fb(struct fb_info *info)
 {
        int rc;
        struct mfb_info *mfbi = info->par;
@@ -1518,7 +1518,7 @@ static ssize_t show_monitor(struct device *device,
        return 0;
 }
 
-static int __devinit fsl_diu_probe(struct platform_device *pdev)
+static int fsl_diu_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct mfb_info *mfbi;
index 3dad31975db8cceaf8fe16963d3ca1d37180b85e..bda5e3941510fa1c415667a873fc684b928a91e8 100644 (file)
@@ -91,10 +91,10 @@ static uint32_t pseudo_palette[16];
 static uint32_t gbe_cmap[256];
 static int gbe_turned_on; /* 0 turned off, 1 turned on */
 
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
 /* default CRT mode */
-static struct fb_var_screeninfo default_var_CRT __devinitdata = {
+static struct fb_var_screeninfo default_var_CRT = {
        /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
        .xres           = 640,
        .yres           = 480,
@@ -125,7 +125,7 @@ static struct fb_var_screeninfo default_var_CRT __devinitdata = {
 };
 
 /* default LCD mode */
-static struct fb_var_screeninfo default_var_LCD __devinitdata = {
+static struct fb_var_screeninfo default_var_LCD = {
        /* 1600x1024, 8 bpp */
        .xres           = 1600,
        .yres           = 1024,
@@ -157,7 +157,7 @@ static struct fb_var_screeninfo default_var_LCD __devinitdata = {
 
 /* default modedb mode */
 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode default_mode_CRT __devinitdata = {
+static struct fb_videomode default_mode_CRT = {
        .refresh        = 60,
        .xres           = 640,
        .yres           = 480,
@@ -172,7 +172,7 @@ static struct fb_videomode default_mode_CRT __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 /* 1600x1024 SGI flatpanel 1600sw */
-static struct fb_videomode default_mode_LCD __devinitdata = {
+static struct fb_videomode default_mode_LCD = {
        /* 1600x1024, 8 bpp */
        .xres           = 1600,
        .yres           = 1024,
@@ -186,8 +186,8 @@ static struct fb_videomode default_mode_LCD __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_videomode *default_mode __devinitdata = &default_mode_CRT;
-static struct fb_var_screeninfo *default_var __devinitdata = &default_var_CRT;
+static struct fb_videomode *default_mode = &default_mode_CRT;
+static struct fb_var_screeninfo *default_var = &default_var_CRT;
 
 static int flat_panel_enabled = 0;
 
@@ -1082,7 +1082,7 @@ static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *at
 
 static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
 
-static void __devexit gbefb_remove_sysfs(struct device *dev)
+static void gbefb_remove_sysfs(struct device *dev)
 {
        device_remove_file(dev, &dev_attr_size);
        device_remove_file(dev, &dev_attr_revision);
@@ -1098,7 +1098,7 @@ static void gbefb_create_sysfs(struct device *dev)
  * Initialization
  */
 
-static int __devinit gbefb_setup(char *options)
+static int gbefb_setup(char *options)
 {
        char *this_opt;
 
@@ -1129,7 +1129,7 @@ static int __devinit gbefb_setup(char *options)
        return 0;
 }
 
-static int __devinit gbefb_probe(struct platform_device *p_dev)
+static int gbefb_probe(struct platform_device *p_dev)
 {
        int i, ret = 0;
        struct fb_info *info;
@@ -1254,7 +1254,7 @@ out_release_framebuffer:
        return ret;
 }
 
-static int __devexit gbefb_remove(struct platform_device* p_dev)
+static int gbefb_remove(struct platform_device* p_dev)
 {
        struct fb_info *info = platform_get_drvdata(p_dev);
 
@@ -1273,7 +1273,7 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
 
 static struct platform_driver gbefb_driver = {
        .probe = gbefb_probe,
-       .remove = __devexit_p(gbefb_remove),
+       .remove = gbefb_remove,
        .driver = {
                .name = "gbefb",
        },
index 265c5ed59adea8824f9a9fe225704cd877ec4924..ebbaada7b94154c88650575f2f63253da096a387 100644 (file)
@@ -29,7 +29,7 @@ static int  crt_option = 1;
 static char panel_option[32] = "";
 
 /* Modes relevant to the GX1 (taken from modedb.c) */
-static const struct fb_videomode __devinitconst gx1_modedb[] = {
+static const struct fb_videomode gx1_modedb[] = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -195,7 +195,7 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info)
        return par->vid_ops->blank_display(info, blank_mode);
 }
 
-static int __devinit gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
 {
        struct geodefb_par *par = info->par;
        unsigned gx_base;
@@ -268,7 +268,7 @@ static struct fb_ops gx1fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __devinit gx1fb_init_fbinfo(struct device *dev)
+static struct fb_info *gx1fb_init_fbinfo(struct device *dev)
 {
        struct geodefb_par *par;
        struct fb_info *info;
@@ -318,7 +318,7 @@ static struct fb_info * __devinit gx1fb_init_fbinfo(struct device *dev)
        return info;
 }
 
-static int __devinit gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct geodefb_par *par;
        struct fb_info *info;
@@ -382,7 +382,7 @@ static int __devinit gx1fb_probe(struct pci_dev *pdev, const struct pci_device_i
        return ret;
 }
 
-static void __devexit gx1fb_remove(struct pci_dev *pdev)
+static void gx1fb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct geodefb_par *par = info->par;
@@ -441,7 +441,7 @@ static struct pci_driver gx1fb_driver = {
        .name           = "gx1fb",
        .id_table       = gx1fb_id_table,
        .probe          = gx1fb_probe,
-       .remove         = __devexit_p(gx1fb_remove),
+       .remove         = gx1fb_remove,
 };
 
 static int __init gx1fb_init(void)
@@ -456,7 +456,7 @@ static int __init gx1fb_init(void)
        return pci_register_driver(&gx1fb_driver);
 }
 
-static void __devexit gx1fb_cleanup(void)
+static void gx1fb_cleanup(void)
 {
        pci_unregister_driver(&gx1fb_driver);
 }
index b4f19db9bb542ddfb453298498ca5e96413fe2a5..19f0c1add747fa23b8db96160b7ec1765fa75a01 100644 (file)
@@ -40,7 +40,7 @@ static int vram;
 static int vt_switch;
 
 /* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __devinitdata = {
+static struct fb_videomode gx_modedb[] = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,15 +110,14 @@ static struct fb_videomode gx_modedb[] __devinitdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
+static struct fb_videomode gx_dcon_modedb[] = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __devinit get_modedb(struct fb_videomode **modedb,
-               unsigned int *size)
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -130,8 +129,7 @@ static void __devinit get_modedb(struct fb_videomode **modedb,
 }
 
 #else
-static void __devinit get_modedb(struct fb_videomode **modedb,
-               unsigned int *size)
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
 {
        *modedb = (struct fb_videomode *) gx_modedb;
        *size = ARRAY_SIZE(gx_modedb);
@@ -228,8 +226,7 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
        return gx_blank_display(info, blank_mode);
 }
 
-static int __devinit gxfb_map_video_memory(struct fb_info *info,
-               struct pci_dev *dev)
+static int gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
 {
        struct gxfb_par *par = info->par;
        int ret;
@@ -293,7 +290,7 @@ static struct fb_ops gxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *gxfb_init_fbinfo(struct device *dev)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -374,8 +371,7 @@ static int gxfb_resume(struct pci_dev *pdev)
 }
 #endif
 
-static int __devinit gxfb_probe(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -455,7 +451,7 @@ static int __devinit gxfb_probe(struct pci_dev *pdev,
        return ret;
 }
 
-static void __devexit gxfb_remove(struct pci_dev *pdev)
+static void gxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct gxfb_par *par = info->par;
index 416851ca8754bec70bb54108c0a7c9cb663dde47..4dd7b5566962b59be9061480f80e373bd1bd7233 100644 (file)
@@ -35,7 +35,7 @@ static int vt_switch;
  * we try to make it something sane - 640x480-60 is sane
  */
 
-static struct fb_videomode geode_modedb[] __devinitdata = {
+static struct fb_videomode geode_modedb[] = {
        /* 640x480-60 */
        { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,15 +219,14 @@ static struct fb_videomode geode_modedb[] __devinitdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
+static struct fb_videomode olpc_dcon_modedb[] = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __devinit get_modedb(struct fb_videomode **modedb,
-               unsigned int *size)
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -239,8 +238,7 @@ static void __devinit get_modedb(struct fb_videomode **modedb,
 }
 
 #else
-static void __devinit get_modedb(struct fb_videomode **modedb,
-               unsigned int *size)
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
 {
        *modedb = (struct fb_videomode *) geode_modedb;
        *size = ARRAY_SIZE(geode_modedb);
@@ -336,8 +334,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)
 }
 
 
-static int __devinit lxfb_map_video_memory(struct fb_info *info,
-                                       struct pci_dev *dev)
+static int lxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
 {
        struct lxfb_par *par = info->par;
        int ret;
@@ -414,7 +411,7 @@ static struct fb_ops lxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
+static struct fb_info *lxfb_init_fbinfo(struct device *dev)
 {
        struct lxfb_par *par;
        struct fb_info *info;
@@ -498,8 +495,7 @@ static int lxfb_resume(struct pci_dev *pdev)
 #define lxfb_resume NULL
 #endif
 
-static int __devinit lxfb_probe(struct pci_dev *pdev,
-                            const struct pci_device_id *id)
+static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct lxfb_par *par;
        struct fb_info *info;
@@ -590,7 +586,7 @@ err:
        return ret;
 }
 
-static void __devexit lxfb_remove(struct pci_dev *pdev)
+static void lxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct lxfb_par *par = info->par;
index 5245f9a71892e75ad08c8cc0439a030910abfc71..861109e7de1b574d6d9880ee5b845346299de7a2 100644 (file)
@@ -70,7 +70,7 @@ static const struct fb_videomode grvga_modedb[] = {
     }
  };
 
-static struct fb_fix_screeninfo grvga_fix __devinitdata = {
+static struct fb_fix_screeninfo grvga_fix = {
        .id =           "AG SVGACTRL",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -267,8 +267,8 @@ static struct fb_ops grvga_ops = {
        .fb_imageblit   = cfb_imageblit
 };
 
-static int __devinit grvga_parse_custom(char *options,
-                                    struct fb_var_screeninfo *screendata)
+static int grvga_parse_custom(char *options,
+                             struct fb_var_screeninfo *screendata)
 {
        char *this_opt;
        int count = 0;
@@ -329,7 +329,7 @@ static int __devinit grvga_parse_custom(char *options,
        return 0;
 }
 
-static int __devinit grvga_probe(struct platform_device *dev)
+static int grvga_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        int retval = -ENOMEM;
@@ -512,7 +512,7 @@ free_fb:
        return retval;
 }
 
-static int __devexit grvga_remove(struct platform_device *device)
+static int grvga_remove(struct platform_device *device)
 {
        struct fb_info *info = dev_get_drvdata(&device->dev);
        struct grvga_par *par = info->par;
@@ -554,7 +554,7 @@ static struct platform_driver grvga_driver = {
                .of_match_table = svgactrl_of_match,
        },
        .probe          = grvga_probe,
-       .remove         = __devexit_p(grvga_remove),
+       .remove         = grvga_remove,
 };
 
 
index 4bdea6e9bd5590dfb5b42d47ac9c570d56699da5..c35663f6a54a10231e05e9a00e973ad856cd5a00 100644 (file)
@@ -159,7 +159,7 @@ struct gxt4500_par {
 static char *mode_option;
 
 /* default mode: 1280x1024 @ 60 Hz, 8 bpp */
-static const struct fb_videomode defaultmode __devinitconst = {
+static const struct fb_videomode defaultmode = {
        .refresh = 60,
        .xres = 1280,
        .yres = 1024,
@@ -588,7 +588,7 @@ static int gxt4500_blank(int blank, struct fb_info *info)
        return 0;
 }
 
-static const struct fb_fix_screeninfo gxt4500_fix __devinitconst = {
+static const struct fb_fix_screeninfo gxt4500_fix = {
        .id = "IBM GXT4500P",
        .type = FB_TYPE_PACKED_PIXELS,
        .visual = FB_VISUAL_PSEUDOCOLOR,
@@ -610,8 +610,7 @@ static struct fb_ops gxt4500_ops = {
 };
 
 /* PCI functions */
-static int __devinit gxt4500_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err;
        unsigned long reg_phys, fb_phys;
@@ -720,7 +719,7 @@ static int __devinit gxt4500_probe(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static void __devexit gxt4500_remove(struct pci_dev *pdev)
+static void gxt4500_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct gxt4500_par *par;
@@ -758,10 +757,10 @@ static struct pci_driver gxt4500_driver = {
        .name = "gxt4500",
        .id_table = gxt4500_pci_tbl,
        .probe = gxt4500_probe,
-       .remove = __devexit_p(gxt4500_remove),
+       .remove = gxt4500_remove,
 };
 
-static int __devinit gxt4500_init(void)
+static int gxt4500_init(void)
 {
 #ifndef MODULE
        if (fb_get_options("gxt4500", &mode_option))
index 614251a9af912953e867802e2ddbd9a495fdee86..59d23181fdb0f768c927fb38d7a60a257471331e 100644 (file)
@@ -47,7 +47,7 @@
 #define DPY_W 600
 #define DPY_H 800
 
-static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
+static struct fb_fix_screeninfo hecubafb_fix = {
        .id =           "hecubafb",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_MONO01,
@@ -58,7 +58,7 @@ static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo hecubafb_var __devinitdata = {
+static struct fb_var_screeninfo hecubafb_var = {
        .xres           = DPY_W,
        .yres           = DPY_H,
        .xres_virtual   = DPY_W,
@@ -211,7 +211,7 @@ static struct fb_deferred_io hecubafb_defio = {
        .deferred_io    = hecubafb_dpy_deferred_io,
 };
 
-static int __devinit hecubafb_probe(struct platform_device *dev)
+static int hecubafb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct hecuba_board *board;
@@ -280,7 +280,7 @@ err_videomem_alloc:
        return retval;
 }
 
-static int __devexit hecubafb_remove(struct platform_device *dev)
+static int hecubafb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -299,7 +299,7 @@ static int __devexit hecubafb_remove(struct platform_device *dev)
 
 static struct platform_driver hecubafb_driver = {
        .probe  = hecubafb_probe,
-       .remove = __devexit_p(hecubafb_remove),
+       .remove = hecubafb_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "hecubafb",
index c645f928265001dc5bb5485a25a1a2012aafc2d4..1e9e2d819d1f13dd26f43fe2c0718bca9e5d9ae6 100644 (file)
@@ -106,7 +106,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
 
 /* Framebuffer driver structures */
 
-static struct fb_var_screeninfo hga_default_var __devinitdata = {
+static struct fb_var_screeninfo hga_default_var = {
        .xres           = 720,
        .yres           = 348,
        .xres_virtual   = 720,
@@ -120,7 +120,7 @@ static struct fb_var_screeninfo hga_default_var __devinitdata = {
        .width          = -1,
 };
 
-static struct fb_fix_screeninfo hga_fix __devinitdata = {
+static struct fb_fix_screeninfo hga_fix = {
        .id             = "HGA",
        .type           = FB_TYPE_PACKED_PIXELS,        /* (not sure) */
        .visual         = FB_VISUAL_MONO10,
@@ -276,7 +276,7 @@ static void hga_blank(int blank_mode)
        spin_unlock_irqrestore(&hga_reg_lock, flags);
 }
 
-static int __devinit hga_card_detect(void)
+static int hga_card_detect(void)
 {
        int count = 0;
        void __iomem *p, *q;
@@ -546,7 +546,7 @@ static struct fb_ops hgafb_ops = {
         *  Initialization
         */
 
-static int __devinit hgafb_probe(struct platform_device *pdev)
+static int hgafb_probe(struct platform_device *pdev)
 {
        struct fb_info *info;
 
@@ -592,7 +592,7 @@ static int __devinit hgafb_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit hgafb_remove(struct platform_device *pdev)
+static int hgafb_remove(struct platform_device *pdev)
 {
        struct fb_info *info = platform_get_drvdata(pdev);
 
@@ -617,7 +617,7 @@ static int __devexit hgafb_remove(struct platform_device *pdev)
 
 static struct platform_driver hgafb_driver = {
        .probe = hgafb_probe,
-       .remove = __devexit_p(hgafb_remove),
+       .remove = hgafb_remove,
        .driver = {
                .name = "hgafb",
        },
index cfb8d6451014e06ca1f6b3775e65569ade4fdc8d..c2414d6ab646f3c75569f85c61165bcb2769ca3f 100644 (file)
 
 #define        WIDTH 640
 
-static struct fb_var_screeninfo hitfb_var __devinitdata = {
+static struct fb_var_screeninfo hitfb_var = {
        .activate       = FB_ACTIVATE_NOW,
        .height         = -1,
        .width          = -1,
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo hitfb_fix __devinitdata = {
+static struct fb_fix_screeninfo hitfb_fix = {
        .id             = "Hitachi HD64461",
        .type           = FB_TYPE_PACKED_PIXELS,
        .accel          = FB_ACCEL_NONE,
@@ -324,7 +324,7 @@ static struct fb_ops hitfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int __devinit hitfb_probe(struct platform_device *dev)
+static int hitfb_probe(struct platform_device *dev)
 {
        unsigned short lcdclor, ldr3, ldvndr;
        struct fb_info *info;
@@ -417,7 +417,7 @@ err_fb:
        return ret;
 }
 
-static int __devexit hitfb_remove(struct platform_device *dev)
+static int hitfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -462,7 +462,7 @@ static const struct dev_pm_ops hitfb_dev_pm_ops = {
 
 static struct platform_driver hitfb_driver = {
        .probe          = hitfb_probe,
-       .remove         = __devexit_p(hitfb_remove),
+       .remove         = hitfb_remove,
        .driver         = {
                .name   = "hitfb",
                .owner  = THIS_MODULE,
index 7324865f965f4c5c1d9c5fe4639dbb8f66f39808..b802f93cef5d285e55448c2bf10d859d0dadfb79 100644 (file)
@@ -206,8 +206,7 @@ static struct fb_ops hpfb_ops = {
 #define HPFB_FBOMSB    0x5d    /* Frame buffer offset          */
 #define HPFB_FBOLSB    0x5f
 
-static int __devinit hpfb_init_one(unsigned long phys_base,
-                                  unsigned long virt_base)
+static int hpfb_init_one(unsigned long phys_base, unsigned long virt_base)
 {
        unsigned long fboff, fb_width, fb_height, fb_start;
        int ret;
@@ -327,7 +326,7 @@ unmap_screen_base:
 /* 
  * Initialise the framebuffer
  */
-static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_id * ent)
+static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent)
 {
        unsigned long paddr, vaddr;
 
@@ -350,7 +349,7 @@ static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_
        return 0;
 }
 
-static void __devexit hpfb_remove_one(struct dio_dev *d)
+static void hpfb_remove_one(struct dio_dev *d)
 {
        unregister_framebuffer(&fb_info);
        if (d->scode >= DIOII_SCBASE)
@@ -373,7 +372,7 @@ static struct dio_driver hpfb_driver = {
     .name      = "hpfb",
     .id_table  = hpfb_dio_tbl,
     .probe     = hpfb_dio_probe,
-    .remove    = __devexit_p(hpfb_remove_one),
+    .remove    = hpfb_remove_one,
 };
 
 int __init hpfb_init(void)
index ff3f8808e4e9ed24a1d3defcca0cb6c11259ce93..cfd0c52e8f737fb60a6279c668c90bf35a3ce24f 100644 (file)
 
 #include "i740_reg.h"
 
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 #ifdef CONFIG_MTRR
-static int mtrr __devinitdata = 1;
+static int mtrr = 1;
 #endif
 
 struct i740fb_par {
@@ -91,7 +91,7 @@ struct i740fb_par {
 #define DACSPEED24_SD  128
 #define DACSPEED32     86
 
-static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
+static struct fb_fix_screeninfo i740fb_fix = {
        .id =           "i740fb",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_TRUECOLOR,
@@ -163,7 +163,7 @@ static int i740fb_ddc_getsda(void *data)
        return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
 }
 
-static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
+static int i740fb_setup_ddc_bus(struct fb_info *info)
 {
        struct i740fb_par *par = info->par;
 
@@ -1007,8 +1007,7 @@ static struct fb_ops i740fb_ops = {
 
 /* ------------------------------------------------------------------------- */
 
-static int __devinit i740fb_probe(struct pci_dev *dev,
-                                 const struct pci_device_id *ent)
+static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct i740fb_par *par;
@@ -1174,7 +1173,7 @@ err_enable_device:
        return ret;
 }
 
-static void __devexit i740fb_remove(struct pci_dev *dev)
+static void i740fb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -1275,7 +1274,7 @@ static struct pci_driver i740fb_driver = {
        .name           = "i740fb",
        .id_table       = i740fb_id_table,
        .probe          = i740fb_probe,
-       .remove         = __devexit_p(i740fb_remove),
+       .remove         = i740fb_remove,
        .suspend        = i740fb_suspend,
        .resume         = i740fb_resume,
 };
index 5c067816a81d82210177ae569768504ef2d3b8e5..4ce3438ade6f31fc8bac432a468f719d777e7cea 100644 (file)
  *
  * Experiment with v_offset to find out which works best for you.
  */
-static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset          __devinitdata;
+static u32 v_offset_default; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset;
 
 static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-static int  __devinit i810fb_init_pci (struct pci_dev *dev,
-                                      const struct pci_device_id *entry);
+static int i810fb_init_pci(struct pci_dev *dev,
+                          const struct pci_device_id *entry);
 static void __exit i810fb_remove_pci(struct pci_dev *dev);
 static int i810fb_resume(struct pci_dev *dev);
 static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
@@ -97,7 +97,7 @@ static int i810fb_blank      (int blank_mode, struct fb_info *info);
 static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
 
 /* PCI */
-static const char * const i810_pci_list[] __devinitconst = {
+static const char * const i810_pci_list[] = {
        "Intel(R) 810 Framebuffer Device"                                 ,
        "Intel(R) 810-DC100 Framebuffer Device"                           ,
        "Intel(R) 810E Framebuffer Device"                                ,
@@ -132,22 +132,22 @@ static struct pci_driver i810fb_driver = {
        .resume   =     i810fb_resume,
 };
 
-static char *mode_option __devinitdata = NULL;
-static int vram       __devinitdata = 4;
-static int bpp        __devinitdata = 8;
-static bool mtrr      __devinitdata;
-static bool accel     __devinitdata;
-static int hsync1     __devinitdata;
-static int hsync2     __devinitdata;
-static int vsync1     __devinitdata;
-static int vsync2     __devinitdata;
-static int xres       __devinitdata;
+static char *mode_option = NULL;
+static int vram = 4;
+static int bpp = 8;
+static bool mtrr;
+static bool accel;
+static int hsync1;
+static int hsync2;
+static int vsync1;
+static int vsync2;
+static int xres;
 static int yres;
-static int vyres      __devinitdata;
-static bool sync      __devinitdata;
-static bool extvga    __devinitdata;
-static bool dcolor    __devinitdata;
-static bool ddc3      __devinitdata;
+static int vyres;
+static bool sync;
+static bool extvga;
+static bool dcolor;
+static bool ddc3;
 
 /*------------------------------------------------------------*/
 
@@ -1541,7 +1541,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        return 0;
 }
 
-static struct fb_ops i810fb_ops __devinitdata = {
+static struct fb_ops i810fb_ops = {
        .owner =             THIS_MODULE,
        .fb_open =           i810fb_open,
        .fb_release =        i810fb_release,
@@ -1628,7 +1628,7 @@ fail:
  *                  AGP resource allocation                            *
  ***********************************************************************/
   
-static void __devinit i810_fix_pointers(struct i810fb_par *par)
+static void i810_fix_pointers(struct i810fb_par *par)
 {
        par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
        par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
@@ -1640,7 +1640,7 @@ static void __devinit i810_fix_pointers(struct i810fb_par *par)
                (par->cursor_heap.offset << 12);
 }
 
-static void __devinit i810_fix_offsets(struct i810fb_par *par)
+static void i810_fix_offsets(struct i810fb_par *par)
 {
        if (vram + 1 > par->aperture.size >> 20)
                vram = (par->aperture.size >> 20) - 1;
@@ -1660,7 +1660,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par)
        par->cursor_heap.size = 4096;
 }
 
-static int __devinit i810_alloc_agp_mem(struct fb_info *info)
+static int i810_alloc_agp_mem(struct fb_info *info)
 {
        struct i810fb_par *par = info->par;
        int size;
@@ -1723,7 +1723,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
  * Sets the user monitor's horizontal and vertical
  * frequency limits
  */
-static void __devinit i810_init_monspecs(struct fb_info *info)
+static void i810_init_monspecs(struct fb_info *info)
 {
        if (!hsync1)
                hsync1 = HFMIN;
@@ -1755,8 +1755,7 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
  * @par: pointer to i810fb_par structure
  * @info: pointer to current fb_info structure
  */
-static void __devinit i810_init_defaults(struct i810fb_par *par, 
-                                     struct fb_info *info)
+static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
 {
        mutex_init(&par->open_lock);
 
@@ -1812,7 +1811,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
  * i810_init_device - initialize device
  * @par: pointer to i810fb_par structure
  */
-static void __devinit i810_init_device(struct i810fb_par *par)
+static void i810_init_device(struct i810fb_par *par)
 {
        u8 reg;
        u8 __iomem *mmio = par->mmio_start_virtual;
@@ -1833,9 +1832,8 @@ static void __devinit i810_init_device(struct i810fb_par *par)
 
 }
 
-static int __devinit 
-i810_allocate_pci_resource(struct i810fb_par *par, 
-                          const struct pci_device_id *entry)
+static int i810_allocate_pci_resource(struct i810fb_par *par,
+                                     const struct pci_device_id *entry)
 {
        int err;
 
@@ -1892,7 +1890,7 @@ i810_allocate_pci_resource(struct i810fb_par *par,
        return 0;
 }
 
-static void __devinit i810fb_find_init_mode(struct fb_info *info)
+static void i810fb_find_init_mode(struct fb_info *info)
 {
        struct fb_videomode mode;
        struct fb_var_screeninfo var;
@@ -1956,7 +1954,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
 }
 
 #ifndef MODULE
-static int __devinit i810fb_setup(char *options)
+static int i810fb_setup(char *options)
 {
        char *this_opt, *suffix = NULL;
 
@@ -2007,8 +2005,8 @@ static int __devinit i810fb_setup(char *options)
 }
 #endif
 
-static int __devinit i810fb_init_pci (struct pci_dev *dev, 
-                                  const struct pci_device_id *entry)
+static int i810fb_init_pci(struct pci_dev *dev,
+                          const struct pci_device_id *entry)
 {
        struct fb_info    *info;
        struct i810fb_par *par = NULL;
@@ -2136,7 +2134,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
 }                                                      
 
 #ifndef MODULE
-static int __devinit i810fb_init(void)
+static int i810fb_init(void)
 {
        char *option = NULL;
 
@@ -2154,7 +2152,7 @@ static int __devinit i810fb_init(void)
 
 #ifdef MODULE
 
-static int __devinit i810fb_init(void)
+static int i810fb_init(void)
 {
        hsync1 *= 1000;
        hsync2 *= 1000;
index 51d4f3d4116dda55e130360b89cc02e06cdfa984..a25afaa534baa3264925b86a503eb2fb39f0d41a 100644 (file)
@@ -64,7 +64,7 @@ static inline void flush_cache(void)
 
 #include <asm/mtrr.h>
 
-static inline void __devinit set_mtrr(struct i810fb_par *par)
+static inline void set_mtrr(struct i810fb_par *par)
 {
        par->mtrr_reg = mtrr_add((u32) par->aperture.physical, 
                 par->aperture.size, MTRR_TYPE_WRCOMB, 1);
index 2d97752f79a516a049f749eb4f82034078d7aabd..79cbfa7d1a9be0703a167c63e515cf3b6ab2fe86 100644 (file)
@@ -571,7 +571,7 @@ static int __init igafb_setup(char *options)
 
 module_init(igafb_init);
 MODULE_LICENSE("GPL");
-static struct pci_device_id igafb_pci_tbl[] __devinitdata = {
+static struct pci_device_id igafb_pci_tbl[] = {
        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { }
index 8149356471e443af26d5a4e2cb97c818bfaf9c7f..d5220cc90e932b67657bded0a2bb5b4a9d05bfa0 100644 (file)
@@ -225,7 +225,7 @@ struct initvalues {
        __u8 addr, value;
 };
 
-static struct initvalues ibm_initregs[] __devinitdata = {
+static struct initvalues ibm_initregs[] = {
        { CLKCTL,       0x21 },
        { SYNCCTL,      0x00 },
        { HSYNCPOS,     0x00 },
@@ -272,7 +272,7 @@ static struct initvalues ibm_initregs[] __devinitdata = {
        { KEYCTL,       0x00 }
 };
 
-static struct initvalues tvp_initregs[] __devinitdata = {
+static struct initvalues tvp_initregs[] = {
        { TVPIRICC,     0x00 },
        { TVPIRBRC,     0xe4 },
        { TVPIRLAC,     0x06 },
@@ -336,7 +336,7 @@ enum {
 static int inverse = 0;
 static char fontname[40] __initdata = { 0 };
 #if defined(CONFIG_PPC)
-static signed char init_vmode __devinitdata = -1, init_cmode __devinitdata = -1;
+static signed char init_vmode = -1, init_cmode = -1;
 #endif
 
 static struct imstt_regvals tvp_reg_init_2 = {
@@ -1333,7 +1333,7 @@ static struct pci_driver imsttfb_pci_driver = {
        .name =         "imsttfb",
        .id_table =     imsttfb_pci_tbl,
        .probe =        imsttfb_probe,
-       .remove =       __devexit_p(imsttfb_remove),
+       .remove =       imsttfb_remove,
 };
 
 static struct fb_ops imsttfb_ops = {
@@ -1349,8 +1349,7 @@ static struct fb_ops imsttfb_ops = {
        .fb_ioctl       = imsttfb_ioctl,
 };
 
-static void __devinit
-init_imstt(struct fb_info *info)
+static void init_imstt(struct fb_info *info)
 {
        struct imstt_par *par = info->par;
        __u32 i, tmp, *ip, *end;
@@ -1466,8 +1465,7 @@ init_imstt(struct fb_info *info)
                info->node, info->fix.id, info->fix.smem_len >> 20, tmp);
 }
 
-static int __devinit
-imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned long addr, size;
        struct imstt_par *par;
@@ -1534,8 +1532,7 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 }
 
-static void __devexit
-imsttfb_remove(struct pci_dev *pdev)
+static void imsttfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct imstt_par *par = info->par;
index e501dbc966b3b2a3976d17956fc9bd9f387cec29..0abf2bf2083604c48006a63682c410c7125109fb 100644 (file)
@@ -139,6 +139,7 @@ struct imxfb_info {
        struct clk              *clk_ahb;
        struct clk              *clk_per;
        enum imxfb_type         devtype;
+       bool                    enabled;
 
        /*
         * These are the addresses we mapped
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
 
 static void imxfb_enable_controller(struct imxfb_info *fbi)
 {
+
+       if (fbi->enabled)
+               return;
+
        pr_debug("Enabling LCD controller\n");
 
        writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
        clk_prepare_enable(fbi->clk_ipg);
        clk_prepare_enable(fbi->clk_ahb);
        clk_prepare_enable(fbi->clk_per);
+       fbi->enabled = true;
 
        if (fbi->backlight_power)
                fbi->backlight_power(1);
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
 
 static void imxfb_disable_controller(struct imxfb_info *fbi)
 {
+       if (!fbi->enabled)
+               return;
+
        pr_debug("Disabling LCD controller\n");
 
        if (fbi->backlight_power)
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
        clk_disable_unprepare(fbi->clk_per);
        clk_disable_unprepare(fbi->clk_ipg);
        clk_disable_unprepare(fbi->clk_ahb);
+       fbi->enabled = false;
 
        writel(0, fbi->regs + LCDC_RMCR);
 }
@@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
 
        memset(fbi, 0, sizeof(struct imxfb_info));
 
+       fbi->devtype = pdev->id_entry->driver_data;
+
        strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
 
        info->fix.type                  = FB_TYPE_PACKED_PIXELS;
@@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        fbi = info->par;
-       fbi->devtype = pdev->id_entry->driver_data;
 
        if (!fb_mode)
                fb_mode = pdata->mode[0].mode.name;
@@ -917,7 +928,7 @@ failed_init:
        return ret;
 }
 
-static int __devexit imxfb_remove(struct platform_device *pdev)
+static int imxfb_remove(struct platform_device *pdev)
 {
        struct imx_fb_platform_data *pdata;
        struct fb_info *info = platform_get_drvdata(pdev);
@@ -959,7 +970,7 @@ void  imxfb_shutdown(struct platform_device * dev)
 static struct platform_driver imxfb_driver = {
        .suspend        = imxfb_suspend,
        .resume         = imxfb_resume,
-       .remove         = __devexit_p(imxfb_remove),
+       .remove         = imxfb_remove,
        .shutdown       = imxfb_shutdown,
        .driver         = {
                .name   = DRIVER_NAME,
index bdcbfbae277741e85b52f300f756d37bf3773a6c..8209e46c5d2875e9cda0de1bb3942212d0b211f9 100644 (file)
 #include "intelfbhw.h"
 #include "../edid.h"
 
-static void __devinit get_initial_mode(struct intelfb_info *dinfo);
+static void get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
                         struct fb_var_screeninfo *var);
 static int intelfb_open(struct fb_info *info, int user);
@@ -162,10 +162,10 @@ static int intelfb_sync(struct fb_info *info);
 static int intelfb_ioctl(struct fb_info *info,
                         unsigned int cmd, unsigned long arg);
 
-static int __devinit intelfb_pci_register(struct pci_dev *pdev,
-                                         const struct pci_device_id *ent);
-static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
-static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
+static int intelfb_pci_register(struct pci_dev *pdev,
+                               const struct pci_device_id *ent);
+static void intelfb_pci_unregister(struct pci_dev *pdev);
+static int intelfb_set_fbinfo(struct intelfb_info *dinfo);
 
 /*
  * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
@@ -177,7 +177,7 @@ static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
 #define INTELFB_CLASS_MASK 0
 #endif
 
-static struct pci_device_id intelfb_pci_table[] __devinitdata = {
+static struct pci_device_id intelfb_pci_table[] = {
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
@@ -219,7 +219,7 @@ static struct pci_driver intelfb_driver = {
        .name =         "intelfb",
        .id_table =     intelfb_pci_table,
        .probe =        intelfb_pci_register,
-       .remove =       __devexit_p(intelfb_pci_unregister)
+       .remove =       intelfb_pci_unregister,
 };
 
 /* Module description/parameters */
@@ -415,7 +415,7 @@ module_exit(intelfb_exit);
  ***************************************************************/
 
 #ifdef CONFIG_MTRR
-static inline void __devinit set_mtrr(struct intelfb_info *dinfo)
+static inline void set_mtrr(struct intelfb_info *dinfo)
 {
        dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
                                   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
@@ -497,8 +497,8 @@ static void cleanup(struct intelfb_info *dinfo)
 } while (0)
 
 
-static int __devinit intelfb_pci_register(struct pci_dev *pdev,
-                                         const struct pci_device_id *ent)
+static int intelfb_pci_register(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct intelfb_info *dinfo;
@@ -921,8 +921,7 @@ err_out_cmap:
        return -ENODEV;
 }
 
-static void __devexit
-intelfb_pci_unregister(struct pci_dev *pdev)
+static void intelfb_pci_unregister(struct pci_dev *pdev)
 {
        struct intelfb_info *dinfo = pci_get_drvdata(pdev);
 
@@ -970,7 +969,7 @@ static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
  *                Various intialisation functions              *
  ***************************************************************/
 
-static void __devinit get_initial_mode(struct intelfb_info *dinfo)
+static void get_initial_mode(struct intelfb_info *dinfo)
 {
        struct fb_var_screeninfo *var;
        int xtot, ytot;
@@ -1037,7 +1036,7 @@ static void __devinit get_initial_mode(struct intelfb_info *dinfo)
        }
 }
 
-static int __devinit intelfb_init_var(struct intelfb_info *dinfo)
+static int intelfb_init_var(struct intelfb_info *dinfo)
 {
        struct fb_var_screeninfo *var;
        int msrc = 0;
@@ -1118,7 +1117,7 @@ static int __devinit intelfb_init_var(struct intelfb_info *dinfo)
        return 0;
 }
 
-static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo)
+static int intelfb_set_fbinfo(struct intelfb_info *dinfo)
 {
        struct fb_info *info = dinfo->info;
 
index 4d25711b99829926c9033d77240265025efecaa7..d999bb5e04851bf857dc396c318dbead0de1bb15 100644 (file)
@@ -136,7 +136,7 @@ struct jzfb {
        uint32_t pseudo_palette[16];
 };
 
-static const struct fb_fix_screeninfo jzfb_fix __devinitconst = {
+static const struct fb_fix_screeninfo jzfb_fix = {
        .id             = "JZ4740 FB",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_TRUECOLOR,
@@ -619,7 +619,7 @@ static struct  fb_ops jzfb_ops = {
        .fb_setcolreg = jzfb_setcolreg,
 };
 
-static int __devinit jzfb_probe(struct platform_device *pdev)
+static int jzfb_probe(struct platform_device *pdev)
 {
        int ret;
        struct jzfb *jzfb;
@@ -725,7 +725,7 @@ err_framebuffer_release:
        return ret;
 }
 
-static int __devexit jzfb_remove(struct platform_device *pdev)
+static int jzfb_remove(struct platform_device *pdev)
 {
        struct jzfb *jzfb = platform_get_drvdata(pdev);
 
@@ -794,7 +794,7 @@ static const struct dev_pm_ops jzfb_pm_ops = {
 
 static struct platform_driver jzfb_driver = {
        .probe = jzfb_probe,
-       .remove = __devexit_p(jzfb_remove),
+       .remove = jzfb_remove,
        .driver = {
                .name = "jz4740-fb",
                .pm = JZFB_PM_OPS,
index acb9370fdb147277e733df39934706eabb8a0645..6157f74ac600529d66f8d71fa8f6d3d5d95a5e5a 100644 (file)
 #define KHZ2PICOS(a) (1000000000UL/(a))
 
 /****************************************************************************/
-static struct fb_fix_screeninfo kyro_fix __devinitdata = {
+static struct fb_fix_screeninfo kyro_fix = {
        .id             = "ST Kyro",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_TRUECOLOR,
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo kyro_var __devinitdata = {
+static struct fb_var_screeninfo kyro_var = {
        /* 640x480, 16bpp @ 60 Hz */
        .xres           = 640,
        .yres           = 480,
@@ -81,18 +81,18 @@ typedef struct {
 /* global graphics card info structure (one per card) */
 static device_info_t deviceInfo;
 
-static char *mode_option __devinitdata = NULL;
-static int nopan __devinitdata = 0;
-static int nowrap __devinitdata = 1;
+static char *mode_option = NULL;
+static int nopan = 0;
+static int nowrap = 1;
 #ifdef CONFIG_MTRR
-static int nomtrr __devinitdata = 0;
+static int nomtrr = 0;
 #endif
 
 /* PCI driver prototypes */
 static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void kyrofb_remove(struct pci_dev *pdev);
 
-static struct fb_videomode kyro_modedb[] __devinitdata = {
+static struct fb_videomode kyro_modedb[] = {
        {
                /* 640x350 @ 85Hz */
                NULL, 85, 640, 350, KHZ2PICOS(31500),
@@ -653,7 +653,7 @@ static struct pci_driver kyrofb_pci_driver = {
        .name           = "kyrofb",
        .id_table       = kyrofb_pci_tbl,
        .probe          = kyrofb_probe,
-       .remove         = __devexit_p(kyrofb_remove),
+       .remove         = kyrofb_remove,
 };
 
 static struct fb_ops kyrofb_ops = {
@@ -667,8 +667,7 @@ static struct fb_ops kyrofb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int __devinit kyrofb_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct kyrofb_info *currentpar;
@@ -754,7 +753,7 @@ out_unmap:
        return -EINVAL;
 }
 
-static void __devexit kyrofb_remove(struct pci_dev *pdev)
+static void kyrofb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct kyrofb_info *par = info->par;
index 9e946e2c1da91fd67e1a3f5198f340f109f79ead..b17f5009a4363dab5546c57891c4d2564814737c 100644 (file)
@@ -547,7 +547,7 @@ static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
                of_iounmap(&op->resource[0], info->screen_base, 0x800000);
 }
 
-static int __devinit leo_probe(struct platform_device *op)
+static int leo_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -636,7 +636,7 @@ out_err:
        return err;
 }
 
-static int __devexit leo_remove(struct platform_device *op)
+static int leo_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct leo_par *par = info->par;
@@ -668,7 +668,7 @@ static struct platform_driver leo_driver = {
                .of_match_table = leo_match,
        },
        .probe          = leo_probe,
-       .remove         = __devexit_p(leo_remove),
+       .remove         = leo_remove,
 };
 
 static int __init leo_init(void)
index d68e332aa21c39d963b37bc3e7f5039a01c8c85c..91c59c9fb082be72d2862aeb88ab47129902aa57 100644 (file)
@@ -668,7 +668,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
        return 0;
 }
 
-static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
+static int of_platform_mb862xx_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct device *dev = &ofdev->dev;
@@ -786,7 +786,7 @@ fbrel:
        return ret;
 }
 
-static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
+static int of_platform_mb862xx_remove(struct platform_device *ofdev)
 {
        struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
        struct mb862xxfb_par *par = fbi->par;
@@ -823,7 +823,7 @@ static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
 /*
  * common types
  */
-static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = {
+static struct of_device_id of_platform_mb862xx_tbl[] = {
        { .compatible = "fujitsu,MB86276", },
        { .compatible = "fujitsu,lime", },
        { .compatible = "fujitsu,MB86277", },
@@ -841,7 +841,7 @@ static struct platform_driver of_platform_mb862xxfb_driver = {
                .of_match_table = of_platform_mb862xx_tbl,
        },
        .probe          = of_platform_mb862xx_probe,
-       .remove         = __devexit_p(of_platform_mb862xx_remove),
+       .remove         = of_platform_mb862xx_remove,
 };
 #endif
 
@@ -984,7 +984,7 @@ static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par)
 #define CHIP_ID(id)    \
        { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }
 
-static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = {
+static struct pci_device_id mb862xx_pci_tbl[] = {
        /* MB86295/MB86296 */
        CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP),
        CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA),
@@ -995,8 +995,8 @@ static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);
 
-static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int mb862xx_pci_probe(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        struct mb862xxfb_par *par;
        struct fb_info *info;
@@ -1133,7 +1133,7 @@ out:
        return ret;
 }
 
-static void __devexit mb862xx_pci_remove(struct pci_dev *pdev)
+static void mb862xx_pci_remove(struct pci_dev *pdev)
 {
        struct fb_info *fbi = pci_get_drvdata(pdev);
        struct mb862xxfb_par *par = fbi->par;
@@ -1174,11 +1174,11 @@ static struct pci_driver mb862xxfb_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = mb862xx_pci_tbl,
        .probe          = mb862xx_pci_probe,
-       .remove         = __devexit_p(mb862xx_pci_remove),
+       .remove         = mb862xx_pci_remove,
 };
 #endif
 
-static int __devinit mb862xxfb_init(void)
+static int mb862xxfb_init(void)
 {
        int ret = -ENODEV;
 
index 12dec7634c5548b4c10c5ba88c0c1d0acb1fa4d5..4449f249b0e7cefce685cd8e9f30152df76ca479 100644 (file)
@@ -213,7 +213,7 @@ static const struct file_operations misc_fops = {
        .llseek = default_llseek,
 };
 
-static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
+static void mbxfb_debugfs_init(struct fb_info *fbi)
 {
        struct mbxfb_info *mfbi = fbi->par;
        struct mbxfb_debugfs_data *dbg;
@@ -236,7 +236,7 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
                                        fbi, &misc_fops);
 }
 
-static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
+static void mbxfb_debugfs_remove(struct fb_info *fbi)
 {
        struct mbxfb_info *mfbi = fbi->par;
        struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
index 6563e50413c1c01dde5e703281ee47cac459f4b6..0c1a874ffd2bfd100be9e8f0b77bd6c0a30e90de 100644 (file)
@@ -79,7 +79,7 @@ struct mbxfb_info {
 
 };
 
-static struct fb_var_screeninfo mbxfb_default __devinitdata = {
+static struct fb_var_screeninfo mbxfb_default = {
        .xres = 640,
        .yres = 480,
        .xres_virtual = 640,
@@ -102,7 +102,7 @@ static struct fb_var_screeninfo mbxfb_default __devinitdata = {
        .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 };
 
-static struct fb_fix_screeninfo mbxfb_fix  __devinitdata = {
+static struct fb_fix_screeninfo mbxfb_fix = {
        .id = "MBX",
        .type = FB_TYPE_PACKED_PIXELS,
        .visual = FB_VISUAL_TRUECOLOR,
@@ -687,7 +687,7 @@ static struct fb_ops mbxfb_ops = {
   Enable external SDRAM controller. Assume that all clocks are active
   by now.
 */
-static void __devinit setup_memc(struct fb_info *fbi)
+static void setup_memc(struct fb_info *fbi)
 {
        unsigned long tmp;
        int i;
@@ -747,7 +747,7 @@ static void enable_clocks(struct fb_info *fbi)
        write_reg_dly(0x00000001, PIXCLKDIV);
 }
 
-static void __devinit setup_graphics(struct fb_info *fbi)
+static void setup_graphics(struct fb_info *fbi)
 {
        unsigned long gsctrl;
        unsigned long vscadr;
@@ -781,7 +781,7 @@ static void __devinit setup_graphics(struct fb_info *fbi)
        write_reg_dly(vscadr, VSCADR);
 }
 
-static void __devinit setup_display(struct fb_info *fbi)
+static void setup_display(struct fb_info *fbi)
 {
        unsigned long dsctrl = 0;
 
@@ -795,7 +795,7 @@ static void __devinit setup_display(struct fb_info *fbi)
        write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
 }
 
-static void __devinit enable_controller(struct fb_info *fbi)
+static void enable_controller(struct fb_info *fbi)
 {
        u32 svctrl, shctrl;
 
@@ -881,7 +881,7 @@ static int mbxfb_resume(struct platform_device *dev)
 
 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
 
-static int __devinit mbxfb_probe(struct platform_device *dev)
+static int mbxfb_probe(struct platform_device *dev)
 {
        int ret;
        struct fb_info *fbi;
@@ -1006,7 +1006,7 @@ err1:
        return ret;
 }
 
-static int __devexit mbxfb_remove(struct platform_device *dev)
+static int mbxfb_remove(struct platform_device *dev)
 {
        struct fb_info *fbi = platform_get_drvdata(dev);
 
@@ -1038,7 +1038,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
 
 static struct platform_driver mbxfb_driver = {
        .probe = mbxfb_probe,
-       .remove = __devexit_p(mbxfb_remove),
+       .remove = mbxfb_remove,
        .suspend = mbxfb_suspend,
        .resume = mbxfb_resume,
        .driver = {
index 97d45e5115e254647454d7c5b7598053944c7273..f30150d71be90bdd31aadbcd87beded46b8ae101 100644 (file)
@@ -99,7 +99,7 @@ static struct epd_frame epd_frame_table[] = {
        },
 };
 
-static struct fb_fix_screeninfo metronomefb_fix __devinitdata = {
+static struct fb_fix_screeninfo metronomefb_fix = {
        .id =           "metronomefb",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_STATIC_PSEUDOCOLOR,
@@ -110,7 +110,7 @@ static struct fb_fix_screeninfo metronomefb_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo metronomefb_var __devinitdata = {
+static struct fb_var_screeninfo metronomefb_var = {
        .xres           = DPY_W,
        .yres           = DPY_H,
        .xres_virtual   = DPY_W,
@@ -167,8 +167,8 @@ static u16 calc_img_cksum(u16 *start, int length)
 }
 
 /* here we decode the incoming waveform file and populate metromem */
-static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
-                               struct metronomefb_par *par)
+static int load_waveform(u8 *mem, size_t size, int m, int t,
+                        struct metronomefb_par *par)
 {
        int tta;
        int wmta;
@@ -338,7 +338,7 @@ static int metronome_display_cmd(struct metronomefb_par *par)
        return par->board->met_wait_event_intr(par);
 }
 
-static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
+static int metronome_powerup_cmd(struct metronomefb_par *par)
 {
        int i;
        u16 cs;
@@ -367,7 +367,7 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
        return par->board->met_wait_event(par);
 }
 
-static int __devinit metronome_config_cmd(struct metronomefb_par *par)
+static int metronome_config_cmd(struct metronomefb_par *par)
 {
        /* setup config command
        we can't immediately set the opcode since the controller
@@ -385,7 +385,7 @@ static int __devinit metronome_config_cmd(struct metronomefb_par *par)
        return par->board->met_wait_event(par);
 }
 
-static int __devinit metronome_init_cmd(struct metronomefb_par *par)
+static int metronome_init_cmd(struct metronomefb_par *par)
 {
        int i;
        u16 cs;
@@ -411,7 +411,7 @@ static int __devinit metronome_init_cmd(struct metronomefb_par *par)
        return par->board->met_wait_event(par);
 }
 
-static int __devinit metronome_init_regs(struct metronomefb_par *par)
+static int metronome_init_regs(struct metronomefb_par *par)
 {
        int res;
 
@@ -569,7 +569,7 @@ static struct fb_deferred_io metronomefb_defio = {
        .deferred_io    = metronomefb_dpy_deferred_io,
 };
 
-static int __devinit metronomefb_probe(struct platform_device *dev)
+static int metronomefb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct metronome_board *board;
@@ -741,7 +741,7 @@ err:
        return retval;
 }
 
-static int __devexit metronomefb_remove(struct platform_device *dev)
+static int metronomefb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -763,7 +763,7 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
 
 static struct platform_driver metronomefb_driver = {
        .probe  = metronomefb_probe,
-       .remove = __devexit_p(metronomefb_remove),
+       .remove = metronomefb_remove,
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "metronomefb",
index 35ac9e8bee63f13a30133382dca3a8f43aa7a25d..e0f8011a3c4bd1b26a2fd80a1a782ecc62ea2cad 100644 (file)
@@ -417,7 +417,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
        mddi_set_auto_hibernate(&mddi->client_data, 1);
 }
 
-static int __devinit mddi_get_client_caps(struct mddi_info *mddi)
+static int mddi_get_client_caps(struct mddi_info *mddi)
 {
        int i, j;
 
@@ -619,9 +619,8 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
 
 static struct mddi_info mddi_info[2];
 
-static int __devinit mddi_clk_setup(struct platform_device *pdev,
-                                   struct mddi_info *mddi,
-                                   unsigned long clk_rate)
+static int mddi_clk_setup(struct platform_device *pdev, struct mddi_info *mddi,
+                         unsigned long clk_rate)
 {
        int ret;
 
@@ -664,7 +663,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
        return 0;
 }
 
-static int __devinit mddi_probe(struct platform_device *pdev)
+static int mddi_probe(struct platform_device *pdev)
 {
        struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
        struct mddi_info *mddi = &mddi_info[pdev->id];
index 49619b4415000efc1ef87756d09667017a682244..755556ca5b2d988ec68b8cc3c1f9bbe7aadf6a34 100644 (file)
@@ -369,7 +369,8 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
                loop--;
        }
 
-       writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR);
+       reg = readl(host->base + LCDC_VDCTRL4);
+       writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
 
        clk_disable_unprepare(host->clk);
 
@@ -586,7 +587,7 @@ static struct fb_ops mxsfb_ops = {
        .fb_imageblit = cfb_imageblit,
 };
 
-static int __devinit mxsfb_restore_mode(struct mxsfb_info *host)
+static int mxsfb_restore_mode(struct mxsfb_info *host)
 {
        struct fb_info *fb_info = &host->fb_info;
        unsigned line_count;
@@ -677,7 +678,7 @@ static int __devinit mxsfb_restore_mode(struct mxsfb_info *host)
        return 0;
 }
 
-static int __devinit mxsfb_init_fbinfo(struct mxsfb_info *host)
+static int mxsfb_init_fbinfo(struct mxsfb_info *host)
 {
        struct fb_info *fb_info = &host->fb_info;
        struct fb_var_screeninfo *var = &fb_info->var;
@@ -739,7 +740,7 @@ static int __devinit mxsfb_init_fbinfo(struct mxsfb_info *host)
        return 0;
 }
 
-static void __devexit mxsfb_free_videomem(struct mxsfb_info *host)
+static void mxsfb_free_videomem(struct mxsfb_info *host)
 {
        struct fb_info *fb_info = &host->fb_info;
 
@@ -772,7 +773,7 @@ static const struct of_device_id mxsfb_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
 
-static int __devinit mxsfb_probe(struct platform_device *pdev)
+static int mxsfb_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id =
                        of_match_device(mxsfb_dt_ids, &pdev->dev);
@@ -912,7 +913,7 @@ error_alloc_info:
        return ret;
 }
 
-static int __devexit mxsfb_remove(struct platform_device *pdev)
+static int mxsfb_remove(struct platform_device *pdev)
 {
        struct fb_info *fb_info = platform_get_drvdata(pdev);
        struct mxsfb_info *host = to_imxfb_host(fb_info);
@@ -949,7 +950,7 @@ static void mxsfb_shutdown(struct platform_device *pdev)
 
 static struct platform_driver mxsfb_driver = {
        .probe = mxsfb_probe,
-       .remove = __devexit_p(mxsfb_remove),
+       .remove = mxsfb_remove,
        .shutdown = mxsfb_shutdown,
        .id_table = mxsfb_devtype,
        .driver = {
index afc9521173effee7fbc5f5814194e25807e98db7..7ef079c146e7242c9edee33cc43bc0cd3c850ce1 100644 (file)
@@ -88,7 +88,7 @@ static bool external;
 static bool libretto;
 static bool nostretch;
 static bool nopciburst;
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
 #ifdef MODULE
 
@@ -1632,7 +1632,7 @@ static struct fb_ops neofb_ops = {
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_videomode __devinitdata mode800x480 = {
+static struct fb_videomode mode800x480 = {
        .xres           = 800,
        .yres           = 480,
        .pixclock       = 25000,
@@ -1646,8 +1646,7 @@ static struct fb_videomode __devinitdata mode800x480 = {
        .vmode          = FB_VMODE_NONINTERLACED
 };
 
-static int __devinit neo_map_mmio(struct fb_info *info,
-                                 struct pci_dev *dev)
+static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
 {
        struct neofb_par *par = info->par;
 
@@ -1707,8 +1706,8 @@ static void neo_unmap_mmio(struct fb_info *info)
                           info->fix.mmio_len);
 }
 
-static int __devinit neo_map_video(struct fb_info *info,
-                                  struct pci_dev *dev, int video_len)
+static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
+                        int video_len)
 {
        //unsigned long addr;
 
@@ -1772,7 +1771,7 @@ static void neo_unmap_video(struct fb_info *info)
                           info->fix.smem_len);
 }
 
-static int __devinit neo_scan_monitor(struct fb_info *info)
+static int neo_scan_monitor(struct fb_info *info)
 {
        struct neofb_par *par = info->par;
        unsigned char type, display;
@@ -1851,7 +1850,7 @@ static int __devinit neo_scan_monitor(struct fb_info *info)
        return 0;
 }
 
-static int __devinit neo_init_hw(struct fb_info *info)
+static int neo_init_hw(struct fb_info *info)
 {
        struct neofb_par *par = info->par;
        int videoRam = 896;
@@ -1939,8 +1938,8 @@ static int __devinit neo_init_hw(struct fb_info *info)
 }
 
 
-static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const struct
-                                                  pci_device_id *id)
+static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
+                                        const struct pci_device_id *id)
 {
        struct fb_info *info;
        struct neofb_par *par;
@@ -2038,8 +2037,7 @@ static void neo_free_fb_info(struct fb_info *info)
 
 /* --------------------------------------------------------------------- */
 
-static int __devinit neofb_probe(struct pci_dev *dev,
-                                const struct pci_device_id *id)
+static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct fb_info *info;
        u_int h_sync, v_sync;
@@ -2128,7 +2126,7 @@ err_map_mmio:
        return err;
 }
 
-static void __devexit neofb_remove(struct pci_dev *dev)
+static void neofb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -2194,7 +2192,7 @@ static struct pci_driver neofb_driver = {
        .name =         "neofb",
        .id_table =     neofb_devices,
        .probe =        neofb_probe,
-       .remove =       __devexit_p(neofb_remove)
+       .remove =       neofb_remove,
 };
 
 /* ************************* init in-kernel code ************************** */
index 475dfee82c4a1207e7ce1107e6a94fd6b49f1a46..32581c72ad097f8eebb75a140b0389897708f284 100644 (file)
@@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
  *    The buffer should be a non-cached, non-buffered, memory region
  *    to allow palette and pixel writes without flushing the cache.
  */
-static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
+static int nuc900fb_map_video_memory(struct fb_info *info)
 {
        struct nuc900fb_info *fbi = info->par;
        dma_addr_t map_dma;
@@ -499,7 +499,7 @@ static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
 
 static char driver_name[] = "nuc900fb";
 
-static int __devinit nuc900fb_probe(struct platform_device *pdev)
+static int nuc900fb_probe(struct platform_device *pdev)
 {
        struct nuc900fb_info *fbi;
        struct nuc900fb_display *display;
index fe13ac567d545b9408bc6e00bb108cf7b0c0d69f..ff228713425ebb31e079d9e9eeea5d581a8ba756 100644 (file)
@@ -70,34 +70,34 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
 
 /* command line data, set in nvidiafb_setup() */
-static int flatpanel __devinitdata = -1;       /* Autodetect later */
-static int fpdither __devinitdata = -1;
-static int forceCRTC __devinitdata = -1;
-static int hwcur __devinitdata = 0;
-static int noaccel __devinitdata = 0;
-static int noscale __devinitdata = 0;
-static int paneltweak __devinitdata = 0;
-static int vram __devinitdata = 0;
-static int bpp __devinitdata = 8;
-static int reverse_i2c __devinitdata;
+static int flatpanel = -1;     /* Autodetect later */
+static int fpdither = -1;
+static int forceCRTC = -1;
+static int hwcur = 0;
+static int noaccel = 0;
+static int noscale = 0;
+static int paneltweak = 0;
+static int vram = 0;
+static int bpp = 8;
+static int reverse_i2c;
 #ifdef CONFIG_MTRR
-static bool nomtrr __devinitdata = false;
+static bool nomtrr = false;
 #endif
 #ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight __devinitdata = 1;
+static int backlight = 1;
 #else
-static int backlight __devinitdata = 0;
+static int backlight = 0;
 #endif
 
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
-static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
+static struct fb_fix_screeninfo nvidiafb_fix = {
        .type = FB_TYPE_PACKED_PIXELS,
        .xpanstep = 8,
        .ypanstep = 1,
 };
 
-static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
+static struct fb_var_screeninfo nvidiafb_default_var = {
        .xres = 640,
        .yres = 480,
        .xres_virtual = 640,
@@ -1105,7 +1105,7 @@ fail:
 #define nvidiafb_resume NULL
 #endif
 
-static int __devinit nvidia_set_fbinfo(struct fb_info *info)
+static int nvidia_set_fbinfo(struct fb_info *info)
 {
        struct fb_monspecs *specs = &info->monspecs;
        struct fb_videomode modedb;
@@ -1201,7 +1201,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
        return nvidiafb_check_var(&info->var, info);
 }
 
-static u32 __devinit nvidia_get_chipset(struct fb_info *info)
+static u32 nvidia_get_chipset(struct fb_info *info)
 {
        struct nvidia_par *par = info->par;
        u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
@@ -1224,7 +1224,7 @@ static u32 __devinit nvidia_get_chipset(struct fb_info *info)
        return id;
 }
 
-static u32 __devinit nvidia_get_arch(struct fb_info *info)
+static u32 nvidia_get_arch(struct fb_info *info)
 {
        struct nvidia_par *par = info->par;
        u32 arch = 0;
@@ -1276,8 +1276,7 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info)
        return arch;
 }
 
-static int __devinit nvidiafb_probe(struct pci_dev *pd,
-                                   const struct pci_device_id *ent)
+static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
 {
        struct nvidia_par *par;
        struct fb_info *info;
@@ -1438,7 +1437,7 @@ err_out:
        return -ENODEV;
 }
 
-static void __devexit nvidiafb_remove(struct pci_dev *pd)
+static void nvidiafb_remove(struct pci_dev *pd)
 {
        struct fb_info *info = pci_get_drvdata(pd);
        struct nvidia_par *par = info->par;
@@ -1473,7 +1472,7 @@ static void __devexit nvidiafb_remove(struct pci_dev *pd)
  * ------------------------------------------------------------------------- */
 
 #ifndef MODULE
-static int __devinit nvidiafb_setup(char *options)
+static int nvidiafb_setup(char *options)
 {
        char *this_opt;
 
@@ -1529,7 +1528,7 @@ static struct pci_driver nvidiafb_driver = {
        .probe    = nvidiafb_probe,
        .suspend  = nvidiafb_suspend,
        .resume   = nvidiafb_resume,
-       .remove   = __devexit_p(nvidiafb_remove),
+       .remove   = nvidiafb_remove,
 };
 
 /* ------------------------------------------------------------------------- *
@@ -1538,7 +1537,7 @@ static struct pci_driver nvidiafb_driver = {
  *
  * ------------------------------------------------------------------------- */
 
-static int __devinit nvidiafb_init(void)
+static int nvidiafb_init(void)
 {
 #ifndef MODULE
        char *option = NULL;
index b739600c51ac3aff71fab4ee197660f59b47c33f..803fee618d57dbf31db2138b0ea6fd6ca346e084 100644 (file)
@@ -606,7 +606,7 @@ static struct spi_driver mipid_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = mipid_spi_probe,
-       .remove = __devexit_p(mipid_spi_remove),
+       .remove = mipid_spi_remove,
 };
 
 module_spi_driver(mipid_spi_driver);
index 65eb76c840a113765ba6afdae85428c2f24e478f..72699f88c00215bc41f5f775f17caf8399dc1e23 100644 (file)
@@ -777,7 +777,7 @@ static struct spi_driver acx565akm_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = acx565akm_spi_probe,
-       .remove = __devexit_p(acx565akm_spi_remove),
+       .remove = acx565akm_spi_remove,
 };
 
 module_spi_driver(acx565akm_spi_driver);
index ace419b801eb6c302fadb26757ffcde8f78fba09..6e5abe8fd2ddbe9f94dcd384c9235c56de1dd3d6 100644 (file)
@@ -216,13 +216,13 @@ static void init_lb035q02_panel(struct spi_device *spi)
        lb035q02_write_reg(spi, 0x3b, 0x0806);
 }
 
-static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi)
+static int lb035q02_panel_spi_probe(struct spi_device *spi)
 {
        init_lb035q02_panel(spi);
        return omap_dss_register_driver(&lb035q02_driver);
 }
 
-static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi)
+static int lb035q02_panel_spi_remove(struct spi_device *spi)
 {
        omap_dss_unregister_driver(&lb035q02_driver);
        return 0;
@@ -234,7 +234,7 @@ static struct spi_driver lb035q02_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = lb035q02_panel_spi_probe,
-       .remove         = __devexit_p(lb035q02_panel_spi_remove),
+       .remove         = lb035q02_panel_spi_remove,
 };
 
 module_spi_driver(lb035q02_spi_driver);
index d1cb722fcdbcea123247b6530d296d5539e3cc9e..dd129475080297de33f239dfc903bb990fd373c5 100644 (file)
@@ -680,7 +680,7 @@ static struct spi_driver mipid_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = mipid_spi_probe,
-       .remove = __devexit_p(mipid_spi_remove),
+       .remove = mipid_spi_remove,
 };
 module_spi_driver(mipid_spi_driver);
 
index 2a79c283bebe471b3b9410b2649857b6ec2fe0d0..c4e9c2b1b465c135e6ddb2c33d01161e41f737a8 100644 (file)
@@ -323,7 +323,7 @@ static int nec_8048_spi_resume(struct spi_device *spi)
 
 static struct spi_driver nec_8048_spi_driver = {
        .probe          = nec_8048_spi_probe,
-       .remove         = __devexit_p(nec_8048_spi_remove),
+       .remove         = nec_8048_spi_remove,
        .suspend        = nec_8048_spi_suspend,
        .resume         = nec_8048_spi_resume,
        .driver         = {
index 316b3da6d2cb99e356332b3ef218cf3f822c7ab0..6b6643911d296c707e7eaa29c30412081378cc5f 100644 (file)
@@ -528,7 +528,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
+static int tpo_td043_spi_remove(struct spi_device *spi)
 {
        struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
 
@@ -580,7 +580,7 @@ static struct spi_driver tpo_td043_spi_driver = {
                .pm     = &tpo_td043_spi_pm,
        },
        .probe  = tpo_td043_spi_probe,
-       .remove = __devexit_p(tpo_td043_spi_remove),
+       .remove = tpo_td043_spi_remove,
 };
 
 module_spi_driver(tpo_td043_spi_driver);
index 18688c12e30d9e5399d732ce6d972d101ae46b55..d7d66ef5cb58098c6f80268651c0a277957fc2e0 100644 (file)
@@ -538,6 +538,7 @@ static const enum dss_feat_id omap3630_dss_feat_list[] = {
        FEAT_ALPHA_FIXED_ZORDER,
        FEAT_FIFO_MERGE,
        FEAT_OMAP3_DSI_FIFO_BUG,
+       FEAT_DPI_USES_VDDS_DSI,
 };
 
 static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
index d57cc58c5168c8948b6c62d01800fa40503f6638..4b23af6e5c2890b41f47fd38a9e88ce2de3ebc9c 100644 (file)
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
        info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 }
 
-static int __devinit p9100_probe(struct platform_device *op)
+static int p9100_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -326,7 +326,7 @@ out_err:
        return err;
 }
 
-static int __devexit p9100_remove(struct platform_device *op)
+static int p9100_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct p9100_par *par = info->par;
@@ -359,7 +359,7 @@ static struct platform_driver p9100_driver = {
                .of_match_table = p9100_match,
        },
        .probe          = p9100_probe,
-       .remove         = __devexit_p(p9100_remove),
+       .remove         = p9100_remove,
 };
 
 static int __init p9100_init(void)
index ae3caa6755c2f63adf6144bec61c121854cebbb9..3d86bac62d3e62214564bf1f336488d6ee819eeb 100644 (file)
@@ -313,7 +313,8 @@ static void platinum_set_hardware(struct fb_info_platinum *pinfo)
 /*
  * Set misc info vars for this driver
  */
-static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_platinum *pinfo)
+static void platinum_init_info(struct fb_info *info,
+                              struct fb_info_platinum *pinfo)
 {
        /* Fill fb_info */
        info->fbops = &platinumfb_ops;
@@ -338,7 +339,7 @@ static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_pl
 }
 
 
-static int __devinit platinum_init_fb(struct fb_info *info)
+static int platinum_init_fb(struct fb_info *info)
 {
        struct fb_info_platinum *pinfo = info->par;
        struct fb_var_screeninfo var;
@@ -533,7 +534,7 @@ static int __init platinumfb_setup(char *options)
 #define invalidate_cache(addr)
 #endif
 
-static int __devinit platinumfb_probe(struct platform_device* odev)
+static int platinumfb_probe(struct platform_device* odev)
 {
        struct device_node      *dp = odev->dev.of_node;
        struct fb_info          *info;
@@ -645,7 +646,7 @@ static int __devinit platinumfb_probe(struct platform_device* odev)
        return rc;
 }
 
-static int __devexit platinumfb_remove(struct platform_device* odev)
+static int platinumfb_remove(struct platform_device* odev)
 {
        struct fb_info          *info = dev_get_drvdata(&odev->dev);
        struct fb_info_platinum *pinfo = info->par;
@@ -683,7 +684,7 @@ static struct platform_driver platinum_driver =
                .of_match_table = platinumfb_match,
        },
        .probe          = platinumfb_probe,
-       .remove         = __devexit_p(platinumfb_remove),
+       .remove         = platinumfb_remove,
 };
 
 static int __init platinumfb_init(void)
index df31a24a5026e9af75a56c0e3b66ad8718a27703..81354eeab0214e106ae89e1e5ad321afbbf000ce 100644 (file)
@@ -67,7 +67,7 @@
  * Driver data
  */
 static int hwcursor = 1;
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 /*
  * The XFree GLINT driver will (I think to implement hardware cursor
@@ -80,10 +80,10 @@ static char *mode_option __devinitdata;
  */
 static bool lowhsync;
 static bool lowvsync;
-static bool noaccel __devinitdata;
+static bool noaccel;
 /* mtrr option */
 #ifdef CONFIG_MTRR
-static bool nomtrr __devinitdata;
+static bool nomtrr;
 #endif
 
 /*
@@ -107,7 +107,7 @@ struct pm2fb_par
  * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
  * if we don't use modedb.
  */
-static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
+static struct fb_fix_screeninfo pm2fb_fix = {
        .id =           "",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -120,7 +120,7 @@ static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
 /*
  * Default video mode. In case the modedb doesn't work.
  */
-static struct fb_var_screeninfo pm2fb_var __devinitdata = {
+static struct fb_var_screeninfo pm2fb_var = {
        /* "640x480, 8 bpp @ 60 Hz */
        .xres =                 640,
        .yres =                 480,
@@ -1515,8 +1515,7 @@ static struct fb_ops pm2fb_ops = {
  * @param      pdev    PCI device.
  * @param      id      PCI device ID.
  */
-static int __devinit pm2fb_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *id)
+static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct pm2fb_par *default_par;
        struct fb_info *info;
@@ -1727,7 +1726,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
  *
  * @param      pdev    PCI device to clean up.
  */
-static void __devexit pm2fb_remove(struct pci_dev *pdev)
+static void pm2fb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct fb_fix_screeninfo *fix = &info->fix;
@@ -1765,7 +1764,7 @@ static struct pci_driver pm2fb_driver = {
        .name           = "pm2fb",
        .id_table       = pm2fb_id_table,
        .probe          = pm2fb_probe,
-       .remove         = __devexit_p(pm2fb_remove),
+       .remove         = pm2fb_remove,
 };
 
 MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
index 055e527a8e4510383f6ebb7f0d4bd4838f3bcfce..7718faa4a73b751d37525d5e775f21e32d4dca64 100644 (file)
  * Driver data
  */
 static int hwcursor = 1;
-static char *mode_option __devinitdata;
-static bool noaccel __devinitdata;
+static char *mode_option;
+static bool noaccel;
 
 /* mtrr option */
 #ifdef CONFIG_MTRR
-static bool nomtrr __devinitdata;
+static bool nomtrr;
 #endif
 
 /*
@@ -84,7 +84,7 @@ struct pm3_par {
  * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
  * to get a fb_var_screeninfo. Otherwise define a default var as well.
  */
-static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
+static struct fb_fix_screeninfo pm3fb_fix = {
        .id =           "Permedia3",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -1229,7 +1229,7 @@ static struct fb_ops pm3fb_ops = {
 
 /* mmio register are already mapped when this function is called */
 /* the pm3fb_fix.smem_start is also set */
-static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par)
+static unsigned long pm3fb_size_memory(struct pm3_par *par)
 {
        unsigned long   memsize = 0;
        unsigned long   tempBypass, i, temp1, temp2;
@@ -1314,8 +1314,7 @@ static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par)
        return memsize;
 }
 
-static int __devinit pm3fb_probe(struct pci_dev *dev,
-                                 const struct pci_device_id *ent)
+static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct pm3_par *par;
@@ -1469,7 +1468,7 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
        /*
         *  Cleanup
         */
-static void __devexit pm3fb_remove(struct pci_dev *dev)
+static void pm3fb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -1507,7 +1506,7 @@ static struct pci_driver pm3fb_driver = {
        .name =         "pm3fb",
        .id_table =     pm3fb_id_table,
        .probe =        pm3fb_probe,
-       .remove =       __devexit_p(pm3fb_remove),
+       .remove =       pm3fb_remove,
 };
 
 MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
index 9b4a60b52a4ca9cf403f22a172e2bc5e3a93c270..d1e46cedb1f721b7219ca0cbe37014c0e6296092 100644 (file)
@@ -43,7 +43,7 @@ struct pmagbafb_par {
 };
 
 
-static struct fb_var_screeninfo pmagbafb_defined __devinitdata = {
+static struct fb_var_screeninfo pmagbafb_defined = {
        .xres           = 1024,
        .yres           = 864,
        .xres_virtual   = 1024,
@@ -67,7 +67,7 @@ static struct fb_var_screeninfo pmagbafb_defined __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo pmagbafb_fix __devinitdata = {
+static struct fb_fix_screeninfo pmagbafb_fix = {
        .id             = "PMAG-BA",
        .smem_len       = (1024 * 1024),
        .type           = FB_TYPE_PACKED_PIXELS,
@@ -141,7 +141,7 @@ static void __init pmagbafb_erase_cursor(struct fb_info *info)
 }
 
 
-static int __devinit pmagbafb_probe(struct device *dev)
+static int pmagbafb_probe(struct device *dev)
 {
        struct tc_dev *tdev = to_tc_dev(dev);
        resource_size_t start, len;
index 4e7a9c46e1122a460957e0a3c22f6cf04b9d8961..0e1317400328c6860b542a763e282ef21572b62b 100644 (file)
@@ -44,7 +44,7 @@ struct pmagbbfb_par {
 };
 
 
-static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {
+static struct fb_var_screeninfo pmagbbfb_defined = {
        .bits_per_pixel = 8,
        .red.length     = 8,
        .green.length   = 8,
@@ -57,7 +57,7 @@ static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo pmagbbfb_fix __devinitdata = {
+static struct fb_fix_screeninfo pmagbbfb_fix = {
        .id             = "PMAGB-BA",
        .smem_len       = (2048 * 1024),
        .type           = FB_TYPE_PACKED_PIXELS,
@@ -147,7 +147,7 @@ static void __init pmagbbfb_erase_cursor(struct fb_info *info)
 /*
  * Set up screen parameters.
  */
-static void __devinit pmagbbfb_screen_setup(struct fb_info *info)
+static void pmagbbfb_screen_setup(struct fb_info *info)
 {
        struct pmagbbfb_par *par = info->par;
 
@@ -179,9 +179,9 @@ static void __devinit pmagbbfb_screen_setup(struct fb_info *info)
 /*
  * Determine oscillator configuration.
  */
-static void __devinit pmagbbfb_osc_setup(struct fb_info *info)
+static void pmagbbfb_osc_setup(struct fb_info *info)
 {
-       static unsigned int pmagbbfb_freqs[] __devinitdata = {
+       static unsigned int pmagbbfb_freqs[] = {
                130808, 119843, 104000, 92980, 74370, 72800,
                69197, 66000, 65000, 50350, 36000, 32000, 25175
        };
@@ -246,7 +246,7 @@ static void __devinit pmagbbfb_osc_setup(struct fb_info *info)
 };
 
 
-static int __devinit pmagbbfb_probe(struct device *dev)
+static int pmagbbfb_probe(struct device *dev)
 {
        struct tc_dev *tdev = to_tc_dev(dev);
        resource_size_t start, len;
index 0b340d6ff8a4cab05eb4843f5d5ecff38700fbf9..920c27bf3947edeb05540bcce3ac11b8c2bddbf4 100644 (file)
@@ -259,7 +259,7 @@ static const struct fb_videomode ps3fb_modedb[] = {
 static int ps3fb_mode;
 module_param(ps3fb_mode, int, 0);
 
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
                          const struct fb_var_screeninfo *var)
@@ -965,7 +965,7 @@ static struct fb_fix_screeninfo ps3fb_fix __initdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
+static int ps3fb_probe(struct ps3_system_bus_device *dev)
 {
        struct fb_info *info;
        struct ps3fb_par *par;
index bcd44c32a2ed501474925b9c373af1cb9b50aee4..df07860563e63df4f24a82c2dea8ddc773b603d3 100644 (file)
@@ -112,11 +112,11 @@ enum { VO_PAL, VO_NTSC, VO_VGA };
 enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
 
 struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] __devinitdata = {
+static struct pvr2_params cables[] = {
        { CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
 };
 
-static struct pvr2_params outputs[] __devinitdata = {
+static struct pvr2_params outputs[] = {
        { VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
 };
 
@@ -145,7 +145,7 @@ static struct pvr2fb_par {
 
 static struct fb_info *fb_info;
 
-static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
+static struct fb_fix_screeninfo pvr2_fix = {
        .id =           "NEC PowerVR2",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_TRUECOLOR,
@@ -154,7 +154,7 @@ static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
        .accel =        FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo pvr2_var __devinitdata = {
+static struct fb_var_screeninfo pvr2_var = {
        .xres =         640,
        .yres =         480,
        .xres_virtual = 640,
@@ -226,7 +226,7 @@ static struct fb_ops pvr2fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_videomode pvr2_modedb[] __devinitdata = {
+static struct fb_videomode pvr2_modedb[] = {
     /*
      * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
      * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -256,7 +256,7 @@ static struct fb_videomode pvr2_modedb[] __devinitdata = {
 #define DEFMODE_VGA    2
 
 static int defmode = DEFMODE_NTSC;
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
 static inline void pvr2fb_set_pal_type(unsigned int type)
 {
@@ -763,7 +763,7 @@ out_unmap:
  * in for flexibility anyways. Who knows, maybe someone has tv-out on a
  * PCI-based version of these things ;-)
  */
-static int __devinit pvr2fb_common_init(void)
+static int pvr2fb_common_init(void)
 {
        struct pvr2fb_par *par = currentpar;
        unsigned long modememused, rev;
@@ -922,8 +922,8 @@ static void __exit pvr2fb_dc_exit(void)
 #endif /* CONFIG_SH_DREAMCAST */
 
 #ifdef CONFIG_PCI
-static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int pvr2fb_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        int ret;
 
@@ -953,7 +953,7 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev,
        return pvr2fb_common_init();
 }
 
-static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev)
+static void pvr2fb_pci_remove(struct pci_dev *pdev)
 {
        if (fb_info->screen_base) {
                iounmap(fb_info->screen_base);
@@ -967,7 +967,7 @@ static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev)
        pci_release_regions(pdev);
 }
 
-static struct pci_device_id pvr2fb_pci_tbl[] __devinitdata = {
+static struct pci_device_id pvr2fb_pci_tbl[] = {
        { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NEON250,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { 0, },
@@ -979,7 +979,7 @@ static struct pci_driver pvr2fb_pci_driver = {
        .name           = "pvr2fb",
        .id_table       = pvr2fb_pci_tbl,
        .probe          = pvr2fb_pci_probe,
-       .remove         = __devexit_p(pvr2fb_pci_remove),
+       .remove         = pvr2fb_pci_remove,
 };
 
 static int __init pvr2fb_pci_init(void)
@@ -993,8 +993,8 @@ static void __exit pvr2fb_pci_exit(void)
 }
 #endif /* CONFIG_PCI */
 
-static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s,
-                                   int val, int size)
+static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
+                         int size)
 {
        int i;
 
index f146089261f4df312a00464d1f5fc50a890dc939..aa9bd1f76d60641d4a242829dc5ed89b4e393976 100644 (file)
@@ -560,7 +560,7 @@ static struct fb_ops pxa168fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int __devinit pxa168fb_init_mode(struct fb_info *info,
+static int pxa168fb_init_mode(struct fb_info *info,
                              struct pxa168fb_mach_info *mi)
 {
        struct pxa168fb_info *fbi = info->par;
@@ -600,7 +600,7 @@ static int __devinit pxa168fb_init_mode(struct fb_info *info,
        return ret;
 }
 
-static int __devinit pxa168fb_probe(struct platform_device *pdev)
+static int pxa168fb_probe(struct platform_device *pdev)
 {
        struct pxa168fb_mach_info *mi;
        struct fb_info *info = 0;
@@ -783,7 +783,7 @@ failed_put_clk:
        return ret;
 }
 
-static int __devexit pxa168fb_remove(struct platform_device *pdev)
+static int pxa168fb_remove(struct platform_device *pdev)
 {
        struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
        struct fb_info *info;
@@ -826,7 +826,7 @@ static struct platform_driver pxa168fb_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pxa168fb_probe,
-       .remove         = __devexit_p(pxa168fb_remove),
+       .remove         = pxa168fb_remove,
 };
 
 module_platform_driver(pxa168fb_driver);
index 0b4ae0cebedaf7c0a6b9c8f3d262d7917ecf8911..6c984eacc7e350bf87a8a6078cb7f4fadc845d8c 100644 (file)
@@ -574,8 +574,7 @@ free_buffers(struct platform_device *dev,
        priv->free = NULL;
 }
 
-static int __devinit
-pxa3xx_gcu_probe(struct platform_device *dev)
+static int pxa3xx_gcu_probe(struct platform_device *dev)
 {
        int i, ret, irq;
        struct resource *r;
@@ -714,8 +713,7 @@ err_free_priv:
        return ret;
 }
 
-static int __devexit
-pxa3xx_gcu_remove(struct platform_device *dev)
+static int pxa3xx_gcu_remove(struct platform_device *dev)
 {
        struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
        struct resource *r = priv->resource_mem;
@@ -737,7 +735,7 @@ pxa3xx_gcu_remove(struct platform_device *dev)
 
 static struct platform_driver pxa3xx_gcu_driver = {
        .probe    = pxa3xx_gcu_probe,
-       .remove  = __devexit_p(pxa3xx_gcu_remove),
+       .remove  = pxa3xx_gcu_remove,
        .driver  = {
                .owner  = THIS_MODULE,
                .name   = DRV_NAME,
index 4fa2ad43fd97ae28f1cf98ebe1a4fea76904d220..580f80cc586fc7a0030cbe2f8ce57b8df4896727 100644 (file)
@@ -869,8 +869,8 @@ static struct fb_ops overlay_fb_ops = {
        .fb_set_par             = overlayfb_set_par,
 };
 
-static void __devinit init_pxafb_overlay(struct pxafb_info *fbi,
-                                        struct pxafb_layer *ofb, int id)
+static void init_pxafb_overlay(struct pxafb_info *fbi, struct pxafb_layer *ofb,
+                              int id)
 {
        sprintf(ofb->fb.fix.id, "overlay%d", id + 1);
 
@@ -903,8 +903,8 @@ static inline int pxafb_overlay_supported(void)
        return 0;
 }
 
-static int __devinit pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
-       struct pxafb_layer *ofb)
+static int pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
+                                         struct pxafb_layer *ofb)
 {
        /* We assume that user will use at most video_mem_size for overlay fb,
         * anyway, it's useless to use 16bpp main plane and 24bpp overlay
@@ -927,7 +927,7 @@ static int __devinit pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
        return 0;
 }
 
-static void __devinit pxafb_overlay_init(struct pxafb_info *fbi)
+static void pxafb_overlay_init(struct pxafb_info *fbi)
 {
        int i, ret;
 
@@ -959,7 +959,7 @@ static void __devinit pxafb_overlay_init(struct pxafb_info *fbi)
        pr_info("PXA Overlay driver loaded successfully!\n");
 }
 
-static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
+static void pxafb_overlay_exit(struct pxafb_info *fbi)
 {
        int i;
 
@@ -1706,7 +1706,7 @@ static const struct dev_pm_ops pxafb_pm_ops = {
 };
 #endif
 
-static int __devinit pxafb_init_video_memory(struct pxafb_info *fbi)
+static int pxafb_init_video_memory(struct pxafb_info *fbi)
 {
        int size = PAGE_ALIGN(fbi->video_mem_size);
 
@@ -1789,7 +1789,7 @@ decode_mode:
                fbi->video_mem_size = video_mem_size;
 }
 
-static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
+static struct pxafb_info *pxafb_init_fbinfo(struct device *dev)
 {
        struct pxafb_info *fbi;
        void *addr;
@@ -1853,7 +1853,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 }
 
 #ifdef CONFIG_FB_PXA_PARAMETERS
-static int __devinit parse_opt_mode(struct device *dev, const char *this_opt)
+static int parse_opt_mode(struct device *dev, const char *this_opt)
 {
        struct pxafb_mach_info *inf = dev->platform_data;
 
@@ -1912,7 +1912,7 @@ done:
        return 0;
 }
 
-static int __devinit parse_opt(struct device *dev, char *this_opt)
+static int parse_opt(struct device *dev, char *this_opt)
 {
        struct pxafb_mach_info *inf = dev->platform_data;
        struct pxafb_mode_info *mode = &inf->modes[0];
@@ -2012,7 +2012,7 @@ static int __devinit parse_opt(struct device *dev, char *this_opt)
        return 0;
 }
 
-static int __devinit pxafb_parse_options(struct device *dev, char *options)
+static int pxafb_parse_options(struct device *dev, char *options)
 {
        char *this_opt;
        int ret;
@@ -2031,7 +2031,7 @@ static int __devinit pxafb_parse_options(struct device *dev, char *options)
        return 0;
 }
 
-static char g_options[256] __devinitdata = "";
+static char g_options[256] = "";
 
 #ifndef MODULE
 static int __init pxafb_setup_options(void)
@@ -2061,8 +2061,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 #ifdef DEBUG_VAR
 /* Check for various illegal bit-combinations. Currently only
  * a warning is given. */
-static void __devinit pxafb_check_options(struct device *dev,
-                                         struct pxafb_mach_info *inf)
+static void pxafb_check_options(struct device *dev, struct pxafb_mach_info *inf)
 {
        if (inf->lcd_conn)
                return;
@@ -2094,7 +2093,7 @@ static void __devinit pxafb_check_options(struct device *dev,
 #define pxafb_check_options(...)       do {} while (0)
 #endif
 
-static int __devinit pxafb_probe(struct platform_device *dev)
+static int pxafb_probe(struct platform_device *dev)
 {
        struct pxafb_info *fbi;
        struct pxafb_mach_info *inf;
@@ -2263,7 +2262,7 @@ failed:
        return ret;
 }
 
-static int __devexit pxafb_remove(struct platform_device *dev)
+static int pxafb_remove(struct platform_device *dev)
 {
        struct pxafb_info *fbi = platform_get_drvdata(dev);
        struct resource *r;
@@ -2304,7 +2303,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 
 static struct platform_driver pxafb_driver = {
        .probe          = pxafb_probe,
-       .remove         = __devexit_p(pxafb_remove),
+       .remove         = pxafb_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "pxa2xx-fb",
index a104e8cd2f54872cc4cb48f6d9f52acf26f08402..d44c7351de0f6dc0e2350cd1cd9ab67fa1457f3e 100644 (file)
@@ -27,7 +27,7 @@
 
 #define Q40_PHYS_SCREEN_ADDR 0xFE800000
 
-static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
+static struct fb_fix_screeninfo q40fb_fix = {
        .id             = "Q40",
        .smem_len       = 1024*1024,
        .type           = FB_TYPE_PACKED_PIXELS,
@@ -36,7 +36,7 @@ static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo q40fb_var __devinitdata = {
+static struct fb_var_screeninfo q40fb_var = {
        .xres           = 1024,
        .yres           = 512,
        .xres_virtual   = 1024,
@@ -83,7 +83,7 @@ static struct fb_ops q40fb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int __devinit q40fb_probe(struct platform_device *dev)
+static int q40fb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
 
index 90df1a60bd16a5e338fddd3cc81772e2b97bd8b6..9536715b5a1b90f1828451300016e45b90ecb1a9 100644 (file)
@@ -205,28 +205,28 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
  * ------------------------------------------------------------------------- */
 
 /* command line data, set in rivafb_setup() */
-static int flatpanel __devinitdata = -1; /* Autodetect later */
-static int forceCRTC __devinitdata = -1;
-static bool noaccel  __devinitdata = 0;
+static int flatpanel = -1; /* Autodetect later */
+static int forceCRTC = -1;
+static bool noaccel  = 0;
 #ifdef CONFIG_MTRR
-static bool nomtrr __devinitdata = 0;
+static bool nomtrr = 0;
 #endif
 #ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight __devinitdata = 1;
+static int backlight = 1;
 #else
-static int backlight __devinitdata = 0;
+static int backlight = 0;
 #endif
 
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 static bool strictmode       = 0;
 
-static struct fb_fix_screeninfo __devinitdata rivafb_fix = {
+static struct fb_fix_screeninfo rivafb_fix = {
        .type           = FB_TYPE_PACKED_PIXELS,
        .xpanstep       = 1,
        .ypanstep       = 1,
 };
 
-static struct fb_var_screeninfo __devinitdata rivafb_default_var = {
+static struct fb_var_screeninfo rivafb_default_var = {
        .xres           = 640,
        .yres           = 480,
        .xres_virtual   = 640,
@@ -1709,7 +1709,7 @@ static struct fb_ops riva_fb_ops = {
        .fb_sync        = rivafb_sync,
 };
 
-static int __devinit riva_set_fbinfo(struct fb_info *info)
+static int riva_set_fbinfo(struct fb_info *info)
 {
        unsigned int cmap_len;
        struct riva_par *par = info->par;
@@ -1747,7 +1747,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
 }
 
 #ifdef CONFIG_PPC_OF
-static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
+static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 {
        struct riva_par *par = info->par;
        struct device_node *dp;
@@ -1780,7 +1780,7 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 #endif /* CONFIG_PPC_OF */
 
 #if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
-static int __devinit riva_get_EDID_i2c(struct fb_info *info)
+static int riva_get_EDID_i2c(struct fb_info *info)
 {
        struct riva_par *par = info->par;
        struct fb_var_screeninfo var;
@@ -1803,8 +1803,8 @@ static int __devinit riva_get_EDID_i2c(struct fb_info *info)
 }
 #endif /* CONFIG_FB_RIVA_I2C */
 
-static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
-                                             struct fb_info *info)
+static void riva_update_default_var(struct fb_var_screeninfo *var,
+                                   struct fb_info *info)
 {
        struct fb_monspecs *specs = &info->monspecs;
        struct fb_videomode modedb;
@@ -1836,7 +1836,7 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
 }
 
 
-static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
+static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
 {
        NVTRACE_ENTER();
 #ifdef CONFIG_PPC_OF
@@ -1850,7 +1850,7 @@ static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
 }
 
 
-static void __devinit riva_get_edidinfo(struct fb_info *info)
+static void riva_get_edidinfo(struct fb_info *info)
 {
        struct fb_var_screeninfo *var = &rivafb_default_var;
        struct riva_par *par = info->par;
@@ -1871,7 +1871,7 @@ static void __devinit riva_get_edidinfo(struct fb_info *info)
  *
  * ------------------------------------------------------------------------- */
 
-static u32 __devinit riva_get_arch(struct pci_dev *pd)
+static u32 riva_get_arch(struct pci_dev *pd)
 {
        u32 arch = 0;
 
@@ -1909,8 +1909,7 @@ static u32 __devinit riva_get_arch(struct pci_dev *pd)
        return arch;
 }
 
-static int __devinit rivafb_probe(struct pci_dev *pd,
-                               const struct pci_device_id *ent)
+static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
 {
        struct riva_par *default_par;
        struct fb_info *info;
@@ -2105,7 +2104,7 @@ err_ret:
        return ret;
 }
 
-static void __devexit rivafb_remove(struct pci_dev *pd)
+static void rivafb_remove(struct pci_dev *pd)
 {
        struct fb_info *info = pci_get_drvdata(pd);
        struct riva_par *par = info->par;
@@ -2145,7 +2144,7 @@ static void __devexit rivafb_remove(struct pci_dev *pd)
  * ------------------------------------------------------------------------- */
 
 #ifndef MODULE
-static int __devinit rivafb_setup(char *options)
+static int rivafb_setup(char *options)
 {
        char *this_opt;
 
@@ -2186,7 +2185,7 @@ static struct pci_driver rivafb_driver = {
        .name           = "rivafb",
        .id_table       = rivafb_pci_tbl,
        .probe          = rivafb_probe,
-       .remove         = __devexit_p(rivafb_remove),
+       .remove         = rivafb_remove,
 };
 
 
@@ -2197,7 +2196,7 @@ static struct pci_driver rivafb_driver = {
  *
  * ------------------------------------------------------------------------- */
 
-static int __devinit rivafb_init(void)
+static int rivafb_init(void)
 {
 #ifndef MODULE
        char *option = NULL;
index 167400e2a18204f359edc38b6cfe2499e7992aa5..6a183375ced1a01d637d560b852a2aa6be309fba 100644 (file)
@@ -86,9 +86,8 @@ static int riva_gpio_getsda(void* data)
        return val;
 }
 
-static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan,
-                                       const char *name,
-                                       unsigned int i2c_class)
+static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name,
+                             unsigned int i2c_class)
 {
        int rc;
 
@@ -124,7 +123,7 @@ static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan,
        return rc;
 }
 
-void __devinit riva_create_i2c_busses(struct riva_par *par)
+void riva_create_i2c_busses(struct riva_par *par)
 {
        par->chan[0].par        = par;
        par->chan[1].par        = par;
@@ -150,7 +149,7 @@ void riva_delete_i2c_busses(struct riva_par *par)
        }
 }
 
-int __devinit riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
 {
        u8 *edid = NULL;
 
index 28b1c6c3d8ac98054ca2aad04021d4107cd01662..76d9053d88c136bb65dd36562cc697361db7a35b 100644 (file)
@@ -84,7 +84,7 @@ static const char *s1d13xxxfb_prod_names[] = {
 /*
  * here we define the default struct fb_fix_screeninfo
  */
-static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
+static struct fb_fix_screeninfo s1d13xxxfb_fix = {
        .id             = S1D_FBID,
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_PSEUDOCOLOR,
@@ -622,7 +622,7 @@ static struct fb_ops s1d13xxxfb_fbops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
+static int s1d13xxxfb_width_tab[2][4] = {
        {4, 8, 16, -1},
        {9, 12, 18, -1},
 };
@@ -642,8 +642,7 @@ static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
  *     Note: some of the hardcoded values here might need some love to
  *     work on various chips, and might need to no longer be hardcoded.
  */
-static void __devinit
-s1d13xxxfb_fetch_hw_state(struct fb_info *info)
+static void s1d13xxxfb_fetch_hw_state(struct fb_info *info)
 {
        struct fb_var_screeninfo *var = &info->var;
        struct fb_fix_screeninfo *fix = &info->fix;
@@ -764,8 +763,7 @@ s1d13xxxfb_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit
-s1d13xxxfb_probe(struct platform_device *pdev)
+static int s1d13xxxfb_probe(struct platform_device *pdev)
 {
        struct s1d13xxxfb_par *default_par;
        struct fb_info *info;
index 1a00ad241edd3dcd10ac83e22d03a50c079920c6..9b57a235c9bcb921c7eadd17e6ed08abf01b41b0 100644 (file)
@@ -1081,8 +1081,7 @@ static void s3c_fb_missing_pixclock(struct fb_videomode *mode)
  *
  * Allocate memory for the given framebuffer.
  */
-static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
-                                        struct s3c_fb_win *win)
+static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
 {
        struct s3c_fb_pd_win *windata = win->windata;
        unsigned int real_size, virt_size, size;
@@ -1172,9 +1171,9 @@ static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
  * Allocate and do the basic initialisation for one of the hardware's graphics
  * windows.
  */
-static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
-                                     struct s3c_fb_win_variant *variant,
-                                     struct s3c_fb_win **res)
+static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
+                           struct s3c_fb_win_variant *variant,
+                           struct s3c_fb_win **res)
 {
        struct fb_var_screeninfo *var;
        struct fb_videomode initmode;
@@ -1360,7 +1359,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
        }
 }
 
-static int __devinit s3c_fb_probe(struct platform_device *pdev)
+static int s3c_fb_probe(struct platform_device *pdev)
 {
        const struct platform_device_id *platid;
        struct s3c_fb_driverdata *fbdrv;
@@ -1521,7 +1520,7 @@ err_bus_clk:
  * Shutdown and then release all the resources that the driver allocated
  * on initialisation.
  */
-static int __devexit s3c_fb_remove(struct platform_device *pdev)
+static int s3c_fb_remove(struct platform_device *pdev)
 {
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        int win;
@@ -2035,7 +2034,7 @@ static const struct dev_pm_ops s3cfb_pm_ops = {
 
 static struct platform_driver s3c_fb_driver = {
        .probe          = s3c_fb_probe,
-       .remove         = __devexit_p(s3c_fb_remove),
+       .remove         = s3c_fb_remove,
        .id_table       = s3c_fb_driver_ids,
        .driver         = {
                .name   = "s3c-fb",
index 1083bb9469eec5911727856cba5623d157c273fe..76a0e7fbd69297d96a755a111d53597a439fe24f 100644 (file)
@@ -637,7 +637,7 @@ static struct fb_ops s3c2410fb_ops = {
  *     cache.  Once this area is remapped, all virtual memory
  *     access to the video memory should occur at the new region.
  */
-static int __devinit s3c2410fb_map_video_memory(struct fb_info *info)
+static int s3c2410fb_map_video_memory(struct fb_info *info)
 {
        struct s3c2410fb_info *fbi = info->par;
        dma_addr_t map_dma;
@@ -819,8 +819,8 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
 
 static const char driver_name[] = "s3c2410fb";
 
-static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
-                                 enum s3c_drv_type drv_type)
+static int s3c24xxfb_probe(struct platform_device *pdev,
+                          enum s3c_drv_type drv_type)
 {
        struct s3c2410fb_info *info;
        struct s3c2410fb_display *display;
@@ -1010,12 +1010,12 @@ dealloc_fb:
        return ret;
 }
 
-static int __devinit s3c2410fb_probe(struct platform_device *pdev)
+static int s3c2410fb_probe(struct platform_device *pdev)
 {
        return s3c24xxfb_probe(pdev, DRV_S3C2410);
 }
 
-static int __devinit s3c2412fb_probe(struct platform_device *pdev)
+static int s3c2412fb_probe(struct platform_device *pdev)
 {
        return s3c24xxfb_probe(pdev, DRV_S3C2412);
 }
@@ -1024,7 +1024,7 @@ static int __devinit s3c2412fb_probe(struct platform_device *pdev)
 /*
  *  Cleanup
  */
-static int __devexit s3c2410fb_remove(struct platform_device *pdev)
+static int s3c2410fb_remove(struct platform_device *pdev)
 {
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
        struct s3c2410fb_info *info = fbinfo->par;
@@ -1101,7 +1101,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
 
 static struct platform_driver s3c2410fb_driver = {
        .probe          = s3c2410fb_probe,
-       .remove         = __devexit_p(s3c2410fb_remove),
+       .remove         = s3c2410fb_remove,
        .suspend        = s3c2410fb_suspend,
        .resume         = s3c2410fb_resume,
        .driver         = {
@@ -1112,7 +1112,7 @@ static struct platform_driver s3c2410fb_driver = {
 
 static struct platform_driver s3c2412fb_driver = {
        .probe          = s3c2412fb_probe,
-       .remove         = __devexit_p(s3c2410fb_remove),
+       .remove         = s3c2410fb_remove,
        .suspend        = s3c2410fb_suspend,
        .resume         = s3c2410fb_resume,
        .driver         = {
index 1d007366b9173d1a9af73b5f0735c0730464ae63..47ca86c5c6c0b3d1d609a001210e5eb132616076 100644 (file)
@@ -153,10 +153,10 @@ static const struct svga_timing_regs s3_timing_regs     = {
 /* Module parameters */
 
 
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 #ifdef CONFIG_MTRR
-static int mtrr __devinitdata = 1;
+static int mtrr = 1;
 #endif
 
 static int fasttext = 1;
@@ -255,7 +255,7 @@ static int s3fb_ddc_getsda(void *data)
        return !!(s3fb_ddc_read(par) & DDC_SDA_IN);
 }
 
-static int __devinit s3fb_setup_ddc_bus(struct fb_info *info)
+static int s3fb_setup_ddc_bus(struct fb_info *info)
 {
        struct s3fb_info *par = info->par;
 
@@ -1066,7 +1066,7 @@ static struct fb_ops s3fb_ops = {
 
 /* ------------------------------------------------------------------------- */
 
-static int __devinit s3_identification(struct s3fb_info *par)
+static int s3_identification(struct s3fb_info *par)
 {
        int chip = par->chip;
 
@@ -1122,7 +1122,7 @@ static int __devinit s3_identification(struct s3fb_info *par)
 
 /* PCI probe */
 
-static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct pci_bus_region bus_reg;
        struct resource vga_res;
@@ -1403,7 +1403,7 @@ err_enable_device:
 
 /* PCI remove */
 
-static void __devexit s3_pci_remove(struct pci_dev *dev)
+static void s3_pci_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct s3fb_info __maybe_unused *par = info->par;
@@ -1509,7 +1509,7 @@ static int s3_pci_resume(struct pci_dev* dev)
 
 /* List of boards that we are trying to support */
 
-static struct pci_device_id s3_devices[] __devinitdata = {
+static struct pci_device_id s3_devices[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},
@@ -1537,7 +1537,7 @@ static struct pci_driver s3fb_pci_driver = {
        .name           = "s3fb",
        .id_table       = s3_devices,
        .probe          = s3_pci_probe,
-       .remove         = __devexit_p(s3_pci_remove),
+       .remove         = s3_pci_remove,
        .suspend        = s3_pci_suspend,
        .resume         = s3_pci_resume,
 };
index b6325848ad614f6beb1d1c49cc72b09b2652e0df..cfbde5e85cbf9a77495e09f1be14fc4c90e1101f 100644 (file)
@@ -1090,7 +1090,7 @@ static int sa1100fb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __devinit sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
+static int sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
 {
        /*
         * We reserve one page for the palette, plus the size
@@ -1116,7 +1116,7 @@ static int __devinit sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
 }
 
 /* Fake monspecs to fill in fbinfo structure */
-static struct fb_monspecs monspecs __devinitdata = {
+static struct fb_monspecs monspecs = {
        .hfmin  = 30000,
        .hfmax  = 70000,
        .vfmin  = 50,
@@ -1124,7 +1124,7 @@ static struct fb_monspecs monspecs __devinitdata = {
 };
 
 
-static struct sa1100fb_info * __devinit sa1100fb_init_fbinfo(struct device *dev)
+static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
 {
        struct sa1100fb_mach_info *inf = dev->platform_data;
        struct sa1100fb_info *fbi;
@@ -1205,7 +1205,7 @@ static struct sa1100fb_info * __devinit sa1100fb_init_fbinfo(struct device *dev)
        return fbi;
 }
 
-static int __devinit sa1100fb_probe(struct platform_device *pdev)
+static int sa1100fb_probe(struct platform_device *pdev)
 {
        struct sa1100fb_info *fbi;
        struct resource *res;
index f4f53b082d0546b9e7c5ff21df2be606991a4152..741b2395d01e483eb347e398549fbcc3881368d7 100644 (file)
@@ -69,7 +69,7 @@
 /* --------------------------------------------------------------------- */
 
 
-static char *mode_option __devinitdata = NULL;
+static char *mode_option = NULL;
 
 #ifdef MODULE
 
@@ -1664,7 +1664,7 @@ static struct fb_ops savagefb_ops = {
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo __devinitdata savagefb_var800x600x8 = {
+static struct fb_var_screeninfo savagefb_var800x600x8 = {
        .accel_flags =  FB_ACCELF_TEXT,
        .xres =         800,
        .yres =         600,
@@ -1715,7 +1715,7 @@ static void savage_disable_mmio(struct savagefb_par *par)
 }
 
 
-static int __devinit savage_map_mmio(struct fb_info *info)
+static int savage_map_mmio(struct fb_info *info)
 {
        struct savagefb_par *par = info->par;
        DBG("savage_map_mmio");
@@ -1761,8 +1761,7 @@ static void savage_unmap_mmio(struct fb_info *info)
        }
 }
 
-static int __devinit savage_map_video(struct fb_info *info,
-                                     int video_len)
+static int savage_map_video(struct fb_info *info, int video_len)
 {
        struct savagefb_par *par = info->par;
        int resource;
@@ -2052,9 +2051,8 @@ static int savage_init_hw(struct savagefb_par *par)
        return videoRambytes;
 }
 
-static int __devinit savage_init_fb_info(struct fb_info *info,
-                                        struct pci_dev *dev,
-                                        const struct pci_device_id *id)
+static int savage_init_fb_info(struct fb_info *info, struct pci_dev *dev,
+                              const struct pci_device_id *id)
 {
        struct savagefb_par *par = info->par;
        int err = 0;
@@ -2178,8 +2176,7 @@ static int __devinit savage_init_fb_info(struct fb_info *info,
 
 /* --------------------------------------------------------------------- */
 
-static int __devinit savagefb_probe(struct pci_dev* dev,
-                                   const struct pci_device_id* id)
+static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct fb_info *info;
        struct savagefb_par *par;
@@ -2340,7 +2337,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
        return err;
 }
 
-static void __devexit savagefb_remove(struct pci_dev *dev)
+static void savagefb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -2449,7 +2446,7 @@ static int savagefb_resume(struct pci_dev* dev)
 }
 
 
-static struct pci_device_id savagefb_devices[] __devinitdata = {
+static struct pci_device_id savagefb_devices[] = {
        {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
 
@@ -2530,7 +2527,7 @@ static struct pci_driver savagefb_driver = {
        .probe =    savagefb_probe,
        .suspend =  savagefb_suspend,
        .resume =   savagefb_resume,
-       .remove =   __devexit_p(savagefb_remove)
+       .remove =   savagefb_remove,
 };
 
 /* **************************** exit-time only **************************** */
index 53455f2955107a1dd2072c90503d8047ff3dc49e..2331fadc272bee53d265f1338c9bcbe648e3e685 100644 (file)
@@ -47,7 +47,7 @@ static int ywrap = 0;
 
 static int flatpanel_id = -1;
 
-static struct fb_fix_screeninfo sgivwfb_fix __devinitdata = {
+static struct fb_fix_screeninfo sgivwfb_fix = {
        .id             = "SGI Vis WS FB",
        .type           = FB_TYPE_PACKED_PIXELS,
         .visual                = FB_VISUAL_PSEUDOCOLOR,
@@ -57,7 +57,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __devinitdata = {
        .line_length    = 640,
 };
 
-static struct fb_var_screeninfo sgivwfb_var __devinitdata = {
+static struct fb_var_screeninfo sgivwfb_var = {
        /* 640x480, 8 bpp */
        .xres           = 640,
        .yres           = 480,
@@ -79,7 +79,7 @@ static struct fb_var_screeninfo sgivwfb_var __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED
 };
 
-static struct fb_var_screeninfo sgivwfb_var1600sw __devinitdata = {
+static struct fb_var_screeninfo sgivwfb_var1600sw = {
        /* 1600x1024, 8 bpp */
        .xres           = 1600,
        .yres           = 1024,
@@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options)
 /*
  *  Initialisation
  */
-static int __devinit sgivwfb_probe(struct platform_device *dev)
+static int sgivwfb_probe(struct platform_device *dev)
 {
        struct sgivw_par *par;
        struct fb_info *info;
@@ -825,7 +825,7 @@ fail_ioremap_regs:
        return -ENXIO;
 }
 
-static int __devexit sgivwfb_remove(struct platform_device *dev)
+static int sgivwfb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -845,7 +845,7 @@ static int __devexit sgivwfb_remove(struct platform_device *dev)
 
 static struct platform_driver sgivwfb_driver = {
        .probe  = sgivwfb_probe,
-       .remove = __devexit_p(sgivwfb_remove),
+       .remove = sgivwfb_remove,
        .driver = {
                .name   = "sgivwfb",
        },
index 83b16e237a0e2f4fcf4d2438ea2f3439851129c8..5fbb0c7ab0c8e54071c3d463511882a146fb7034 100644 (file)
@@ -431,7 +431,7 @@ static int sh7760fb_alloc_mem(struct fb_info *info)
        return 0;
 }
 
-static int __devinit sh7760fb_probe(struct platform_device *pdev)
+static int sh7760fb_probe(struct platform_device *pdev)
 {
        struct fb_info *info;
        struct resource *res;
@@ -557,7 +557,7 @@ out_fb:
        return ret;
 }
 
-static int __devexit sh7760fb_remove(struct platform_device *dev)
+static int sh7760fb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
        struct sh7760fb_par *par = info->par;
@@ -582,7 +582,7 @@ static struct platform_driver sh7760_lcdc_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = sh7760fb_probe,
-       .remove = __devexit_p(sh7760fb_remove),
+       .remove = sh7760fb_remove,
 };
 
 module_platform_driver(sh7760_lcdc_driver);
index f4962292792c6fd305af02d70709c5b43e203027..701b461cf8a953b602c676bd50d1e164267deb98 100644 (file)
@@ -533,7 +533,7 @@ efindslot:
        return ret;
 }
 
-static int __devexit sh_mipi_remove(struct platform_device *pdev)
+static int sh_mipi_remove(struct platform_device *pdev)
 {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -574,7 +574,7 @@ static int __devexit sh_mipi_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver sh_mipi_driver = {
-       .remove         = __devexit_p(sh_mipi_remove),
+       .remove         = sh_mipi_remove,
        .shutdown       = sh_mipi_shutdown,
        .driver = {
                .name   = "sh-mipi-dsi",
index e78fe4bc15249c21612020b858273b0c8884f3da..63203acef812211cb17788454116fcbe77debdd7 100644 (file)
@@ -1649,7 +1649,7 @@ sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
        unregister_framebuffer(ovl->info);
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
 {
        struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
@@ -1688,7 +1688,7 @@ sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
        framebuffer_release(info);
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
 {
        struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
@@ -2137,7 +2137,7 @@ sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
                unregister_framebuffer(ch->info);
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
 {
        struct fb_info *info = ch->info;
@@ -2185,7 +2185,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
        framebuffer_release(info);
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
                               const struct fb_videomode *modes,
                               unsigned int num_modes)
@@ -2417,7 +2417,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
  * Probe/remove and driver init/exit
  */
 
-static const struct fb_videomode default_720p __devinitconst = {
+static const struct fb_videomode default_720p = {
        .name = "HDMI 720p",
        .xres = 1280,
        .yres = 720,
@@ -2496,7 +2496,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
 {
        int interface_type = ch->cfg->interface_type;
 
@@ -2536,7 +2536,7 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
        return 0;
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
 {
        const struct sh_mobile_lcdc_format_info *format;
@@ -2591,7 +2591,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
        return 0;
 }
 
-static int __devinit
+static int
 sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
 {
        const struct sh_mobile_lcdc_format_info *format;
@@ -2695,7 +2695,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
        return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
 }
 
-static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+static int sh_mobile_lcdc_probe(struct platform_device *pdev)
 {
        struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
        struct sh_mobile_lcdc_priv *priv;
index 7a0ba8bb3fbebed167711a7dd6a29d6a9e9e92a0..e0f098562a74b87eee790de505a8483a8a2024b7 100644 (file)
@@ -620,7 +620,7 @@ static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
  * Probe/remove and driver init/exit
  */
 
-static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
+static int sh_mobile_meram_probe(struct platform_device *pdev)
 {
        struct sh_mobile_meram_priv *priv;
        struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
index a7a48db64ce20d0cdad34635da4848bc0410dec1..977e27927a211ab0fffcd37087f90e0c0fa86e9f 100644 (file)
@@ -106,8 +106,7 @@ sisfb_setdefaultparms(void)
 
 /* ------------- Parameter parsing -------------- */
 
-static void __devinit
-sisfb_search_vesamode(unsigned int vesamode, bool quiet)
+static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
 {
        int i = 0, j = 0;
 
@@ -146,8 +145,7 @@ sisfb_search_vesamode(unsigned int vesamode, bool quiet)
                printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
 }
 
-static void __devinit
-sisfb_search_mode(char *name, bool quiet)
+static void sisfb_search_mode(char *name, bool quiet)
 {
        unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
        int i = 0;
@@ -225,8 +223,7 @@ sisfb_search_mode(char *name, bool quiet)
 }
 
 #ifndef MODULE
-static void __devinit
-sisfb_get_vga_mode_from_kernel(void)
+static void sisfb_get_vga_mode_from_kernel(void)
 {
 #ifdef CONFIG_X86
        char mymode[32];
@@ -345,8 +342,7 @@ sisfb_search_specialtiming(const char *name)
 
 /* ----------- Various detection routines ----------- */
 
-static void __devinit
-sisfb_detect_custom_timing(struct sis_video_info *ivideo)
+static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
 {
        unsigned char *biosver = NULL;
        unsigned char *biosdate = NULL;
@@ -403,8 +399,7 @@ sisfb_detect_custom_timing(struct sis_video_info *ivideo)
        } while(mycustomttable[i].chipID);
 }
 
-static bool __devinit
-sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
+static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
        int i, j, xres, yres, refresh, index;
        u32 emodes;
@@ -505,8 +500,8 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
        return monitor->datavalid;
 }
 
-static void __devinit
-sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
+static void sisfb_handle_ddc(struct sis_video_info *ivideo,
+                            struct sisfb_monitor *monitor, int crtno)
 {
        unsigned short temp, i, realcrtno = crtno;
        unsigned char  buffer[256];
@@ -1898,8 +1893,7 @@ static struct fb_ops sisfb_ops = {
 
 /* ---------------- Chip generation dependent routines ---------------- */
 
-static struct pci_dev * __devinit
-sisfb_get_northbridge(int basechipid)
+static struct pci_dev *sisfb_get_northbridge(int basechipid)
 {
        struct pci_dev *pdev = NULL;
        int nbridgenum, nbridgeidx, i;
@@ -1938,8 +1932,7 @@ sisfb_get_northbridge(int basechipid)
        return pdev;
 }
 
-static int __devinit
-sisfb_get_dram_size(struct sis_video_info *ivideo)
+static int sisfb_get_dram_size(struct sis_video_info *ivideo)
 {
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
        u8 reg;
@@ -2038,8 +2031,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
 
 /* -------------- video bridge device detection --------------- */
 
-static void __devinit
-sisfb_detect_VB_connect(struct sis_video_info *ivideo)
+static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 {
        u8 cr32, temp;
 
@@ -2164,8 +2156,7 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 
 /* ------------------ Sensing routines ------------------ */
 
-static bool __devinit
-sisfb_test_DDC1(struct sis_video_info *ivideo)
+static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
     int count = 48;
@@ -2177,8 +2168,7 @@ sisfb_test_DDC1(struct sis_video_info *ivideo)
     return (count != -1);
 }
 
-static void __devinit
-sisfb_sense_crt1(struct sis_video_info *ivideo)
+static void sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
     bool mustwait = false;
     u8  sr1F, cr17;
@@ -2259,8 +2249,7 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
 }
 
 /* Determine and detect attached devices on SiS30x */
-static void __devinit
-SiS_SenseLCD(struct sis_video_info *ivideo)
+static void SiS_SenseLCD(struct sis_video_info *ivideo)
 {
        unsigned char buffer[256];
        unsigned short temp, realcrtno, i;
@@ -2347,8 +2336,7 @@ SiS_SenseLCD(struct sis_video_info *ivideo)
        ivideo->SiS_Pr.PanelSelfDetected = true;
 }
 
-static int __devinit
-SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
+static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
     int temp, mytest, result, i, j;
 
@@ -2377,8 +2365,7 @@ SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
     return result;
 }
 
-static void __devinit
-SiS_Sense30x(struct sis_video_info *ivideo)
+static void SiS_Sense30x(struct sis_video_info *ivideo)
 {
     u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
     u16 svhs=0, svhs_c=0;
@@ -2518,8 +2505,7 @@ SiS_Sense30x(struct sis_video_info *ivideo)
 }
 
 /* Determine and detect attached TV's on Chrontel */
-static void __devinit
-SiS_SenseCh(struct sis_video_info *ivideo)
+static void SiS_SenseCh(struct sis_video_info *ivideo)
 {
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
     u8 temp1, temp2;
@@ -2643,8 +2629,7 @@ SiS_SenseCh(struct sis_video_info *ivideo)
     }
 }
 
-static void __devinit
-sisfb_get_VB_type(struct sis_video_info *ivideo)
+static void sisfb_get_VB_type(struct sis_video_info *ivideo)
 {
        char stdstr[]    = "sisfb: Detected";
        char bridgestr[] = "video bridge";
@@ -2906,8 +2891,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
        ivideo->engineok = 1;
 }
 
-static void __devinit
-sisfb_detect_lcd_type(struct sis_video_info *ivideo)
+static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
 {
        u8 reg;
        int i;
@@ -2962,8 +2946,7 @@ sisfb_detect_lcd_type(struct sis_video_info *ivideo)
                        ivideo->lcdxres, ivideo->lcdyres);
 }
 
-static void __devinit
-sisfb_save_pdc_emi(struct sis_video_info *ivideo)
+static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
 {
 #ifdef CONFIG_FB_SIS_300
        /* Save the current PanelDelayCompensation if the LCD is currently used */
@@ -3081,8 +3064,7 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
 
 /* -------------------- Memory manager routines ---------------------- */
 
-static u32 __devinit
-sisfb_getheapstart(struct sis_video_info *ivideo)
+static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
 {
        u32 ret = ivideo->sisfb_parm_mem * 1024;
        u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
@@ -3128,8 +3110,7 @@ sisfb_getheapstart(struct sis_video_info *ivideo)
        return ret;
 }
 
-static u32 __devinit
-sisfb_getheapsize(struct sis_video_info *ivideo)
+static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
 {
        u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
        u32 ret = 0;
@@ -3154,8 +3135,7 @@ sisfb_getheapsize(struct sis_video_info *ivideo)
        return ret;
 }
 
-static int __devinit
-sisfb_heap_init(struct sis_video_info *ivideo)
+static int sisfb_heap_init(struct sis_video_info *ivideo)
 {
        struct SIS_OH *poh;
 
@@ -4061,8 +4041,8 @@ static int __init sisfb_setup(char *options)
 }
 #endif
 
-static int __devinit
-sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
+static int sisfb_check_rom(void __iomem *rom_base,
+                          struct sis_video_info *ivideo)
 {
        void __iomem *rom;
        int romptr;
@@ -4089,8 +4069,7 @@ sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
        return 1;
 }
 
-static unsigned char * __devinit
-sisfb_find_rom(struct pci_dev *pdev)
+static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
 {
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
        void __iomem *rom_base;
@@ -4149,9 +4128,8 @@ sisfb_find_rom(struct pci_dev *pdev)
        return myrombase;
 }
 
-static void __devinit
-sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
-                       unsigned int min)
+static void sisfb_post_map_vram(struct sis_video_info *ivideo,
+                               unsigned int *mapsize, unsigned int min)
 {
        if (*mapsize < (min << 20))
                return;
@@ -4176,8 +4154,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
 }
 
 #ifdef CONFIG_FB_SIS_300
-static int __devinit
-sisfb_post_300_buswidth(struct sis_video_info *ivideo)
+static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
 {
        void __iomem *FBAddress = ivideo->video_vbase;
        unsigned short temp;
@@ -4222,7 +4199,7 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
        return 1;                       /* 32bit */
 }
 
-static const unsigned short __devinitconst SiS_DRAMType[17][5] = {
+static const unsigned short SiS_DRAMType[17][5] = {
        {0x0C,0x0A,0x02,0x40,0x39},
        {0x0D,0x0A,0x01,0x40,0x48},
        {0x0C,0x09,0x02,0x20,0x35},
@@ -4242,10 +4219,9 @@ static const unsigned short __devinitconst SiS_DRAMType[17][5] = {
        {0x09,0x08,0x01,0x01,0x00}
 };
 
-static int __devinit
-sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
-                       int PseudoRankCapacity, int PseudoAdrPinCount,
-                       unsigned int mapsize)
+static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
+                                int buswidth, int PseudoRankCapacity,
+                                int PseudoAdrPinCount, unsigned int mapsize)
 {
        void __iomem *FBAddr = ivideo->video_vbase;
        unsigned short sr14;
@@ -4309,8 +4285,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
        return 0;
 }
 
-static void __devinit
-sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
+static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
 {
        struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
        int     i, j, buswidth;
@@ -4335,8 +4310,7 @@ sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
        }
 }
 
-static void __devinit
-sisfb_post_sis300(struct pci_dev *pdev)
+static void sisfb_post_sis300(struct pci_dev *pdev)
 {
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
        unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
@@ -4547,8 +4521,7 @@ sisfb_post_sis300(struct pci_dev *pdev)
 
 #ifdef CONFIG_FB_SIS_315
 #if 0
-static void __devinit
-sisfb_post_sis315330(struct pci_dev *pdev)
+static void sisfb_post_sis315330(struct pci_dev *pdev)
 {
        /* TODO */
 }
@@ -4559,8 +4532,7 @@ static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
        return ivideo->chip_real_id == XGI_21;
 }
 
-static void __devinit
-sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
+static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
 {
        unsigned int i;
        u8 reg;
@@ -4571,9 +4543,9 @@ sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
        }
 }
 
-static int __devinit
-sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
-                               unsigned short pcivendor)
+static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
+                                 struct pci_dev *mypdev,
+                                 unsigned short pcivendor)
 {
        struct pci_dev *pdev = NULL;
        unsigned short temp;
@@ -4591,9 +4563,8 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
        return ret;
 }
 
-static int __devinit
-sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
-                       unsigned int enda, unsigned int mapsize)
+static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
+                                unsigned int enda, unsigned int mapsize)
 {
        unsigned int pos;
        int i;
@@ -4623,8 +4594,7 @@ sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
        return 1;
 }
 
-static int __devinit
-sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
+static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
 {
        unsigned int buswidth, ranksize, channelab, mapsize;
        int i, j, k, l, status;
@@ -4876,8 +4846,7 @@ bail_out:
        return status;
 }
 
-static void __devinit
-sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
+static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
 {
        u8 v1, v2, v3;
        int index;
@@ -4932,8 +4901,8 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
        sisfb_post_xgi_delay(ivideo, 0x43);
 }
 
-static void __devinit
-sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
+static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
+                                           u8 regb)
 {
        unsigned char *bios = ivideo->bios_abase;
        u8 v1;
@@ -4973,8 +4942,7 @@ sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
        sisfb_post_xgi_delay(ivideo, 1);
 }
 
-static void __devinit
-sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
+static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
 {
        sisfb_post_xgi_setclocks(ivideo, 1);
 
@@ -5015,8 +4983,7 @@ sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
        sisfb_post_xgi_delay(ivideo, 1);
 }
 
-static void __devinit
-sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
+static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
 {
        unsigned char *bios = ivideo->bios_abase;
        static const u8 cs158[8] = {
@@ -5061,8 +5028,7 @@ sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
                sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
 }
 
-static u8 __devinit
-sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
+static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
 {
        unsigned char *bios = ivideo->bios_abase;
        u8 ramtype;
@@ -5101,8 +5067,7 @@ sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
        return ramtype;
 }
 
-static int __devinit
-sisfb_post_xgi(struct pci_dev *pdev)
+static int sisfb_post_xgi(struct pci_dev *pdev)
 {
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
        unsigned char *bios = ivideo->bios_abase;
@@ -5839,8 +5804,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
 }
 #endif
 
-static int __devinit
-sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct sisfb_chip_info  *chipinfo = &sisfb_chip_info[ent->driver_data];
        struct sis_video_info   *ivideo = NULL;
@@ -6530,7 +6494,7 @@ error_3:  vfree(ivideo->bios_abase);
 /*                PCI DEVICE HANDLING                */
 /*****************************************************/
 
-static void __devexit sisfb_remove(struct pci_dev *pdev)
+static void sisfb_remove(struct pci_dev *pdev)
 {
        struct sis_video_info   *ivideo = pci_get_drvdata(pdev);
        struct fb_info          *sis_fb_info = ivideo->memyselfandi;
@@ -6591,7 +6555,7 @@ static struct pci_driver sisfb_driver = {
        .name           = "sisfb",
        .id_table       = sisfb_pci_table,
        .probe          = sisfb_probe,
-       .remove         = __devexit_p(sisfb_remove)
+       .remove         = sisfb_remove,
 };
 
 static int __init sisfb_init(void)
index 9540e977270e3932c1d536990546541cefa4258d..32e23c20943056ec221c10f338cbdae964421742 100644 (file)
@@ -98,7 +98,7 @@ static struct sisfb_chip_info {
        int             hwcursor_size;
        int             CRT2_write_enable;
        const char      *chip_name;
-} sisfb_chip_info[] __devinitdata = {
+} sisfb_chip_info[] = {
        { SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
        { SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
        { SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
@@ -113,7 +113,7 @@ static struct sisfb_chip_info {
        { XGI_40,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
 };
 
-static struct pci_device_id __devinitdata sisfb_pci_table[] = {
+static struct pci_device_id sisfb_pci_table[] = {
 #ifdef CONFIG_FB_SIS_300
        { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
@@ -317,7 +317,7 @@ static struct _sis_lcd_data {
        u16 xres;
        u16 yres;
        u8  default_mode_idx;
-} sis_lcd_data[] __devinitdata = {
+} sis_lcd_data[] = {
        { LCD_640x480,    640,  480,  23 },
        { LCD_800x600,    800,  600,  43 },
        { LCD_1024x600,  1024,  600,  67 },
@@ -339,21 +339,21 @@ static struct _sis_lcd_data {
 };
 
 /* CR36 evaluation */
-static unsigned short sis300paneltype[] __devinitdata = {
+static unsigned short sis300paneltype[] = {
        LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
        LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
        LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
        LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN
 };
 
-static unsigned short sis310paneltype[] __devinitdata = {
+static unsigned short sis310paneltype[] = {
        LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
        LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
        LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
        LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN,   LCD_UNKNOWN
 };
 
-static unsigned short sis661paneltype[] __devinitdata = {
+static unsigned short sis661paneltype[] = {
        LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
        LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
        LCD_1280x854,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
@@ -466,7 +466,7 @@ static struct _sisfbddcsmodes {
        u16 h;
        u16 v;
        u32 d;
-} sisfb_ddcsmodes[] __devinitdata = {
+} sisfb_ddcsmodes[] = {
        { 0x10000, 67, 75, 108000},
        { 0x08000, 48, 72,  50000},
        { 0x04000, 46, 75,  49500},
@@ -488,7 +488,7 @@ static struct _sisfbddcfmodes {
        u16 v;
        u16 h;
        u32 d;
-} sisfb_ddcfmodes[] __devinitdata = {
+} sisfb_ddcfmodes[] = {
        { 1280, 1024, 85, 92, 157500},
        { 1600, 1200, 60, 75, 162000},
        { 1600, 1200, 65, 82, 175500},
@@ -505,7 +505,7 @@ static struct _chswtable {
        u16  subsysCard;
        char *vendorName;
        char *cardName;
-} mychswtable[] __devinitdata = {
+} mychswtable[] = {
        { 0x1631, 0x1002, "Mitachi", "0x1002" },
        { 0x1071, 0x7521, "Mitac"  , "7521P"  },
        { 0,      0,      ""       , ""       }
@@ -525,7 +525,7 @@ static struct _customttable {
        char  *cardName;
        u32   SpecialID;
        char  *optionName;
-} mycustomttable[] __devinitdata = {
+} mycustomttable[] = {
        { SIS_630, "2.00.07", "09/27/2002-13:38:25",
          0x3240A8,
          { 0x220, 0x227, 0x228, 0x229, 0x0ee },
index 5b6abc6de84ba0a823a80806f0d84c6675f0b5c0..2d4694c6b9e0f207338fe79a4a47b4846b0438cf 100644 (file)
@@ -63,7 +63,7 @@
 /*
  * Driver data
  */
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 /*
  *  If your driver supports multiple boards, you should make the  
@@ -84,7 +84,7 @@ struct xxx_par;
  * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
  * to get a fb_var_screeninfo. Otherwise define a default var as well. 
  */
-static struct fb_fix_screeninfo xxxfb_fix __devinitdata = {
+static struct fb_fix_screeninfo xxxfb_fix = {
        .id =           "FB's name", 
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -678,8 +678,7 @@ static struct fb_ops xxxfb_ops = {
      */
 
 /* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
-static int __devinit xxxfb_probe(struct pci_dev *dev,
-                             const struct pci_device_id *ent)
+static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
     struct fb_info *info;
     struct xxx_par *par;
@@ -705,9 +704,7 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
      */
     info->screen_base = framebuffer_virtual_memory;
     info->fbops = &xxxfb_ops;
-    info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be
-                           * used, so mark it as __devinitdata
-                           */
+    info->fix = xxxfb_fix;
     info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
                                            * 16-member array
                                            */
@@ -836,8 +833,8 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
     /*
      *  Cleanup
      */
-/* static void __devexit xxxfb_remove(struct platform_device *pdev) */
-static void __devexit xxxfb_remove(struct pci_dev *dev)
+/* static void xxxfb_remove(struct platform_device *pdev) */
+static void xxxfb_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        /* or platform_get_drvdata(pdev); */
@@ -899,7 +896,7 @@ static struct pci_driver xxxfb_driver = {
        .name =         "xxxfb",
        .id_table =     xxxfb_id_table,
        .probe =        xxxfb_probe,
-       .remove =       __devexit_p(xxxfb_remove),
+       .remove =       xxxfb_remove,
        .suspend =      xxxfb_suspend, /* optional but recommended */
        .resume =       xxxfb_resume,  /* optional but recommended */
 };
index 3690effbedccc2bf552c66e997ca5257b1b4c20a..1501979099dce08b1b17cff6d0dc281135a9dcb0 100644 (file)
@@ -46,7 +46,7 @@
 static char *fb_mode = "640x480-16@60";
 static unsigned long default_bpp = 16;
 
-static struct fb_videomode __devinitdata sm501_default_mode = {
+static struct fb_videomode sm501_default_mode = {
        .refresh        = 60,
        .xres           = 640,
        .yres           = 480,
@@ -1664,8 +1664,7 @@ static void sm501fb_stop(struct sm501fb_info *info)
                           resource_size(info->regs_res));
 }
 
-static int __devinit sm501fb_init_fb(struct fb_info *fb,
-                          enum sm501_controller head,
+static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
                           const char *fbname)
 {
        struct sm501_platdata_fbsub *pd;
@@ -1850,8 +1849,8 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
 static char driver_name_crt[] = "sm501fb-crt";
 static char driver_name_pnl[] = "sm501fb-panel";
 
-static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
-                                      enum sm501_controller head)
+static int sm501fb_probe_one(struct sm501fb_info *info,
+                            enum sm501_controller head)
 {
        unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
        struct sm501_platdata_fbsub *pd;
@@ -1892,9 +1891,8 @@ static void sm501_free_init_fb(struct sm501fb_info *info,
        fb_dealloc_cmap(&fbi->cmap);
 }
 
-static int __devinit sm501fb_start_one(struct sm501fb_info *info,
-                                      enum sm501_controller head,
-                                      const char *drvname)
+static int sm501fb_start_one(struct sm501fb_info *info,
+                            enum sm501_controller head, const char *drvname)
 {
        struct fb_info *fbi = info->fb[head];
        int ret;
@@ -1922,7 +1920,7 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info,
        return 0;
 }
 
-static int __devinit sm501fb_probe(struct platform_device *pdev)
+static int sm501fb_probe(struct platform_device *pdev)
 {
        struct sm501fb_info *info;
        struct device *dev = &pdev->dev;
index 6101f5c2f62f5ce3b2d32e40ea2dc346831f9d49..395cb6a8d8f3a86e3507be05686218ebee6f7d6f 100644 (file)
@@ -36,7 +36,7 @@ struct ssd1307fb_par {
        int reset;
 };
 
-static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
+static struct fb_fix_screeninfo ssd1307fb_fix = {
        .id             = "Solomon SSD1307",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_MONO10,
@@ -47,7 +47,7 @@ static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
+static struct fb_var_screeninfo ssd1307fb_var = {
        .xres           = SSD1307FB_WIDTH,
        .yres           = SSD1307FB_HEIGHT,
        .xres_virtual   = SSD1307FB_WIDTH,
@@ -145,8 +145,8 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
                                u32 page_length = SSD1307FB_WIDTH * i;
                                u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
                                u8 byte = *(vmem + index);
-                               u8 bit = byte & (1 << (7 - (j % 8)));
-                               bit = bit >> (7 - (j % 8));
+                               u8 bit = byte & (1 << (j % 8));
+                               bit = bit >> (j % 8);
                                buf |= bit << k;
                        }
                        ssd1307fb_write_data(par->client, buf);
@@ -227,7 +227,8 @@ static struct fb_deferred_io ssd1307fb_defio = {
        .deferred_io    = ssd1307fb_deferred_io,
 };
 
-static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int ssd1307fb_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct fb_info *info;
        u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
@@ -352,7 +353,7 @@ fb_alloc_error:
        return ret;
 }
 
-static int __devexit ssd1307fb_remove(struct i2c_client *client)
+static int ssd1307fb_remove(struct i2c_client *client)
 {
        struct fb_info *info = i2c_get_clientdata(client);
        struct ssd1307fb_par *par = info->par;
@@ -380,7 +381,7 @@ MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 
 static struct i2c_driver ssd1307fb_driver = {
        .probe = ssd1307fb_probe,
-       .remove = __devexit_p(ssd1307fb_remove),
+       .remove = ssd1307fb_remove,
        .id_table = ssd1307fb_i2c_id,
        .driver = {
                .name = "ssd1307fb",
index 111fb32e87695c4343db204cc5b8dd703d725e30..9c00026e3ae24ea652aefab4b2127f6953789d33 100644 (file)
@@ -104,7 +104,7 @@ static bool slowpci;                /* slow PCI settings */
 */
 #define DEFAULT_VIDEO_MODE "640x480@60"
 
-static char *mode_option __devinitdata = DEFAULT_VIDEO_MODE;
+static char *mode_option = DEFAULT_VIDEO_MODE;
 
 enum {
        ID_VOODOO1 = 0,
@@ -113,7 +113,7 @@ enum {
 
 #define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
 
-static struct sst_spec voodoo_spec[] __devinitdata = {
+static struct sst_spec voodoo_spec[] = {
  { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
  { .name = "Voodoo2",        .default_gfx_clock = 75000, .max_gfxclk = 85 },
 };
@@ -822,7 +822,7 @@ static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 /* 
  * get lfb size 
  */
-static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize)
+static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
 {
        u8 __iomem *fbbase_virt = info->screen_base;
 
@@ -865,7 +865,7 @@ static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize)
 /* fbi should be idle, and fifo emty and mem disabled */
 /* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
 
-static int __devinit sst_detect_att(struct fb_info *info)
+static int sst_detect_att(struct fb_info *info)
 {
        struct sstfb_par *par = info->par;
        int i, mir, dir;
@@ -890,7 +890,7 @@ static int __devinit sst_detect_att(struct fb_info *info)
        return 0;
 }
 
-static int __devinit sst_detect_ti(struct fb_info *info)
+static int sst_detect_ti(struct fb_info *info)
 {
        struct sstfb_par *par = info->par;
        int i, mir, dir;
@@ -926,7 +926,7 @@ static int __devinit sst_detect_ti(struct fb_info *info)
  * touched...
  * is it really safe ? how can i reset this ramdac ? geee...
  */
-static int __devinit sst_detect_ics(struct fb_info *info)
+static int sst_detect_ics(struct fb_info *info)
 {
        struct sstfb_par *par = info->par;
        int m_clk0_1, m_clk0_7, m_clk1_b;
@@ -1105,7 +1105,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
  */
 
 
-static struct dac_switch dacs[] __devinitdata = {
+static struct dac_switch dacs[] = {
        {       .name           = "TI TVP3409",
                .detect         = sst_detect_ti,
                .set_pll        = sst_set_pll_att_ti,
@@ -1121,7 +1121,7 @@ static struct dac_switch dacs[] __devinitdata = {
                .set_vidmod     = sst_set_vidmod_ics },
 };
 
-static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
+static int sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
 {
        int i, ret = 0;
 
@@ -1140,7 +1140,7 @@ static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *
 /*
  * Internal Routines
  */
-static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
+static int sst_init(struct fb_info *info, struct sstfb_par *par)
 {
        u32 fbiinit0, fbiinit1, fbiinit4;
        struct pci_dev *dev = par->dev;
@@ -1239,7 +1239,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
        return 1;
 }
 
-static void  __devexit sst_shutdown(struct fb_info *info)
+static void sst_shutdown(struct fb_info *info)
 {
        struct sstfb_par *par = info->par;
        struct pci_dev *dev = par->dev;
@@ -1271,7 +1271,7 @@ static void  __devexit sst_shutdown(struct fb_info *info)
 /*
  * Interface to the world
  */
-static int  __devinit sstfb_setup(char *options)
+static int sstfb_setup(char *options)
 {
        char *this_opt;
 
@@ -1317,8 +1317,7 @@ static struct fb_ops sstfb_ops = {
        .fb_ioctl       = sstfb_ioctl,
 };
 
-static int __devinit sstfb_probe(struct pci_dev *pdev,
-                       const struct pci_device_id *id)
+static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct fb_info *info;
        struct fb_fix_screeninfo *fix;
@@ -1458,7 +1457,7 @@ fail_mmio_mem:
        return -ENXIO;  /* no voodoo detected */
 }
 
-static void __devexit sstfb_remove(struct pci_dev *pdev)
+static void sstfb_remove(struct pci_dev *pdev)
 {
        struct sstfb_par *par;
        struct fb_info *info;
@@ -1490,11 +1489,11 @@ static struct pci_driver sstfb_driver = {
        .name           = "sstfb",
        .id_table       = sstfb_id_tbl,
        .probe          = sstfb_probe,
-       .remove         = __devexit_p(sstfb_remove),
+       .remove         = sstfb_remove,
 };
 
 
-static int __devinit sstfb_init(void)
+static int sstfb_init(void)
 {
        char *option = NULL;
 
@@ -1505,7 +1504,7 @@ static int __devinit sstfb_init(void)
        return pci_register_driver(&sstfb_driver);
 }
 
-static void __devexit sstfb_exit(void)
+static void sstfb_exit(void)
 {
        pci_unregister_driver(&sstfb_driver);
 }
index 729a50722bdfb05138983fbf50c0e74145a97f6d..cc6f48bba36be34f167710f0be7ed7e50da601fa 100644 (file)
@@ -25,7 +25,7 @@ struct gfb_info {
        u32                     pseudo_palette[16];
 };
 
-static int __devinit gfb_get_props(struct gfb_info *gp)
+static int gfb_get_props(struct gfb_info *gp)
 {
        gp->width = of_getintprop_default(gp->of_node, "width", 0);
        gp->height = of_getintprop_default(gp->of_node, "height", 0);
@@ -66,7 +66,7 @@ static struct fb_ops gfb_ops = {
        .fb_imageblit           = cfb_imageblit,
 };
 
-static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
+static int gfb_set_fbinfo(struct gfb_info *gp)
 {
        struct fb_info *info = gp->info;
        struct fb_var_screeninfo *var = &info->var;
@@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
         return 0;
 }
 
-static int __devinit gfb_probe(struct platform_device *op)
+static int gfb_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -173,7 +173,7 @@ err_out:
        return err;
 }
 
-static int __devexit gfb_remove(struct platform_device *op)
+static int gfb_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct gfb_info *gp = info->par;
@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, ffb_match);
 
 static struct platform_driver gfb_driver = {
        .probe          = gfb_probe,
-       .remove         = __devexit_p(gfb_remove),
+       .remove         = gfb_remove,
        .driver = {
                .name           = "gfb",
                .owner          = THIS_MODULE,
index 7fbcba86d1a223c185069297b9a96033d70deded..843b6bab0483bb60d357f38129638cc61411121f 100644 (file)
@@ -29,7 +29,7 @@ struct s3d_info {
        u32                     pseudo_palette[16];
 };
 
-static int __devinit s3d_get_props(struct s3d_info *sp)
+static int s3d_get_props(struct s3d_info *sp)
 {
        sp->width = of_getintprop_default(sp->of_node, "width", 0);
        sp->height = of_getintprop_default(sp->of_node, "height", 0);
@@ -70,7 +70,7 @@ static struct fb_ops s3d_ops = {
        .fb_imageblit           = cfb_imageblit,
 };
 
-static int __devinit s3d_set_fbinfo(struct s3d_info *sp)
+static int s3d_set_fbinfo(struct s3d_info *sp)
 {
        struct fb_info *info = sp->info;
        struct fb_var_screeninfo *var = &info->var;
@@ -115,8 +115,8 @@ static int __devinit s3d_set_fbinfo(struct s3d_info *sp)
         return 0;
 }
 
-static int __devinit s3d_pci_register(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int s3d_pci_register(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct s3d_info *sp;
@@ -219,7 +219,7 @@ err_out:
        return err;
 }
 
-static void __devexit s3d_pci_unregister(struct pci_dev *pdev)
+static void s3d_pci_unregister(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct s3d_info *sp = info->par;
@@ -251,7 +251,7 @@ static struct pci_driver s3d_driver = {
        .name           = "s3d",
        .id_table       = s3d_pci_table,
        .probe          = s3d_pci_register,
-       .remove         = __devexit_p(s3d_pci_unregister),
+       .remove         = s3d_pci_unregister,
 };
 
 static int __init s3d_init(void)
index 6c71b1b44477322eb1a45b312aa8a0b780e3f9ad..387350d004df7caa1ec5d566c905e2c231a95dc8 100644 (file)
@@ -51,7 +51,7 @@ struct e3d_info {
        u32                     pseudo_palette[16];
 };
 
-static int __devinit e3d_get_props(struct e3d_info *ep)
+static int e3d_get_props(struct e3d_info *ep)
 {
        ep->width = of_getintprop_default(ep->of_node, "width", 0);
        ep->height = of_getintprop_default(ep->of_node, "height", 0);
@@ -193,7 +193,7 @@ static struct fb_ops e3d_ops = {
        .fb_imageblit           = e3d_imageblit,
 };
 
-static int __devinit e3d_set_fbinfo(struct e3d_info *ep)
+static int e3d_set_fbinfo(struct e3d_info *ep)
 {
        struct fb_info *info = ep->info;
        struct fb_var_screeninfo *var = &info->var;
@@ -238,8 +238,8 @@ static int __devinit e3d_set_fbinfo(struct e3d_info *ep)
         return 0;
 }
 
-static int __devinit e3d_pci_register(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int e3d_pci_register(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct device_node *of_node;
        const char *device_type;
@@ -392,7 +392,7 @@ err_out:
        return err;
 }
 
-static void __devexit e3d_pci_unregister(struct pci_dev *pdev)
+static void e3d_pci_unregister(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct e3d_info *ep = info->par;
@@ -437,7 +437,7 @@ static struct pci_driver e3d_driver = {
        .name           = "e3d",
        .id_table       = e3d_pci_table,
        .probe          = e3d_pci_register,
-       .remove         = __devexit_p(e3d_pci_unregister),
+       .remove         = e3d_pci_unregister,
 };
 
 static int __init e3d_init(void)
index 07c66e9466343bec9b9f7cd0741698903d44e1e5..c000852500aa06822f19bb713b5f0b27c94359ab 100644 (file)
@@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
                           info->screen_base, info->fix.smem_len);
 }
 
-static int __devinit tcx_probe(struct platform_device *op)
+static int tcx_probe(struct platform_device *op)
 {
        struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
@@ -486,7 +486,7 @@ out_err:
        return err;
 }
 
-static int __devexit tcx_remove(struct platform_device *op)
+static int tcx_remove(struct platform_device *op)
 {
        struct fb_info *info = dev_get_drvdata(&op->dev);
        struct tcx_par *par = info->par;
@@ -518,7 +518,7 @@ static struct platform_driver tcx_driver = {
                .of_match_table = tcx_match,
        },
        .probe          = tcx_probe,
-       .remove         = __devexit_p(tcx_remove),
+       .remove         = tcx_remove,
 };
 
 static int __init tcx_init(void)
index e026724a3a56528a3782e87f9615109bdcd1811f..64bc28ba40375cdca47cd3219bba3e61b4a89d70 100644 (file)
@@ -100,7 +100,7 @@ static inline int mtrr_del(int reg, unsigned long base,
 #define VOODOO3_MAX_PIXCLOCK 300000
 #define VOODOO5_MAX_PIXCLOCK 350000
 
-static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
+static struct fb_fix_screeninfo tdfx_fix = {
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
        .ypanstep =     1,
@@ -108,7 +108,7 @@ static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
        .accel =        FB_ACCEL_3DFX_BANSHEE
 };
 
-static struct fb_var_screeninfo tdfx_var __devinitdata = {
+static struct fb_var_screeninfo tdfx_var = {
        /* "640x480, 8 bpp @ 60 Hz */
        .xres =         640,
        .yres =         480,
@@ -135,9 +135,8 @@ static struct fb_var_screeninfo tdfx_var __devinitdata = {
 /*
  * PCI driver prototypes
  */
-static int __devinit tdfxfb_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id);
-static void __devexit tdfxfb_remove(struct pci_dev *pdev);
+static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void tdfxfb_remove(struct pci_dev *pdev);
 
 static struct pci_device_id tdfxfb_id_table[] = {
        { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
@@ -156,7 +155,7 @@ static struct pci_driver tdfxfb_driver = {
        .name           = "tdfxfb",
        .id_table       = tdfxfb_id_table,
        .probe          = tdfxfb_probe,
-       .remove         = __devexit_p(tdfxfb_remove),
+       .remove         = tdfxfb_remove,
 };
 
 MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
@@ -167,9 +166,9 @@ MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
 static int nopan;
 static int nowrap = 1;      /* not implemented (yet) */
 static int hwcursor = 1;
-static char *mode_option __devinitdata;
+static char *mode_option;
 /* mtrr option */
-static bool nomtrr __devinitdata;
+static bool nomtrr;
 
 /* -------------------------------------------------------------------------
  *                     Hardware-specific funcions
@@ -1279,8 +1278,8 @@ static int tdfxfb_ddc_getsda(void *data)
        return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
 }
 
-static int __devinit tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan,
-                                         const char *name, struct device *dev)
+static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
+                               struct device *dev)
 {
        int rc;
 
@@ -1308,8 +1307,8 @@ static int __devinit tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan,
        return rc;
 }
 
-static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
-                                         const char *name, struct device *dev)
+static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
+                               struct device *dev)
 {
        int rc;
 
@@ -1336,7 +1335,7 @@ static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
        return rc;
 }
 
-static void __devinit tdfxfb_create_i2c_busses(struct fb_info *info)
+static void tdfxfb_create_i2c_busses(struct fb_info *info)
 {
        struct tdfx_par *par = info->par;
 
@@ -1388,8 +1387,7 @@ static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
  *      Initializes and allocates resources for PCI device @pdev.
  *
  */
-static int __devinit tdfxfb_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *id)
+static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct tdfx_par *default_par;
        struct fb_info *info;
@@ -1626,7 +1624,7 @@ static void __init tdfxfb_setup(char *options)
  *      lifetime for the PCI device @pdev.
  *
  */
-static void __devexit tdfxfb_remove(struct pci_dev *pdev)
+static void tdfxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct tdfx_par *par = info->par;
index aba7686b1a32fe76c7259fa48e3d3cad5c6369b9..c9c8e5a1fdeef75e7b5a38039514f68f8abebec1 100644 (file)
@@ -61,8 +61,8 @@ static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
 static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 
-static int __devinit tgafb_register(struct device *dev);
-static void __devexit tgafb_unregister(struct device *dev);
+static int tgafb_register(struct device *dev);
+static void tgafb_unregister(struct device *dev);
 
 static const char *mode_option;
 static const char *mode_option_pci = "640x480@60";
@@ -93,9 +93,8 @@ static struct fb_ops tgafb_ops = {
 /*
  *  PCI registration operations
  */
-static int __devinit tgafb_pci_register(struct pci_dev *,
-                                       const struct pci_device_id *);
-static void __devexit tgafb_pci_unregister(struct pci_dev *);
+static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
+static void tgafb_pci_unregister(struct pci_dev *);
 
 static struct pci_device_id const tgafb_pci_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
@@ -107,17 +106,16 @@ static struct pci_driver tgafb_pci_driver = {
        .name                   = "tgafb",
        .id_table               = tgafb_pci_table,
        .probe                  = tgafb_pci_register,
-       .remove                 = __devexit_p(tgafb_pci_unregister),
+       .remove                 = tgafb_pci_unregister,
 };
 
-static int __devinit
-tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int tgafb_pci_register(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        return tgafb_register(&pdev->dev);
 }
 
-static void __devexit
-tgafb_pci_unregister(struct pci_dev *pdev)
+static void tgafb_pci_unregister(struct pci_dev *pdev)
 {
        tgafb_unregister(&pdev->dev);
 }
@@ -127,8 +125,8 @@ tgafb_pci_unregister(struct pci_dev *pdev)
 /*
  *  TC registration operations
  */
-static int __devinit tgafb_tc_register(struct device *);
-static int __devexit tgafb_tc_unregister(struct device *);
+static int tgafb_tc_register(struct device *);
+static int tgafb_tc_unregister(struct device *);
 
 static struct tc_device_id const tgafb_tc_table[] = {
        { "DEC     ", "PMAGD-AA" },
@@ -143,12 +141,11 @@ static struct tc_driver tgafb_tc_driver = {
                .name           = "tgafb",
                .bus            = &tc_bus_type,
                .probe          = tgafb_tc_register,
-               .remove         = __devexit_p(tgafb_tc_unregister),
+               .remove         = tgafb_tc_unregister,
        },
 };
 
-static int __devinit
-tgafb_tc_register(struct device *dev)
+static int tgafb_tc_register(struct device *dev)
 {
        int status = tgafb_register(dev);
        if (!status)
@@ -156,8 +153,7 @@ tgafb_tc_register(struct device *dev)
        return status;
 }
 
-static int __devexit
-tgafb_tc_unregister(struct device *dev)
+static int tgafb_tc_unregister(struct device *dev)
 {
        put_device(dev);
        tgafb_unregister(dev);
@@ -1546,8 +1542,7 @@ static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
        return 0;
 }
 
-static int __devinit
-tgafb_register(struct device *dev)
+static int tgafb_register(struct device *dev)
 {
        static const struct fb_videomode modedb_tc = {
                /* 1280x1024 @ 72 Hz, 76.8 kHz hsync */
@@ -1692,8 +1687,7 @@ tgafb_register(struct device *dev)
        return ret;
 }
 
-static void __devexit
-tgafb_unregister(struct device *dev)
+static void tgafb_unregister(struct device *dev)
 {
        resource_size_t bar0_start = 0, bar0_len = 0;
        int tga_bus_pci = TGA_BUS_PCI(dev);
@@ -1721,16 +1715,14 @@ tgafb_unregister(struct device *dev)
        framebuffer_release(info);
 }
 
-static void __devexit
-tgafb_exit(void)
+static void tgafb_exit(void)
 {
        tc_unregister_driver(&tgafb_tc_driver);
        pci_unregister_driver(&tgafb_pci_driver);
 }
 
 #ifndef MODULE
-static int __devinit
-tgafb_setup(char *arg)
+static int tgafb_setup(char *arg)
 {
        char *this_opt;
 
@@ -1751,8 +1743,7 @@ tgafb_setup(char *arg)
 }
 #endif /* !MODULE */
 
-static int __devinit
-tgafb_init(void)
+static int tgafb_init(void)
 {
        int status;
 #ifndef MODULE
index b244f060f1511554491522889c138fc43cd864ba..dc4fb862015605738fba8ca7eb07aac1ca0a5b9e 100644 (file)
 #define LCR_VCLKHW             0x1b4 /* VCLK High Width                */
 #define LCR_OC                 0x1b6 /* Output Control                 */
 
-static char *mode_option __devinitdata;
+static char *mode_option;
 
 struct tmiofb_par {
        u32                             pseudo_palette[16];
@@ -675,7 +675,7 @@ static struct fb_ops tmiofb_ops = {
 
 /*--------------------------------------------------------------------------*/
 
-static int __devinit tmiofb_probe(struct platform_device *dev)
+static int tmiofb_probe(struct platform_device *dev)
 {
        const struct mfd_cell *cell = mfd_get_cell(dev);
        struct tmio_fb_data *data = dev->dev.platform_data;
@@ -807,7 +807,7 @@ err_ioremap_ccr:
        return retval;
 }
 
-static int __devexit tmiofb_remove(struct platform_device *dev)
+static int tmiofb_remove(struct platform_device *dev)
 {
        const struct mfd_cell *cell = mfd_get_cell(dev);
        struct fb_info *info = platform_get_drvdata(dev);
@@ -1002,7 +1002,7 @@ static struct platform_driver tmiofb_driver = {
        .driver.name    = "tmio-fb",
        .driver.owner   = THIS_MODULE,
        .probe          = tmiofb_probe,
-       .remove         = __devexit_p(tmiofb_remove),
+       .remove         = tmiofb_remove,
        .suspend        = tmiofb_suspend,
        .resume         = tmiofb_resume,
 };
index 34cf019bba44b64dc9c5a09ec4683efac8ff262c..ab57d387d6b5ffc093407ad9b2a0d55ddb8fe50e 100644 (file)
@@ -53,19 +53,19 @@ static struct fb_fix_screeninfo tridentfb_fix = {
 /* defaults which are normally overriden by user values */
 
 /* video mode */
-static char *mode_option __devinitdata = "640x480-8@60";
-static int bpp __devinitdata = 8;
+static char *mode_option = "640x480-8@60";
+static int bpp = 8;
 
-static int noaccel __devinitdata;
+static int noaccel;
 
 static int center;
 static int stretch;
 
-static int fp __devinitdata;
-static int crt __devinitdata;
+static int fp;
+static int crt;
 
-static int memsize __devinitdata;
-static int memdiff __devinitdata;
+static int memsize;
+static int memdiff;
 static int nativex;
 
 module_param(mode_option, charp, 0);
@@ -637,7 +637,7 @@ static inline void crtc_unlock(struct tridentfb_par *par)
 }
 
 /*  Return flat panel's maximum x resolution */
-static int __devinit get_nativex(struct tridentfb_par *par)
+static int get_nativex(struct tridentfb_par *par)
 {
        int x, y, tmp;
 
@@ -771,7 +771,7 @@ static void set_number_of_lines(struct tridentfb_par *par, int lines)
  * If we see that FP is active we assume we have one.
  * Otherwise we have a CRT display. User can override.
  */
-static int __devinit is_flatpanel(struct tridentfb_par *par)
+static int is_flatpanel(struct tridentfb_par *par)
 {
        if (fp)
                return 1;
@@ -781,7 +781,7 @@ static int __devinit is_flatpanel(struct tridentfb_par *par)
 }
 
 /* Try detecting the video memory size */
-static unsigned int __devinit get_memsize(struct tridentfb_par *par)
+static unsigned int get_memsize(struct tridentfb_par *par)
 {
        unsigned char tmp, tmp2;
        unsigned int k;
@@ -1331,8 +1331,8 @@ static struct fb_ops tridentfb_ops = {
        .fb_sync = tridentfb_sync,
 };
 
-static int __devinit trident_pci_probe(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+static int trident_pci_probe(struct pci_dev *dev,
+                            const struct pci_device_id *id)
 {
        int err;
        unsigned char revision;
@@ -1543,7 +1543,7 @@ out_unmap1:
        return err;
 }
 
-static void __devexit trident_pci_remove(struct pci_dev *dev)
+static void trident_pci_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct tridentfb_par *par = info->par;
@@ -1591,7 +1591,7 @@ static struct pci_driver tridentfb_pci_driver = {
        .name = "tridentfb",
        .id_table = trident_devices,
        .probe = trident_pci_probe,
-       .remove = __devexit_p(trident_pci_remove)
+       .remove = trident_pci_remove,
 };
 
 /*
index 2f8f82d874a15995b375a7250d5eb259711d9a69..b75db01864883e5fea61f63cc95e3df35e749ea2 100644 (file)
@@ -36,26 +36,26 @@ static struct cb_id uvesafb_cn_id = {
 static char v86d_path[PATH_MAX] = "/sbin/v86d";
 static char v86d_started;      /* has v86d been started by uvesafb? */
 
-static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
+static struct fb_fix_screeninfo uvesafb_fix = {
        .id     = "VESA VGA",
        .type   = FB_TYPE_PACKED_PIXELS,
        .accel  = FB_ACCEL_NONE,
        .visual = FB_VISUAL_TRUECOLOR,
 };
 
-static int mtrr                __devinitdata = 3; /* enable mtrr by default */
-static bool blank      = 1;               /* enable blanking by default */
-static int ypan                = 1;             /* 0: scroll, 1: ypan, 2: ywrap */
-static bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */
-static bool nocrtc     __devinitdata; /* ignore CRTC settings */
-static bool noedid     __devinitdata; /* don't try DDC transfers */
-static int vram_remap  __devinitdata; /* set amt. of memory to be used */
-static int vram_total  __devinitdata; /* set total amount of memory */
-static u16 maxclk      __devinitdata; /* maximum pixel clock */
-static u16 maxvf       __devinitdata; /* maximum vertical frequency */
-static u16 maxhf       __devinitdata; /* maximum horizontal frequency */
-static u16 vbemode     __devinitdata; /* force use of a specific VBE mode */
-static char *mode_option __devinitdata;
+static int mtrr                = 3;    /* enable mtrr by default */
+static bool blank      = 1;    /* enable blanking by default */
+static int ypan                = 1;    /* 0: scroll, 1: ypan, 2: ywrap */
+static bool pmi_setpal = true; /* use PMI for palette changes */
+static bool nocrtc;            /* ignore CRTC settings */
+static bool noedid;            /* don't try DDC transfers */
+static int vram_remap;         /* set amt. of memory to be used */
+static int vram_total;         /* set total amount of memory */
+static u16 maxclk;             /* maximum pixel clock */
+static u16 maxvf;              /* maximum vertical frequency */
+static u16 maxhf;              /* maximum horizontal frequency */
+static u16 vbemode;            /* force use of a specific VBE mode */
+static char *mode_option;
 static u8  dac_width   = 6;
 
 static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
@@ -418,8 +418,8 @@ static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
        uvesafb_free(task);
 }
 
-static int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
-               struct uvesafb_par *par)
+static int uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
+                              struct uvesafb_par *par)
 {
        int err;
 
@@ -477,8 +477,8 @@ static int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
        return 0;
 }
 
-static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
-               struct uvesafb_par *par)
+static int uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
+                               struct uvesafb_par *par)
 {
        int off = 0, err;
        u16 *mode;
@@ -556,8 +556,8 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
  * x86 and not x86_64.
  */
 #ifdef CONFIG_X86_32
-static int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
-               struct uvesafb_par *par)
+static int uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
+                             struct uvesafb_par *par)
 {
        int i, err;
 
@@ -602,8 +602,8 @@ static int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
  * Check whether a video mode is supported by the Video BIOS and is
  * compatible with the monitor limits.
  */
-static int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode,
-               struct fb_info *info)
+static int uvesafb_is_valid_mode(struct fb_videomode *mode,
+                                struct fb_info *info)
 {
        if (info->monspecs.gtf) {
                fb_videomode_to_var(&info->var, mode);
@@ -618,8 +618,7 @@ static int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode,
        return 1;
 }
 
-static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
-               struct fb_info *info)
+static int uvesafb_vbe_getedid(struct uvesafb_ktask *task, struct fb_info *info)
 {
        struct uvesafb_par *par = info->par;
        int err = 0;
@@ -684,8 +683,8 @@ static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
        return err;
 }
 
-static void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
-               struct fb_info *info)
+static void uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
+                                   struct fb_info *info)
 {
        struct uvesafb_par *par = info->par;
        int i;
@@ -765,8 +764,8 @@ static void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
        return;
 }
 
-static void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
-               struct uvesafb_par *par)
+static void uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
+                                    struct uvesafb_par *par)
 {
        int err;
 
@@ -794,7 +793,7 @@ static void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
        par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
 }
 
-static int __devinit uvesafb_vbe_init(struct fb_info *info)
+static int uvesafb_vbe_init(struct fb_info *info)
 {
        struct uvesafb_ktask *task = NULL;
        struct uvesafb_par *par = info->par;
@@ -839,7 +838,7 @@ out:        uvesafb_free(task);
        return err;
 }
 
-static int __devinit uvesafb_vbe_init_mode(struct fb_info *info)
+static int uvesafb_vbe_init_mode(struct fb_info *info)
 {
        struct list_head *pos;
        struct fb_modelist *modelist;
@@ -1444,8 +1443,7 @@ static struct fb_ops uvesafb_ops = {
        .fb_set_par     = uvesafb_set_par,
 };
 
-static void __devinit uvesafb_init_info(struct fb_info *info,
-               struct vbe_mode_ib *mode)
+static void uvesafb_init_info(struct fb_info *info, struct vbe_mode_ib *mode)
 {
        unsigned int size_vmode;
        unsigned int size_remap;
@@ -1540,7 +1538,7 @@ static void __devinit uvesafb_init_info(struct fb_info *info,
                info->fbops->fb_pan_display = NULL;
 }
 
-static void __devinit uvesafb_init_mtrr(struct fb_info *info)
+static void uvesafb_init_mtrr(struct fb_info *info)
 {
 #ifdef CONFIG_MTRR
        if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
@@ -1582,7 +1580,7 @@ static void __devinit uvesafb_init_mtrr(struct fb_info *info)
 #endif /* CONFIG_MTRR */
 }
 
-static void __devinit uvesafb_ioremap(struct fb_info *info)
+static void uvesafb_ioremap(struct fb_info *info)
 {
 #ifdef CONFIG_X86
        switch (mtrr) {
@@ -1738,7 +1736,7 @@ static struct attribute_group uvesafb_dev_attgrp = {
        .attrs = uvesafb_dev_attrs,
 };
 
-static int __devinit uvesafb_probe(struct platform_device *dev)
+static int uvesafb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct vbe_mode_ib *mode = NULL;
@@ -1882,7 +1880,7 @@ static struct platform_driver uvesafb_driver = {
 static struct platform_device *uvesafb_device;
 
 #ifndef MODULE
-static int __devinit uvesafb_setup(char *options)
+static int uvesafb_setup(char *options)
 {
        char *this_opt;
 
@@ -1950,7 +1948,7 @@ static ssize_t store_v86d(struct device_driver *dev, const char *buf,
 
 static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
 
-static int __devinit uvesafb_init(void)
+static int uvesafb_init(void)
 {
        int err;
 
@@ -1994,7 +1992,7 @@ static int __devinit uvesafb_init(void)
 
 module_init(uvesafb_init);
 
-static void __devexit uvesafb_exit(void)
+static void uvesafb_exit(void)
 {
        struct uvesafb_ktask *task;
 
index 4709edc3cb7f3057f7de9d8d63555f3fd1aa2cea..0aa516fc59cde498343bedf801b0d07c022b28e1 100644 (file)
@@ -393,7 +393,7 @@ static void vmlfb_release_devices(struct vml_par *par)
  * Free up allocated resources for a device.
  */
 
-static void __devexit vml_pci_remove(struct pci_dev *dev)
+static void vml_pci_remove(struct pci_dev *dev)
 {
        struct fb_info *info;
        struct vml_info *vinfo;
@@ -452,8 +452,7 @@ static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo *var)
  * struct per pipe. Currently we have only one pipe.
  */
 
-static int __devinit vml_pci_probe(struct pci_dev *dev,
-                                  const struct pci_device_id *id)
+static int vml_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct vml_info *vinfo;
        struct fb_info *info;
@@ -1060,7 +1059,7 @@ static struct pci_driver vmlfb_pci_driver = {
        .name = "vmlfb",
        .id_table = vml_ids,
        .probe = vml_pci_probe,
-       .remove = __devexit_p(vml_pci_remove)
+       .remove = vml_pci_remove,
 };
 
 static void __exit vmlfb_cleanup(void)
index c7f692525b8849a64a492577bde6861c55bae71d..8bc1f9398945a2c99b9e45286064499d4dfd88fe 100644 (file)
@@ -78,7 +78,7 @@ static void rvfree(void *mem, unsigned long size)
        vfree(mem);
 }
 
-static struct fb_var_screeninfo vfb_default __devinitdata = {
+static struct fb_var_screeninfo vfb_default = {
        .xres =         640,
        .yres =         480,
        .xres_virtual = 640,
@@ -100,7 +100,7 @@ static struct fb_var_screeninfo vfb_default __devinitdata = {
        .vmode =        FB_VMODE_NONINTERLACED,
 };
 
-static struct fb_fix_screeninfo vfb_fix __devinitdata = {
+static struct fb_fix_screeninfo vfb_fix = {
        .id =           "Virtual FB",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -477,7 +477,7 @@ static int __init vfb_setup(char *options)
      *  Initialisation
      */
 
-static int __devinit vfb_probe(struct platform_device *dev)
+static int vfb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        int retval = -ENOMEM;
index 0267acd8dc832690e3f02709a9e99361a8979805..545faeccdb445f78fc4eaf3809b2c65c792edd55 100644 (file)
@@ -65,7 +65,7 @@ struct vga16fb_par {
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo vga16fb_defined __devinitdata = {
+static struct fb_var_screeninfo vga16fb_defined = {
        .xres           = 640,
        .yres           = 480,
        .xres_virtual   = 640,
@@ -85,7 +85,7 @@ static struct fb_var_screeninfo vga16fb_defined __devinitdata = {
 };
 
 /* name should not depend on EGA/VGA */
-static struct fb_fix_screeninfo vga16fb_fix __devinitdata = {
+static struct fb_fix_screeninfo vga16fb_fix = {
        .id             = "VGA16 VGA",
        .smem_start     = VGA_FB_PHYS,
        .smem_len       = VGA_FB_PHYS_LEN,
@@ -1303,7 +1303,7 @@ static int __init vga16fb_setup(char *options)
 }
 #endif
 
-static int __devinit vga16fb_probe(struct platform_device *dev)
+static int vga16fb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
        struct vga16fb_par *par;
@@ -1395,7 +1395,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
        return ret;
 }
 
-static int __devexit vga16fb_remove(struct platform_device *dev)
+static int vga16fb_remove(struct platform_device *dev)
 {
        struct fb_info *info = platform_get_drvdata(dev);
 
@@ -1407,7 +1407,7 @@ static int __devexit vga16fb_remove(struct platform_device *dev)
 
 static struct platform_driver vga16fb_driver = {
        .probe = vga16fb_probe,
-       .remove = __devexit_p(vga16fb_remove),
+       .remove = vga16fb_remove,
        .driver = {
                .name = "vga16fb",
        },
index 6be72f0ba21d16a7d23b8bb2b0d465d7efd50027..7789553952d3b1fdac3e9a23e6f63edf1cdae4aa 100644 (file)
@@ -25,7 +25,7 @@
 static void tmds_register_write(int index, u8 data);
 static int tmds_register_read(int index);
 static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
-static void __devinit dvi_get_panel_size_from_DDCv1(
+static void dvi_get_panel_size_from_DDCv1(
        struct tmds_chip_information *tmds_chip,
        struct tmds_setting_information *tmds_setting);
 static int viafb_dvi_query_EDID(void);
@@ -35,8 +35,8 @@ static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
        return tmds_register_read(device_id_subaddr) == device_id;
 }
 
-void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
-       struct tmds_setting_information *tmds_setting)
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+                        struct tmds_setting_information *tmds_setting)
 {
        DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
 
@@ -47,7 +47,7 @@ void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
        return;
 }
 
-bool __devinit viafb_tmds_trasmitter_identify(void)
+bool viafb_tmds_trasmitter_identify(void)
 {
        unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
 
@@ -285,7 +285,7 @@ static int viafb_dvi_query_EDID(void)
 }
 
 /* Get Panel Size Using EDID1 Table */
-static void __devinit dvi_get_panel_size_from_DDCv1(
+static void dvi_get_panel_size_from_DDCv1(
        struct tmds_chip_information *tmds_chip,
        struct tmds_setting_information *tmds_setting)
 {
index db757850c2167228ab315a10321aec7ef0db8291..4c6bfba57d11ad87f6bd1d6c8be153e80142aa71 100644 (file)
@@ -56,8 +56,8 @@
 int viafb_dvi_sense(void);
 void viafb_dvi_disable(void);
 void viafb_dvi_enable(void);
-bool __devinit viafb_tmds_trasmitter_identify(void);
-void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+bool viafb_tmds_trasmitter_identify(void);
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
        struct tmds_setting_information *tmds_setting);
 void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
        u16 cxres, u16 cyres, int iga);
index 898590db5e14d5ecc3a887dfe4a18c9cf30a4a00..80233dae358ae1e1784d647e41382f90603bd23c 100644 (file)
@@ -465,9 +465,9 @@ static struct via_device_mapping device_mapping[] = {
 static struct via_clock clock;
 
 static void load_fix_bit_crtc_reg(void);
-static void __devinit init_gfx_chip_info(int chip_type);
-static void __devinit init_tmds_chip_info(void);
-static void __devinit init_lvds_chip_info(void);
+static void init_gfx_chip_info(int chip_type);
+static void init_tmds_chip_info(void);
+static void init_lvds_chip_info(void);
 static void device_screen_off(void);
 static void device_screen_on(void);
 static void set_display_channel(void);
@@ -1507,7 +1507,7 @@ void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
        viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
 }
 
-void __devinit viafb_init_chip_info(int chip_type)
+void viafb_init_chip_info(int chip_type)
 {
        via_clock_init(&clock, chip_type);
        init_gfx_chip_info(chip_type);
@@ -1540,7 +1540,7 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
        }
 }
 
-static void __devinit init_gfx_chip_info(int chip_type)
+static void init_gfx_chip_info(int chip_type)
 {
        u8 tmp;
 
@@ -1593,7 +1593,7 @@ static void __devinit init_gfx_chip_info(int chip_type)
        }
 }
 
-static void __devinit init_tmds_chip_info(void)
+static void init_tmds_chip_info(void)
 {
        viafb_tmds_trasmitter_identify();
 
@@ -1638,7 +1638,7 @@ static void __devinit init_tmds_chip_info(void)
                &viaparinfo->shared->tmds_setting_info);
 }
 
-static void __devinit init_lvds_chip_info(void)
+static void init_lvds_chip_info(void)
 {
        viafb_lvds_trasmitter_identify();
        viafb_init_lcd_size();
@@ -1672,7 +1672,7 @@ static void __devinit init_lvds_chip_info(void)
                  viaparinfo->chip_info->lvds_chip_info.output_interface);
 }
 
-void __devinit viafb_init_dac(int set_iga)
+void viafb_init_dac(int set_iga)
 {
        int i;
        u8 tmp;
index 6be243cfc823b4d257fc34044497b99907ce10c0..a8205754c7361ff2d68662892cbc581abaad2706 100644 (file)
@@ -663,8 +663,8 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
 int viafb_setmode(void);
 void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
        const struct fb_videomode *mode);
-void __devinit viafb_init_chip_info(int chip_type);
-void __devinit viafb_init_dac(int set_iga);
+void viafb_init_chip_info(int chip_type);
+void viafb_init_dac(int set_iga);
 int viafb_get_refresh(int hres, int vres, u32 float_refresh);
 void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
 
index 1650379105364d72c6fca5328d407f92035ef95c..980ee1b1dcf313b9dc98a6689b7cac48c702d887 100644 (file)
@@ -49,7 +49,7 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
 };
 
 static bool lvds_identify_integratedlvds(void);
-static void __devinit fp_id_to_vindex(int panel_id);
+static void fp_id_to_vindex(int panel_id);
 static int lvds_register_read(int index);
 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
                      int panel_vres);
@@ -81,7 +81,7 @@ static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
        return lvds_register_read(device_id_subaddr) == device_id;
 }
 
-void __devinit viafb_init_lcd_size(void)
+void viafb_init_lcd_size(void)
 {
        DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
 
@@ -139,7 +139,7 @@ static bool lvds_identify_integratedlvds(void)
        return true;
 }
 
-bool __devinit viafb_lvds_trasmitter_identify(void)
+bool viafb_lvds_trasmitter_identify(void)
 {
        if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
                viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
@@ -180,7 +180,7 @@ bool __devinit viafb_lvds_trasmitter_identify(void)
        return false;
 }
 
-static void __devinit fp_id_to_vindex(int panel_id)
+static void fp_id_to_vindex(int panel_id)
 {
        DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
 
@@ -914,7 +914,7 @@ static void check_diport_of_integrated_lvds(
                  plvds_chip_info->output_interface);
 }
 
-void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
+void viafb_init_lvds_output_interface(struct lvds_chip_information
                                *plvds_chip_info,
                                struct lvds_setting_information
                                *plvds_setting_info)
index 8f3e4e06156c3381648349969a263a7a3edc7afe..5c988a063ad5ec58f6116e92b3e27d05a424146f 100644 (file)
@@ -71,15 +71,15 @@ void viafb_enable_lvds_vt1636(struct lvds_setting_information
                        struct lvds_chip_information *plvds_chip_info);
 void viafb_lcd_disable(void);
 void viafb_lcd_enable(void);
-void __devinit viafb_init_lcd_size(void);
-void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
+void viafb_init_lcd_size(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
                                *plvds_chip_info,
                                struct lvds_setting_information
                                *plvds_setting_info);
 void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
        u16 cyres, struct lvds_setting_information *plvds_setting_info,
        struct lvds_chip_information *plvds_chip_info);
-bool __devinit viafb_lvds_trasmitter_identify(void);
+bool viafb_lvds_trasmitter_identify(void);
 void viafb_init_lvds_output_interface(struct lvds_chip_information
                                *plvds_chip_info,
                                struct lvds_setting_information
index dd58b530c0dffde2a1f511a059cb6bc42279f7c9..6e274825fb312349d95d5bdddb43b4c9e45e8775 100644 (file)
@@ -80,7 +80,7 @@ static inline int viafb_mmio_read(int reg)
  */
 static u32 viafb_enabled_ints;
 
-static void __devinit viafb_int_init(void)
+static void viafb_int_init(void)
 {
        viafb_enabled_ints = 0;
 
@@ -475,7 +475,7 @@ static int viafb_get_fb_size_from_pci(int chip_type)
 /*
  * Figure out and map our MMIO regions.
  */
-static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
+static int via_pci_setup_mmio(struct viafb_dev *vdev)
 {
        int ret;
        /*
@@ -550,8 +550,8 @@ static struct viafb_subdev_info {
 };
 #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
 
-static int __devinit via_create_subdev(struct viafb_dev *vdev,
-               struct viafb_subdev_info *info)
+static int via_create_subdev(struct viafb_dev *vdev,
+                            struct viafb_subdev_info *info)
 {
        int ret;
 
@@ -573,7 +573,7 @@ static int __devinit via_create_subdev(struct viafb_dev *vdev,
        return ret;
 }
 
-static int __devinit via_setup_subdevs(struct viafb_dev *vdev)
+static int via_setup_subdevs(struct viafb_dev *vdev)
 {
        int i;
 
@@ -671,8 +671,7 @@ static int via_resume(struct pci_dev *pdev)
 }
 #endif /* CONFIG_PM */
 
-static int __devinit via_pci_probe(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
+static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret;
 
@@ -716,7 +715,7 @@ out_disable:
        return ret;
 }
 
-static void __devexit via_pci_remove(struct pci_dev *pdev)
+static void via_pci_remove(struct pci_dev *pdev)
 {
        via_teardown_subdevs();
        via_fb_pci_remove(pdev);
@@ -725,7 +724,7 @@ static void __devexit via_pci_remove(struct pci_dev *pdev)
 }
 
 
-static struct pci_device_id via_pci_table[] __devinitdata = {
+static struct pci_device_id via_pci_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
          .driver_data = UNICHROME_CLE266 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
@@ -760,7 +759,7 @@ static struct pci_driver via_driver = {
        .name           = "viafb",
        .id_table       = via_pci_table,
        .probe          = via_pci_probe,
-       .remove         = __devexit_p(via_pci_remove),
+       .remove         = via_pci_remove,
 #ifdef CONFIG_PM
        .suspend        = via_suspend,
        .resume         = via_resume,
index d69cfef7c338551cf73524c29a18b99233308158..e408679081ab25a8adb3fe543a8c70c45e4289b5 100644 (file)
@@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
 /*
  * Platform device stuff.
  */
-static __devinit int viafb_gpio_probe(struct platform_device *platdev)
+static int viafb_gpio_probe(struct platform_device *platdev)
 {
        struct viafb_dev *vdev = platdev->dev.platform_data;
        struct via_port_cfg *port_cfg = vdev->port_cfg;
index c80e770e180029a132087f73f3cbbfc6295a7c5e..325c43c6ff973895eb6b4b573b330ad596295a6a 100644 (file)
@@ -1072,7 +1072,7 @@ static int __init parse_active_dev(void)
        return 0;
 }
 
-static int __devinit parse_port(char *opt_str, int *output_interface)
+static int parse_port(char *opt_str, int *output_interface)
 {
        if (!strncmp(opt_str, "DVP0", 4))
                *output_interface = INTERFACE_DVP0;
@@ -1089,7 +1089,7 @@ static int __devinit parse_port(char *opt_str, int *output_interface)
        return 0;
 }
 
-static void __devinit parse_lcd_port(void)
+static void parse_lcd_port(void)
 {
        parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
                output_interface);
@@ -1102,7 +1102,7 @@ static void __devinit parse_lcd_port(void)
                  output_interface);
 }
 
-static void __devinit parse_dvi_port(void)
+static void parse_dvi_port(void)
 {
        parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
                output_interface);
@@ -1727,7 +1727,7 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
 
 #endif
 
-static void __devinit i2c_bus_probe(struct viafb_shared *shared)
+static void i2c_bus_probe(struct viafb_shared *shared)
 {
        /* should be always CRT */
        printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
@@ -1753,7 +1753,7 @@ static void i2c_bus_free(struct viafb_shared *shared)
        via_aux_free(shared->i2c_2C);
 }
 
-int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
+int via_fb_pci_probe(struct viafb_dev *vdev)
 {
        u32 default_xres, default_yres;
        struct fb_var_screeninfo default_var;
@@ -1945,7 +1945,7 @@ out_fb_release:
        return rc;
 }
 
-void __devexit via_fb_pci_remove(struct pci_dev *pdev)
+void via_fb_pci_remove(struct pci_dev *pdev)
 {
        DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
        fb_dealloc_cmap(&viafbinfo->cmap);
index 9af8da70e7812e292d6b69cfce09f3a0ee3712c5..aa2579c2364a53ea07573d019605620184591daf 100644 (file)
@@ -273,7 +273,7 @@ static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit vt8500lcd_probe(struct platform_device *pdev)
+static int vt8500lcd_probe(struct platform_device *pdev)
 {
        struct vt8500lcd_info *fbi;
        struct resource *res;
@@ -469,7 +469,7 @@ failed:
        return ret;
 }
 
-static int __devexit vt8500lcd_remove(struct platform_device *pdev)
+static int vt8500lcd_remove(struct platform_device *pdev)
 {
        struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
        struct resource *res;
@@ -505,7 +505,7 @@ static const struct of_device_id via_dt_ids[] = {
 
 static struct platform_driver vt8500lcd_driver = {
        .probe          = vt8500lcd_probe,
-       .remove         = __devexit_p(vt8500lcd_remove),
+       .remove         = vt8500lcd_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "vt8500-lcd",
index 4e74d262cf3e9f338c1eb0cb46a5835794a532d3..e9557fa014eec0f201b1f91c38970097a37fd5e5 100644 (file)
@@ -660,7 +660,7 @@ static struct fb_ops vt8623fb_ops = {
 
 /* PCI probe */
 
-static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        struct pci_bus_region bus_reg;
        struct resource vga_res;
@@ -807,7 +807,7 @@ err_enable_device:
 
 /* PCI remove */
 
-static void __devexit vt8623_pci_remove(struct pci_dev *dev)
+static void vt8623_pci_remove(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
 
@@ -906,7 +906,7 @@ fail:
 
 /* List of boards that we are trying to support */
 
-static struct pci_device_id vt8623_devices[] __devinitdata = {
+static struct pci_device_id vt8623_devices[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},
        {0, 0, 0, 0, 0, 0, 0}
 };
@@ -917,7 +917,7 @@ static struct pci_driver vt8623fb_pci_driver = {
        .name           = "vt8623fb",
        .id_table       = vt8623_devices,
        .probe          = vt8623_pci_probe,
-       .remove         = __devexit_p(vt8623_pci_remove),
+       .remove         = vt8623_pci_remove,
        .suspend        = vt8623_pci_suspend,
        .resume         = vt8623_pci_resume,
 };
index 2f6b2b835f880391a9c7beccb750a2acc1347ca5..7a299e951f75421a7a4112eae5af284cc977a6ca 100644 (file)
@@ -54,7 +54,7 @@ static void w100_update_enable(void);
 static void w100_update_disable(void);
 static void calc_hsync(struct w100fb_par *par);
 static void w100_init_graphic_engine(struct w100fb_par *par);
-struct w100_pll_info *w100_get_xtal_table(unsigned int freq) __devinit;
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
 
 /* Pseudo palette size */
 #define MAX_PALETTES      16
@@ -630,7 +630,7 @@ static int w100fb_resume(struct platform_device *dev)
 #endif
 
 
-int __devinit w100fb_probe(struct platform_device *pdev)
+int w100fb_probe(struct platform_device *pdev)
 {
        int err = -EIO;
        struct w100fb_mach_info *inf;
@@ -783,7 +783,7 @@ out:
 }
 
 
-static int __devexit w100fb_remove(struct platform_device *pdev)
+static int w100fb_remove(struct platform_device *pdev)
 {
        struct fb_info *info = platform_get_drvdata(pdev);
        struct w100fb_par *par=info->par;
@@ -1021,7 +1021,7 @@ static struct pll_entries {
        { 0 },
 };
 
-struct w100_pll_info __devinit *w100_get_xtal_table(unsigned int freq)
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
 {
        struct pll_entries *pll_entry = w100_pll_tables;
 
@@ -1624,7 +1624,7 @@ static void w100_vsync(void)
 
 static struct platform_driver w100fb_driver = {
        .probe          = w100fb_probe,
-       .remove         = __devexit_p(w100fb_remove),
+       .remove         = w100fb_remove,
        .suspend        = w100fb_suspend,
        .resume         = w100fb_resume,
        .driver         = {
index 77539c1b56a028833d35e4db8ede98b8e4e7d4bc..4dd0580f96fd65c32f5c717c5ffdf332626b2a48 100644 (file)
@@ -260,7 +260,7 @@ static struct fb_ops wm8505fb_ops = {
        .fb_blank       = wm8505fb_blank,
 };
 
-static int __devinit wm8505fb_probe(struct platform_device *pdev)
+static int wm8505fb_probe(struct platform_device *pdev)
 {
        struct wm8505fb_info    *fbi;
        struct resource         *res;
@@ -431,7 +431,7 @@ failed:
        return ret;
 }
 
-static int __devexit wm8505fb_remove(struct platform_device *pdev)
+static int wm8505fb_remove(struct platform_device *pdev)
 {
        struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
        struct resource *res;
@@ -462,7 +462,7 @@ static const struct of_device_id wmt_dt_ids[] = {
 
 static struct platform_driver wm8505fb_driver = {
        .probe          = wm8505fb_probe,
-       .remove         = __devexit_p(wm8505fb_remove),
+       .remove         = wm8505fb_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = DRIVER_NAME,
index ba025b4c7d095b562cf5fae84a16914b9473aa37..4aaeb18223bcff371bfac7b9d8653f2c6fdef80b 100644 (file)
@@ -124,7 +124,7 @@ int wmt_ge_sync(struct fb_info *p)
 }
 EXPORT_SYMBOL_GPL(wmt_ge_sync);
 
-static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
+static int wmt_ge_rops_probe(struct platform_device *pdev)
 {
        struct resource *res;
 
@@ -152,7 +152,7 @@ static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
+static int wmt_ge_rops_remove(struct platform_device *pdev)
 {
        iounmap(regbase);
        return 0;
@@ -165,7 +165,7 @@ static const struct of_device_id wmt_dt_ids[] = {
 
 static struct platform_driver wmt_ge_rops_driver = {
        .probe          = wmt_ge_rops_probe,
-       .remove         = __devexit_p(wmt_ge_rops_remove),
+       .remove         = wmt_ge_rops_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "wmt_ge_rops",
index 917bb5681684d31490e1b228b60db57cc0d53a7b..cd005c227a23cd3748ae4cdb22584474273e88c5 100644 (file)
@@ -358,8 +358,8 @@ static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit xenfb_probe(struct xenbus_device *dev,
-                                const struct xenbus_device_id *id)
+static int xenfb_probe(struct xenbus_device *dev,
+                      const struct xenbus_device_id *id)
 {
        struct xenfb_info *info;
        struct fb_info *fb_info;
@@ -487,8 +487,7 @@ error:
        return ret;
 }
 
-static __devinit void
-xenfb_make_preferred_console(void)
+static void xenfb_make_preferred_console(void)
 {
        struct console *c;
 
index 18084525402ace0afd1c08ada58e2c2a50f5cfad..af0b4fdf9aa9a709340304a9490797360081b1b6 100644 (file)
@@ -403,7 +403,7 @@ static int xilinxfb_release(struct device *dev)
  * OF bus binding
  */
 
-static int __devinit xilinxfb_of_probe(struct platform_device *op)
+static int xilinxfb_of_probe(struct platform_device *op)
 {
        const u32 *prop;
        u32 *p;
@@ -485,13 +485,13 @@ static int __devinit xilinxfb_of_probe(struct platform_device *op)
        return -ENODEV;
 }
 
-static int __devexit xilinxfb_of_remove(struct platform_device *op)
+static int xilinxfb_of_remove(struct platform_device *op)
 {
        return xilinxfb_release(&op->dev);
 }
 
 /* Match table for of_platform binding */
-static struct of_device_id xilinxfb_of_match[] __devinitdata = {
+static struct of_device_id xilinxfb_of_match[] = {
        { .compatible = "xlnx,xps-tft-1.00.a", },
        { .compatible = "xlnx,xps-tft-2.00.a", },
        { .compatible = "xlnx,xps-tft-2.01.a", },
@@ -503,7 +503,7 @@ MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
 
 static struct platform_driver xilinxfb_of_driver = {
        .probe = xilinxfb_of_probe,
-       .remove = __devexit_p(xilinxfb_of_remove),
+       .remove = xilinxfb_of_remove,
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
index d19fe3e323b4dd17ad3cf43b099bdac7cf31aa5c..797e1c79a104864ff5c87c2e887c02eb2fe1db89 100644 (file)
@@ -500,7 +500,7 @@ static void remove_common(struct virtio_balloon *vb)
        vb->vdev->config->del_vqs(vb->vdev);
 }
 
-static void __devexit virtballoon_remove(struct virtio_device *vdev)
+static void virtballoon_remove(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
 
@@ -552,7 +552,7 @@ static struct virtio_driver virtio_balloon_driver = {
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
        .probe =        virtballoon_probe,
-       .remove =       __devexit_p(virtballoon_remove),
+       .remove =       virtballoon_remove,
        .config_changed = virtballoon_changed,
 #ifdef CONFIG_PM
        .freeze =       virtballoon_freeze,
index 634f80bcdbd7d3872201aa16af79cfd51caccaf9..31f966f4d27f6800899fa8cad4b6e390fd497003 100644 (file)
@@ -440,7 +440,7 @@ static struct virtio_config_ops virtio_mmio_config_ops = {
 
 /* Platform device */
 
-static int __devinit virtio_mmio_probe(struct platform_device *pdev)
+static int virtio_mmio_probe(struct platform_device *pdev)
 {
        struct virtio_mmio_device *vm_dev;
        struct resource *mem;
@@ -493,7 +493,7 @@ static int __devinit virtio_mmio_probe(struct platform_device *pdev)
        return register_virtio_device(&vm_dev->vdev);
 }
 
-static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+static int virtio_mmio_remove(struct platform_device *pdev)
 {
        struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
 
@@ -638,7 +638,7 @@ MODULE_DEVICE_TABLE(of, virtio_mmio_match);
 
 static struct platform_driver virtio_mmio_driver = {
        .probe          = virtio_mmio_probe,
-       .remove         = __devexit_p(virtio_mmio_remove),
+       .remove         = virtio_mmio_remove,
        .driver         = {
                .name   = "virtio-mmio",
                .owner  = THIS_MODULE,
index e3ecc94591ad29defa2b572d54eab60a223cb3aa..0c142892c105f6c56857352d8dda2d262582aaa0 100644 (file)
@@ -676,8 +676,8 @@ static void virtio_pci_release_dev(struct device *_d)
 }
 
 /* the PCI probing function */
-static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
-                                     const struct pci_device_id *id)
+static int virtio_pci_probe(struct pci_dev *pci_dev,
+                           const struct pci_device_id *id)
 {
        struct virtio_pci_device *vp_dev;
        int err;
@@ -751,7 +751,7 @@ out:
        return err;
 }
 
-static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
+static void virtio_pci_remove(struct pci_dev *pci_dev)
 {
        struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
 
@@ -822,7 +822,7 @@ static struct pci_driver virtio_pci_driver = {
        .name           = "virtio-pci",
        .id_table       = virtio_pci_id_table,
        .probe          = virtio_pci_probe,
-       .remove         = __devexit_p(virtio_pci_remove),
+       .remove         = virtio_pci_remove,
 #ifdef CONFIG_PM
        .driver.pm      = &virtio_pci_pm_ops,
 #endif
index aa250cebecd2963207b3eda1b767af65b4437f02..7b07135ab26ef722824c7387a9ec9df547d36f49 100644 (file)
@@ -772,7 +772,7 @@ static int vlynq_remove(struct platform_device *pdev)
 static struct platform_driver vlynq_platform_driver = {
        .driver.name = "vlynq",
        .probe = vlynq_probe,
-       .remove = __devexit_p(vlynq_remove),
+       .remove = vlynq_remove,
 };
 
 struct bus_type vlynq_bus_type = {
@@ -783,7 +783,7 @@ struct bus_type vlynq_bus_type = {
 };
 EXPORT_SYMBOL(vlynq_bus_type);
 
-static int __devinit vlynq_init(void)
+static int vlynq_init(void)
 {
        int res = 0;
 
@@ -803,7 +803,7 @@ fail_bus:
        return res;
 }
 
-static void __devexit vlynq_exit(void)
+static void vlynq_exit(void)
 {
        platform_driver_unregister(&vlynq_platform_driver);
        bus_unregister(&vlynq_bus_type);
index d338b56ea2f09b5a5005f7128cdff1a07906d779..708a25fc99616bf124764443d029b376e9f98cf9 100644 (file)
@@ -191,7 +191,7 @@ static struct platform_driver mxc_w1_driver = {
                   .name = "mxc_w1",
        },
        .probe = mxc_w1_probe,
-       .remove = __devexit_p(mxc_w1_remove),
+       .remove = mxc_w1_remove,
 };
 module_platform_driver(mxc_w1_driver);
 
index ad1bb9382a964dc69af3caeb55e83ec8d5a9bde0..7f809fd4a57f950c94c3d5d280fe471f60ebeaf4 100644 (file)
@@ -76,6 +76,16 @@ config DA9052_WATCHDOG
           Alternatively say M to compile the driver as a module,
           which will be called da9052_wdt.
 
+config DA9055_WATCHDOG
+       tristate "Dialog Semiconductor DA9055 Watchdog"
+       depends on MFD_DA9055
+       help
+         If you say yes here you get support for watchdog on the Dialog
+         Semiconductor DA9055 PMIC.
+
+         This driver can also be built as a module.  If so, the module
+         will be called da9055_wdt.
+
 config WM831X_WATCHDOG
        tristate "WM831x watchdog"
        depends on MFD_WM831X
@@ -232,6 +242,7 @@ config EP93XX_WATCHDOG
 config OMAP_WATCHDOG
        tristate "OMAP Watchdog"
        depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
+       select WATCHDOG_CORE
        help
          Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog.  Say 'Y'
          here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer.
@@ -300,6 +311,7 @@ config COH901327_WATCHDOG
 config TWL4030_WATCHDOG
        tristate "TWL4030 Watchdog"
        depends on TWL4030_CORE
+       select WATCHDOG_CORE
        help
          Support for TI TWL4030 watchdog.  Say 'Y' here to enable the
          watchdog timer support for TWL4030 chips.
@@ -342,7 +354,7 @@ config MAX63XX_WATCHDOG
 
 config IMX2_WDT
        tristate "IMX2+ Watchdog"
-       depends on IMX_HAVE_PLATFORM_IMX2_WDT
+       depends on ARCH_MXC
        help
          This is the driver for the hardware watchdog
          on the Freescale IMX2 and later processors.
@@ -431,7 +443,7 @@ config ALIM7101_WDT
 
 config F71808E_WDT
        tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        help
          This is the driver for the hardware watchdog on the Fintek
          F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers.
@@ -622,7 +634,7 @@ config IT8712F_WDT
 
 config IT87_WDT
        tristate "IT87 Watchdog Timer"
-       depends on X86 && EXPERIMENTAL
+       depends on X86
        ---help---
          This is the driver for the hardware watchdog on the ITE IT8702,
          IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
index 572b39bed06a256ff6c79df0b943acbda7e88174..97bbdb3a464844588fa97e526b89eb284f302145 100644 (file)
@@ -164,6 +164,7 @@ obj-$(CONFIG_XEN_WDT) += xen_wdt.o
 
 # Architecture Independent
 obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
+obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
 obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
index 7c8ede7816b1a1efacf9a196648bcfb2b5bc4c0c..38a999e60c0d7f26f03b2eac77f39e4b2296413a 100644 (file)
@@ -284,6 +284,7 @@ static void ath97_wdt_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver ath79_wdt_driver = {
+       .probe          = ath79_wdt_probe,
        .remove         = ath79_wdt_remove,
        .shutdown       = ath97_wdt_shutdown,
        .driver         = {
@@ -292,17 +293,7 @@ static struct platform_driver ath79_wdt_driver = {
        },
 };
 
-static int __init ath79_wdt_init(void)
-{
-       return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe);
-}
-module_init(ath79_wdt_init);
-
-static void __exit ath79_wdt_exit(void)
-{
-       platform_driver_unregister(&ath79_wdt_driver);
-}
-module_exit(ath79_wdt_exit);
+module_platform_driver(ath79_wdt_driver);
 
 MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver");
 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
index cd87758abac3154d3c411ed8b3ef9194a461f389..f270bb7bc4564126638200c270882da039219c88 100644 (file)
@@ -266,6 +266,7 @@ static void cpu5wdt_exit(void)
        if (cpu5wdt_device.queue) {
                cpu5wdt_device.queue = 0;
                wait_for_completion(&cpu5wdt_device.stop);
+               del_timer(&cpu5wdt_device.timer);
        }
 
        misc_deregister(&cpu5wdt_misc);
index 8be70d8f26809c0fb0a9e5828a3b7e230d9861c1..367445009c64b98e5361eda0082f01f9db4dd707 100644 (file)
@@ -53,10 +53,6 @@ static const struct {
 
 static void da9052_wdt_release_resources(struct kref *r)
 {
-       struct da9052_wdt_data *driver_data =
-               container_of(r, struct da9052_wdt_data, kref);
-
-       kfree(driver_data);
 }
 
 static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev,
diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c
new file mode 100644 (file)
index 0000000..f5ad105
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * System monitoring driver for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/delay.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define DA9055_DEF_TIMEOUT     4
+#define DA9055_TWDMIN          256
+
+struct da9055_wdt_data {
+       struct watchdog_device wdt;
+       struct da9055 *da9055;
+       struct kref kref;
+};
+
+static const struct {
+       u8 reg_val;
+       int user_time;  /* In seconds */
+} da9055_wdt_maps[] = {
+       { 0, 0 },
+       { 1, 2 },
+       { 2, 4 },
+       { 3, 8 },
+       { 4, 16 },
+       { 5, 32 },
+       { 5, 33 },  /* Actual time  32.768s so included both 32s and 33s */
+       { 6, 65 },
+       { 6, 66 },  /* Actual time 65.536s so include both, 65s and 66s */
+       { 7, 131 },
+};
+
+static int da9055_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                 unsigned int timeout)
+{
+       struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct da9055 *da9055 = driver_data->da9055;
+       int ret, i;
+
+       for (i = 0; i < ARRAY_SIZE(da9055_wdt_maps); i++)
+               if (da9055_wdt_maps[i].user_time == timeout)
+                       break;
+
+       if (i == ARRAY_SIZE(da9055_wdt_maps))
+               ret = -EINVAL;
+       else
+               ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B,
+                                       DA9055_TWDSCALE_MASK,
+                                       da9055_wdt_maps[i].reg_val <<
+                                       DA9055_TWDSCALE_SHIFT);
+       if (ret < 0) {
+               dev_err(da9055->dev,
+                       "Failed to update timescale bit, %d\n", ret);
+               return ret;
+       }
+
+       wdt_dev->timeout = timeout;
+
+       return 0;
+}
+
+static int da9055_wdt_ping(struct watchdog_device *wdt_dev)
+{
+       struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct da9055 *da9055 = driver_data->da9055;
+
+       /*
+        * We have a minimum time for watchdog window called TWDMIN. A write
+        * to the watchdog before this elapsed time will cause an error.
+        */
+       mdelay(DA9055_TWDMIN);
+
+       /* Reset the watchdog timer */
+       return da9055_reg_update(da9055, DA9055_REG_CONTROL_E,
+                                DA9055_WATCHDOG_MASK, 1);
+}
+
+static void da9055_wdt_release_resources(struct kref *r)
+{
+}
+
+static void da9055_wdt_ref(struct watchdog_device *wdt_dev)
+{
+       struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
+
+       kref_get(&driver_data->kref);
+}
+
+static void da9055_wdt_unref(struct watchdog_device *wdt_dev)
+{
+       struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
+
+       kref_put(&driver_data->kref, da9055_wdt_release_resources);
+}
+
+static int da9055_wdt_start(struct watchdog_device *wdt_dev)
+{
+       return da9055_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+}
+
+static int da9055_wdt_stop(struct watchdog_device *wdt_dev)
+{
+       return da9055_wdt_set_timeout(wdt_dev, 0);
+}
+
+static struct watchdog_info da9055_wdt_info = {
+       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity       = "DA9055 Watchdog",
+};
+
+static const struct watchdog_ops da9055_wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = da9055_wdt_start,
+       .stop = da9055_wdt_stop,
+       .ping = da9055_wdt_ping,
+       .set_timeout = da9055_wdt_set_timeout,
+       .ref = da9055_wdt_ref,
+       .unref = da9055_wdt_unref,
+};
+
+static int da9055_wdt_probe(struct platform_device *pdev)
+{
+       struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+       struct da9055_wdt_data *driver_data;
+       struct watchdog_device *da9055_wdt;
+       int ret;
+
+       driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
+                                  GFP_KERNEL);
+       if (!driver_data) {
+               dev_err(da9055->dev, "Failed to allocate watchdog device\n");
+               return -ENOMEM;
+       }
+
+       driver_data->da9055 = da9055;
+
+       da9055_wdt = &driver_data->wdt;
+
+       da9055_wdt->timeout = DA9055_DEF_TIMEOUT;
+       da9055_wdt->info = &da9055_wdt_info;
+       da9055_wdt->ops = &da9055_wdt_ops;
+       watchdog_set_nowayout(da9055_wdt, nowayout);
+       watchdog_set_drvdata(da9055_wdt, driver_data);
+
+       kref_init(&driver_data->kref);
+
+       ret = da9055_wdt_stop(da9055_wdt);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to stop watchdog, %d\n", ret);
+               goto err;
+       }
+
+       dev_set_drvdata(&pdev->dev, driver_data);
+
+       ret = watchdog_register_device(&driver_data->wdt);
+       if (ret != 0)
+               dev_err(da9055->dev, "watchdog_register_device() failed: %d\n",
+                       ret);
+
+err:
+       return ret;
+}
+
+static int da9055_wdt_remove(struct platform_device *pdev)
+{
+       struct da9055_wdt_data *driver_data = dev_get_drvdata(&pdev->dev);
+
+       watchdog_unregister_device(&driver_data->wdt);
+       kref_put(&driver_data->kref, da9055_wdt_release_resources);
+
+       return 0;
+}
+
+static struct platform_driver da9055_wdt_driver = {
+       .probe = da9055_wdt_probe,
+       .remove = da9055_wdt_remove,
+       .driver = {
+               .name   = "da9055-watchdog",
+       },
+};
+
+module_platform_driver(da9055_wdt_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-watchdog");
index 8791879e5181d08ee8218cb9c0a1df20acfe1f8c..e8e87246ea6d9dfe722564ce0199b5b2868363a4 100644 (file)
@@ -208,7 +208,7 @@ static int davinci_wdt_probe(struct platform_device *pdev)
        if (WARN_ON(IS_ERR(wdt_clk)))
                return PTR_ERR(wdt_clk);
 
-       clk_enable(wdt_clk);
+       clk_prepare_enable(wdt_clk);
 
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
@@ -256,16 +256,23 @@ static int davinci_wdt_remove(struct platform_device *pdev)
                wdt_mem = NULL;
        }
 
-       clk_disable(wdt_clk);
+       clk_disable_unprepare(wdt_clk);
        clk_put(wdt_clk);
 
        return 0;
 }
 
+static const struct of_device_id davinci_wdt_of_match[] = {
+       { .compatible = "ti,davinci-wdt", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, davinci_wdt_of_match);
+
 static struct platform_driver platform_wdt_driver = {
        .driver = {
                .name = "watchdog",
                .owner  = THIS_MODULE,
+               .of_match_table = davinci_wdt_of_match,
        },
        .probe = davinci_wdt_probe,
        .remove = davinci_wdt_remove,
index 8717255ec7be07367c9c5c5dd3fc47bf0b301dc6..11796b9b864eb000e3fba1b0b6a94984d8324232 100644 (file)
@@ -39,7 +39,7 @@
 #endif /* CONFIG_HPWDT_NMI_DECODING */
 #include <asm/nmi.h>
 
-#define HPWDT_VERSION                  "1.3.0"
+#define HPWDT_VERSION                  "1.3.1"
 #define SECS_TO_TICKS(secs)            ((secs) * 1000 / 128)
 #define TICKS_TO_SECS(ticks)           ((ticks) * 128 / 1000)
 #define HPWDT_MAX_TIMER                        TICKS_TO_SECS(65535)
index a84eb551ea2742f08ef977ab45a774021a0b71e4..233cfadcb21f55538310f938ff037b0dbd236225 100644 (file)
@@ -80,8 +80,7 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
 
        /* Check it really was our interrupt */
        if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
-               dev_printk(KERN_CRIT, wdt->dev,
-                                       "Triggered - Reboot ignored.\n");
+               dev_crit(wdt->dev, "Triggered - Reboot ignored\n");
                /* Clear the interrupt on the watchdog */
                writel(1, wdt->base + TWD_WDOG_INTSTAT);
                return IRQ_HANDLED;
@@ -123,7 +122,7 @@ static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
 
 static void mpcore_wdt_start(struct mpcore_wdt *wdt)
 {
-       dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+       dev_info(wdt->dev, "enabling watchdog\n");
 
        /* This loads the count register but does NOT start the count yet */
        mpcore_wdt_keepalive(wdt);
@@ -180,8 +179,8 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file)
        if (wdt->expect_close == 42)
                mpcore_wdt_stop(wdt);
        else {
-               dev_printk(KERN_CRIT, wdt->dev,
-                               "unexpected close, not stopping watchdog!\n");
+               dev_crit(wdt->dev,
+                        "unexpected close, not stopping watchdog!\n");
                mpcore_wdt_keepalive(wdt);
        }
        clear_bit(0, &wdt->timer_alive);
@@ -351,9 +350,9 @@ static int mpcore_wdt_probe(struct platform_device *pdev)
                ret = devm_request_irq(wdt->dev, wdt->irq, mpcore_wdt_fire, 0,
                                "mpcore_wdt", wdt);
                if (ret) {
-                       dev_printk(KERN_ERR, wdt->dev,
-                                       "cannot register IRQ%d for watchdog\n",
-                                       wdt->irq);
+                       dev_err(wdt->dev,
+                               "cannot register IRQ%d for watchdog\n",
+                               wdt->irq);
                        return ret;
                }
        }
@@ -365,9 +364,9 @@ static int mpcore_wdt_probe(struct platform_device *pdev)
        mpcore_wdt_miscdev.parent = &pdev->dev;
        ret = misc_register(&mpcore_wdt_miscdev);
        if (ret) {
-               dev_printk(KERN_ERR, wdt->dev,
+               dev_err(wdt->dev,
                        "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+                       WATCHDOG_MINOR, ret);
                return ret;
        }
 
index 3e3ebbc83fafe8ba194470c0da8d9fe862897684..b0e541d022e68a23d6edb8d05bd306d21d291728 100644 (file)
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
-#include <linux/bitops.h>
 #include <linux/io.h>
-#include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_data/omap-wd-timer.h>
 
 #include "omap_wdt.h"
 
-static struct platform_device *omap_wdt_dev;
-
 static unsigned timer_margin;
 module_param(timer_margin, uint, 0);
 MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
 
-static unsigned int wdt_trgr_pattern = 0x1234;
-static DEFINE_SPINLOCK(wdt_lock);
-
 struct omap_wdt_dev {
        void __iomem    *base;          /* physical */
        struct device   *dev;
-       int             omap_wdt_users;
+       bool            omap_wdt_users;
        struct resource *mem;
-       struct miscdevice omap_wdt_miscdev;
+       int             wdt_trgr_pattern;
+       struct mutex    lock;           /* to avoid races with PM */
 };
 
-static void omap_wdt_ping(struct omap_wdt_dev *wdev)
+static void omap_wdt_reload(struct omap_wdt_dev *wdev)
 {
        void __iomem    *base = wdev->base;
 
@@ -74,8 +66,8 @@ static void omap_wdt_ping(struct omap_wdt_dev *wdev)
        while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08)
                cpu_relax();
 
-       wdt_trgr_pattern = ~wdt_trgr_pattern;
-       __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR));
+       wdev->wdt_trgr_pattern = ~wdev->wdt_trgr_pattern;
+       __raw_writel(wdev->wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR));
 
        /* wait for posted write to complete */
        while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08)
@@ -111,18 +103,10 @@ static void omap_wdt_disable(struct omap_wdt_dev *wdev)
                cpu_relax();
 }
 
-static void omap_wdt_adjust_timeout(unsigned new_timeout)
-{
-       if (new_timeout < TIMER_MARGIN_MIN)
-               new_timeout = TIMER_MARGIN_DEFAULT;
-       if (new_timeout > TIMER_MARGIN_MAX)
-               new_timeout = TIMER_MARGIN_MAX;
-       timer_margin = new_timeout;
-}
-
-static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
+static void omap_wdt_set_timer(struct omap_wdt_dev *wdev,
+                                  unsigned int timeout)
 {
-       u32 pre_margin = GET_WLDR_VAL(timer_margin);
+       u32 pre_margin = GET_WLDR_VAL(timeout);
        void __iomem *base = wdev->base;
 
        /* just count up at 32 KHz */
@@ -134,16 +118,14 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
                cpu_relax();
 }
 
-/*
- *     Allow only one task to hold it open
- */
-static int omap_wdt_open(struct inode *inode, struct file *file)
+static int omap_wdt_start(struct watchdog_device *wdog)
 {
-       struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
        void __iomem *base = wdev->base;
 
-       if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
-               return -EBUSY;
+       mutex_lock(&wdev->lock);
+
+       wdev->omap_wdt_users = true;
 
        pm_runtime_get_sync(wdev->dev);
 
@@ -155,223 +137,168 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
        while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
                cpu_relax();
 
-       file->private_data = (void *) wdev;
-
-       omap_wdt_set_timeout(wdev);
-       omap_wdt_ping(wdev); /* trigger loading of new timeout value */
+       omap_wdt_set_timer(wdev, wdog->timeout);
+       omap_wdt_reload(wdev); /* trigger loading of new timeout value */
        omap_wdt_enable(wdev);
 
-       return nonseekable_open(inode, file);
+       mutex_unlock(&wdev->lock);
+
+       return 0;
 }
 
-static int omap_wdt_release(struct inode *inode, struct file *file)
+static int omap_wdt_stop(struct watchdog_device *wdog)
 {
-       struct omap_wdt_dev *wdev = file->private_data;
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
-       /*
-        *      Shut off the timer unless NOWAYOUT is defined.
-        */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+       mutex_lock(&wdev->lock);
        omap_wdt_disable(wdev);
-
        pm_runtime_put_sync(wdev->dev);
-#else
-       pr_crit("Unexpected close, not stopping!\n");
-#endif
-       wdev->omap_wdt_users = 0;
-
+       wdev->omap_wdt_users = false;
+       mutex_unlock(&wdev->lock);
        return 0;
 }
 
-static ssize_t omap_wdt_write(struct file *file, const char __user *data,
-               size_t len, loff_t *ppos)
+static int omap_wdt_ping(struct watchdog_device *wdog)
 {
-       struct omap_wdt_dev *wdev = file->private_data;
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
-       /* Refresh LOAD_TIME. */
-       if (len) {
-               spin_lock(&wdt_lock);
-               omap_wdt_ping(wdev);
-               spin_unlock(&wdt_lock);
-       }
-       return len;
+       mutex_lock(&wdev->lock);
+       omap_wdt_reload(wdev);
+       mutex_unlock(&wdev->lock);
+
+       return 0;
 }
 
-static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
-                                               unsigned long arg)
+static int omap_wdt_set_timeout(struct watchdog_device *wdog,
+                               unsigned int timeout)
 {
-       struct omap_wd_timer_platform_data *pdata;
-       struct omap_wdt_dev *wdev;
-       u32 rs;
-       int new_margin, bs;
-       static const struct watchdog_info ident = {
-               .identity = "OMAP Watchdog",
-               .options = WDIOF_SETTIMEOUT,
-               .firmware_version = 0,
-       };
-
-       wdev = file->private_data;
-       pdata = wdev->dev->platform_data;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user((struct watchdog_info __user *)arg, &ident,
-                               sizeof(ident));
-       case WDIOC_GETSTATUS:
-               return put_user(0, (int __user *)arg);
-       case WDIOC_GETBOOTSTATUS:
-               if (!pdata || !pdata->read_reset_sources)
-                       return put_user(0, (int __user *)arg);
-               rs = pdata->read_reset_sources();
-               bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
-                       WDIOF_CARDRESET : 0;
-               return put_user(bs, (int __user *)arg);
-       case WDIOC_KEEPALIVE:
-               spin_lock(&wdt_lock);
-               omap_wdt_ping(wdev);
-               spin_unlock(&wdt_lock);
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, (int __user *)arg))
-                       return -EFAULT;
-               omap_wdt_adjust_timeout(new_margin);
-
-               spin_lock(&wdt_lock);
-               omap_wdt_disable(wdev);
-               omap_wdt_set_timeout(wdev);
-               omap_wdt_enable(wdev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
-               omap_wdt_ping(wdev);
-               spin_unlock(&wdt_lock);
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(timer_margin, (int __user *)arg);
-       default:
-               return -ENOTTY;
-       }
+       mutex_lock(&wdev->lock);
+       omap_wdt_disable(wdev);
+       omap_wdt_set_timer(wdev, timeout);
+       omap_wdt_enable(wdev);
+       omap_wdt_reload(wdev);
+       wdog->timeout = timeout;
+       mutex_unlock(&wdev->lock);
+
+       return 0;
 }
 
-static const struct file_operations omap_wdt_fops = {
-       .owner = THIS_MODULE,
-       .write = omap_wdt_write,
-       .unlocked_ioctl = omap_wdt_ioctl,
-       .open = omap_wdt_open,
-       .release = omap_wdt_release,
-       .llseek = no_llseek,
+static const struct watchdog_info omap_wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = "OMAP Watchdog",
+};
+
+static const struct watchdog_ops omap_wdt_ops = {
+       .owner          = THIS_MODULE,
+       .start          = omap_wdt_start,
+       .stop           = omap_wdt_stop,
+       .ping           = omap_wdt_ping,
+       .set_timeout    = omap_wdt_set_timeout,
 };
 
 static int omap_wdt_probe(struct platform_device *pdev)
 {
+       struct omap_wd_timer_platform_data *pdata = pdev->dev.platform_data;
+       bool nowayout = WATCHDOG_NOWAYOUT;
+       struct watchdog_device *omap_wdt;
        struct resource *res, *mem;
        struct omap_wdt_dev *wdev;
+       u32 rs;
        int ret;
 
+       omap_wdt = devm_kzalloc(&pdev->dev, sizeof(*omap_wdt), GFP_KERNEL);
+       if (!omap_wdt)
+               return -ENOMEM;
+
        /* reserve static register mappings */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENOENT;
-               goto err_get_resource;
-       }
+       if (!res)
+               return -ENOENT;
 
-       if (omap_wdt_dev) {
-               ret = -EBUSY;
-               goto err_busy;
-       }
+       mem = devm_request_mem_region(&pdev->dev, res->start,
+                                     resource_size(res), pdev->name);
+       if (!mem)
+               return -EBUSY;
 
-       mem = request_mem_region(res->start, resource_size(res), pdev->name);
-       if (!mem) {
-               ret = -EBUSY;
-               goto err_busy;
-       }
+       wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
+       if (!wdev)
+               return -ENOMEM;
 
-       wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL);
-       if (!wdev) {
-               ret = -ENOMEM;
-               goto err_kzalloc;
-       }
+       wdev->omap_wdt_users    = false;
+       wdev->mem               = mem;
+       wdev->dev               = &pdev->dev;
+       wdev->wdt_trgr_pattern  = 0x1234;
+       mutex_init(&wdev->lock);
 
-       wdev->omap_wdt_users = 0;
-       wdev->mem = mem;
-       wdev->dev = &pdev->dev;
+       wdev->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+       if (!wdev->base)
+               return -ENOMEM;
 
-       wdev->base = ioremap(res->start, resource_size(res));
-       if (!wdev->base) {
-               ret = -ENOMEM;
-               goto err_ioremap;
-       }
+       omap_wdt->info        = &omap_wdt_info;
+       omap_wdt->ops         = &omap_wdt_ops;
+       omap_wdt->min_timeout = TIMER_MARGIN_MIN;
+       omap_wdt->max_timeout = TIMER_MARGIN_MAX;
+
+       if (timer_margin >= TIMER_MARGIN_MIN &&
+           timer_margin <= TIMER_MARGIN_MAX)
+               omap_wdt->timeout = timer_margin;
+       else
+               omap_wdt->timeout = TIMER_MARGIN_DEFAULT;
 
-       platform_set_drvdata(pdev, wdev);
+       watchdog_set_drvdata(omap_wdt, wdev);
+       watchdog_set_nowayout(omap_wdt, nowayout);
+
+       platform_set_drvdata(pdev, omap_wdt);
 
        pm_runtime_enable(wdev->dev);
        pm_runtime_get_sync(wdev->dev);
 
-       omap_wdt_disable(wdev);
-       omap_wdt_adjust_timeout(timer_margin);
+       if (pdata && pdata->read_reset_sources)
+               rs = pdata->read_reset_sources();
+       else
+               rs = 0;
+       omap_wdt->bootstatus = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
+                               WDIOF_CARDRESET : 0;
 
-       wdev->omap_wdt_miscdev.parent = &pdev->dev;
-       wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR;
-       wdev->omap_wdt_miscdev.name = "watchdog";
-       wdev->omap_wdt_miscdev.fops = &omap_wdt_fops;
+       omap_wdt_disable(wdev);
 
-       ret = misc_register(&(wdev->omap_wdt_miscdev));
-       if (ret)
-               goto err_misc;
+       ret = watchdog_register_device(omap_wdt);
+       if (ret) {
+               pm_runtime_disable(wdev->dev);
+               return ret;
+       }
 
        pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n",
                __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
-               timer_margin);
+               omap_wdt->timeout);
 
        pm_runtime_put_sync(wdev->dev);
 
-       omap_wdt_dev = pdev;
-
        return 0;
-
-err_misc:
-       pm_runtime_disable(wdev->dev);
-       platform_set_drvdata(pdev, NULL);
-       iounmap(wdev->base);
-
-err_ioremap:
-       wdev->base = NULL;
-       kfree(wdev);
-
-err_kzalloc:
-       release_mem_region(res->start, resource_size(res));
-
-err_busy:
-err_get_resource:
-
-       return ret;
 }
 
 static void omap_wdt_shutdown(struct platform_device *pdev)
 {
-       struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+       struct watchdog_device *wdog = platform_get_drvdata(pdev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
+       mutex_lock(&wdev->lock);
        if (wdev->omap_wdt_users) {
                omap_wdt_disable(wdev);
                pm_runtime_put_sync(wdev->dev);
        }
+       mutex_unlock(&wdev->lock);
 }
 
 static int omap_wdt_remove(struct platform_device *pdev)
 {
-       struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct watchdog_device *wdog = platform_get_drvdata(pdev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
        pm_runtime_disable(wdev->dev);
-       if (!res)
-               return -ENOENT;
-
-       misc_deregister(&(wdev->omap_wdt_miscdev));
-       release_mem_region(res->start, resource_size(res));
-       platform_set_drvdata(pdev, NULL);
-
-       iounmap(wdev->base);
-
-       kfree(wdev);
-       omap_wdt_dev = NULL;
+       watchdog_unregister_device(wdog);
 
        return 0;
 }
@@ -386,25 +313,31 @@ static int omap_wdt_remove(struct platform_device *pdev)
 
 static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+       struct watchdog_device *wdog = platform_get_drvdata(pdev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
+       mutex_lock(&wdev->lock);
        if (wdev->omap_wdt_users) {
                omap_wdt_disable(wdev);
                pm_runtime_put_sync(wdev->dev);
        }
+       mutex_unlock(&wdev->lock);
 
        return 0;
 }
 
 static int omap_wdt_resume(struct platform_device *pdev)
 {
-       struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+       struct watchdog_device *wdog = platform_get_drvdata(pdev);
+       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
 
+       mutex_lock(&wdev->lock);
        if (wdev->omap_wdt_users) {
                pm_runtime_get_sync(wdev->dev);
                omap_wdt_enable(wdev);
-               omap_wdt_ping(wdev);
+               omap_wdt_reload(wdev);
        }
+       mutex_unlock(&wdev->lock);
 
        return 0;
 }
@@ -437,5 +370,4 @@ module_platform_driver(omap_wdt_driver);
 
 MODULE_AUTHOR("George G. Davis");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS("platform:omap_wdt");
index 0478b001b1efbb1621613e07b438fa4bbad7cf32..7c18b3bffcf74ab0845fb8796659d297c618e6ed 100644 (file)
@@ -156,6 +156,8 @@ static int orion_wdt_probe(struct platform_device *pdev)
        wdt_tclk = clk_get_rate(clk);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
        wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!wdt_reg)
                return -ENOMEM;
index b0dab10fc6a5122a2947addcf78238a30476a5a9..27bcd4e2c4a4f3b2063aa2f38a4fc6927f0e565d 100644 (file)
@@ -354,7 +354,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
                goto err_map;
        }
 
-       clk_enable(wdt_clock);
+       clk_prepare_enable(wdt_clock);
 
        ret = s3c2410wdt_cpufreq_register();
        if (ret < 0) {
@@ -421,7 +421,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
        s3c2410wdt_cpufreq_deregister();
 
  err_clk:
-       clk_disable(wdt_clock);
+       clk_disable_unprepare(wdt_clock);
        clk_put(wdt_clock);
        wdt_clock = NULL;
 
@@ -445,7 +445,7 @@ static int s3c2410wdt_remove(struct platform_device *dev)
 
        s3c2410wdt_cpufreq_deregister();
 
-       clk_disable(wdt_clock);
+       clk_disable_unprepare(wdt_clock);
        clk_put(wdt_clock);
        wdt_clock = NULL;
 
index b3876812ff075327a57cb33d55f7c9c684fa9dcc..2b0e000d4377de2714cbadcfb557c32c33a16321 100644 (file)
@@ -13,7 +13,9 @@
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  *
- *     See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide"
+ *     See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide",
+ *         AMD Publication 45482 "AMD SB800-Series Southbridges Register
+ *                                                           Reference Guide"
  */
 
 /*
 #include "sp5100_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.01"
+#define TCO_VERSION "0.03"
 #define TCO_MODULE_NAME "SP5100 TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 
 /* internal variables */
 static u32 tcobase_phys;
+static u32 resbase_phys;
+static u32 tco_wdt_fired;
 static void __iomem *tcobase;
 static unsigned int pm_iobase;
 static DEFINE_SPINLOCK(tco_lock);      /* Guards the hardware */
 static unsigned long timer_alive;
 static char tco_expect_close;
 static struct pci_dev *sp5100_tco_pci;
+static struct resource wdt_res = {
+       .name = "Watchdog Timer",
+       .flags = IORESOURCE_MEM,
+};
 
 /* the watchdog platform device */
 static struct platform_device *sp5100_tco_platform_device;
@@ -64,9 +72,15 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+static unsigned int force_addr;
+module_param(force_addr, uint, 0);
+MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address."
+               " ONLY USE THIS PARAMETER IF YOU REALLY KNOW"
+               " WHAT YOU ARE DOING (default=none)");
+
 /*
  * Some TCO specific functions
  */
@@ -122,6 +136,79 @@ static int tco_timer_set_heartbeat(int t)
        return 0;
 }
 
+static void tco_timer_enable(void)
+{
+       int val;
+
+       if (sp5100_tco_pci->revision >= 0x40) {
+               /* For SB800 or later */
+               /* Set the Watchdog timer resolution to 1 sec */
+               outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG);
+               val = inb(SB800_IO_PM_DATA_REG);
+               val |= SB800_PM_WATCHDOG_SECOND_RES;
+               outb(val, SB800_IO_PM_DATA_REG);
+
+               /* Enable watchdog decode bit and watchdog timer */
+               outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
+               val = inb(SB800_IO_PM_DATA_REG);
+               val |= SB800_PCI_WATCHDOG_DECODE_EN;
+               val &= ~SB800_PM_WATCHDOG_DISABLE;
+               outb(val, SB800_IO_PM_DATA_REG);
+       } else {
+               /* For SP5100 or SB7x0 */
+               /* Enable watchdog decode bit */
+               pci_read_config_dword(sp5100_tco_pci,
+                                     SP5100_PCI_WATCHDOG_MISC_REG,
+                                     &val);
+
+               val |= SP5100_PCI_WATCHDOG_DECODE_EN;
+
+               pci_write_config_dword(sp5100_tco_pci,
+                                      SP5100_PCI_WATCHDOG_MISC_REG,
+                                      val);
+
+               /* Enable Watchdog timer and set the resolution to 1 sec */
+               outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
+               val = inb(SP5100_IO_PM_DATA_REG);
+               val |= SP5100_PM_WATCHDOG_SECOND_RES;
+               val &= ~SP5100_PM_WATCHDOG_DISABLE;
+               outb(val, SP5100_IO_PM_DATA_REG);
+       }
+}
+
+static void tco_timer_disable(void)
+{
+       int val;
+
+       if (sp5100_tco_pci->revision >= 0x40) {
+               /* For SB800 or later */
+               /* Enable watchdog decode bit and Disable watchdog timer */
+               outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
+               val = inb(SB800_IO_PM_DATA_REG);
+               val |= SB800_PCI_WATCHDOG_DECODE_EN;
+               val |= SB800_PM_WATCHDOG_DISABLE;
+               outb(val, SB800_IO_PM_DATA_REG);
+       } else {
+               /* For SP5100 or SB7x0 */
+               /* Enable watchdog decode bit */
+               pci_read_config_dword(sp5100_tco_pci,
+                                     SP5100_PCI_WATCHDOG_MISC_REG,
+                                     &val);
+
+               val |= SP5100_PCI_WATCHDOG_DECODE_EN;
+
+               pci_write_config_dword(sp5100_tco_pci,
+                                      SP5100_PCI_WATCHDOG_MISC_REG,
+                                      val);
+
+               /* Disable Watchdog timer */
+               outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
+               val = inb(SP5100_IO_PM_DATA_REG);
+               val |= SP5100_PM_WATCHDOG_DISABLE;
+               outb(val, SP5100_IO_PM_DATA_REG);
+       }
+}
+
 /*
  *     /dev/watchdog handling
  */
@@ -270,11 +357,12 @@ MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
 /*
  * Init & exit routines
  */
-
 static unsigned char sp5100_tco_setupdevice(void)
 {
        struct pci_dev *dev = NULL;
+       const char *dev_name = NULL;
        u32 val;
+       u32 index_reg, data_reg, base_addr;
 
        /* Match the PCI device */
        for_each_pci_dev(dev) {
@@ -287,29 +375,160 @@ static unsigned char sp5100_tco_setupdevice(void)
        if (!sp5100_tco_pci)
                return 0;
 
+       pr_info("PCI Revision ID: 0x%x\n", sp5100_tco_pci->revision);
+
+       /*
+        * Determine type of southbridge chipset.
+        */
+       if (sp5100_tco_pci->revision >= 0x40) {
+               dev_name = SB800_DEVNAME;
+               index_reg = SB800_IO_PM_INDEX_REG;
+               data_reg = SB800_IO_PM_DATA_REG;
+               base_addr = SB800_PM_WATCHDOG_BASE;
+       } else {
+               dev_name = SP5100_DEVNAME;
+               index_reg = SP5100_IO_PM_INDEX_REG;
+               data_reg = SP5100_IO_PM_DATA_REG;
+               base_addr = SP5100_PM_WATCHDOG_BASE;
+       }
+
        /* Request the IO ports used by this driver */
        pm_iobase = SP5100_IO_PM_INDEX_REG;
-       if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
+       if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, dev_name)) {
                pr_err("I/O address 0x%04x already in use\n", pm_iobase);
                goto exit;
        }
 
-       /* Find the watchdog base address. */
-       outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG);
-       val = inb(SP5100_IO_PM_DATA_REG);
-       outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG);
-       val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
-       outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG);
-       val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
-       outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG);
-       /* Low three bits of BASE0 are reserved. */
-       val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
+       /*
+        * First, Find the watchdog timer MMIO address from indirect I/O.
+        */
+       outb(base_addr+3, index_reg);
+       val = inb(data_reg);
+       outb(base_addr+2, index_reg);
+       val = val << 8 | inb(data_reg);
+       outb(base_addr+1, index_reg);
+       val = val << 8 | inb(data_reg);
+       outb(base_addr+0, index_reg);
+       /* Low three bits of BASE are reserved */
+       val = val << 8 | (inb(data_reg) & 0xf8);
+
+       pr_debug("Got 0x%04x from indirect I/O\n", val);
+
+       /* Check MMIO address conflict */
+       if (request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
+                                                               dev_name))
+               goto setup_wdt;
+       else
+               pr_debug("MMIO address 0x%04x already in use\n", val);
+
+       /*
+        * Secondly, Find the watchdog timer MMIO address
+        * from SBResource_MMIO register.
+        */
+       if (sp5100_tco_pci->revision >= 0x40) {
+               /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
+               outb(SB800_PM_ACPI_MMIO_EN+3, SB800_IO_PM_INDEX_REG);
+               val = inb(SB800_IO_PM_DATA_REG);
+               outb(SB800_PM_ACPI_MMIO_EN+2, SB800_IO_PM_INDEX_REG);
+               val = val << 8 | inb(SB800_IO_PM_DATA_REG);
+               outb(SB800_PM_ACPI_MMIO_EN+1, SB800_IO_PM_INDEX_REG);
+               val = val << 8 | inb(SB800_IO_PM_DATA_REG);
+               outb(SB800_PM_ACPI_MMIO_EN+0, SB800_IO_PM_INDEX_REG);
+               val = val << 8 | inb(SB800_IO_PM_DATA_REG);
+       } else {
+               /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
+               pci_read_config_dword(sp5100_tco_pci,
+                                     SP5100_SB_RESOURCE_MMIO_BASE, &val);
+       }
+
+       /* The SBResource_MMIO is enabled and mapped memory space? */
+       if ((val & (SB800_ACPI_MMIO_DECODE_EN | SB800_ACPI_MMIO_SEL)) ==
+                                                 SB800_ACPI_MMIO_DECODE_EN) {
+               /* Clear unnecessary the low twelve bits */
+               val &= ~0xFFF;
+               /* Add the Watchdog Timer offset to base address. */
+               val += SB800_PM_WDT_MMIO_OFFSET;
+               /* Check MMIO address conflict */
+               if (request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
+                                                                  dev_name)) {
+                       pr_debug("Got 0x%04x from SBResource_MMIO register\n",
+                               val);
+                       goto setup_wdt;
+               } else
+                       pr_debug("MMIO address 0x%04x already in use\n", val);
+       } else
+               pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val);
+
+       /*
+        * Lastly re-programming the watchdog timer MMIO address,
+        * This method is a last resort...
+        *
+        * Before re-programming, to ensure that the watchdog timer
+        * is disabled, disable the watchdog timer.
+        */
+       tco_timer_disable();
+
+       if (force_addr) {
+               /*
+                * Force the use of watchdog timer MMIO address, and aligned to
+                * 8byte boundary.
+                */
+               force_addr &= ~0x7;
+               val = force_addr;
+
+               pr_info("Force the use of 0x%04x as MMIO address\n", val);
+       } else {
+               /*
+                * Get empty slot into the resource tree for watchdog timer.
+                */
+               if (allocate_resource(&iomem_resource,
+                                     &wdt_res,
+                                     SP5100_WDT_MEM_MAP_SIZE,
+                                     0xf0000000,
+                                     0xfffffff8,
+                                     0x8,
+                                     NULL,
+                                     NULL)) {
+                       pr_err("MMIO allocation failed\n");
+                       goto unreg_region;
+               }
+
+               val = resbase_phys = wdt_res.start;
+               pr_debug("Got 0x%04x from resource tree\n", val);
+       }
+
+       /* Restore to the low three bits, if chipset is SB8x0(or later) */
+       if (sp5100_tco_pci->revision >= 0x40) {
+               u8 reserved_bit;
+               reserved_bit = inb(base_addr) & 0x7;
+               val |= (u32)reserved_bit;
+       }
+
+       /* Re-programming the watchdog timer base address */
+       outb(base_addr+0, index_reg);
+       /* Low three bits of BASE are reserved */
+       outb((val >>  0) & 0xf8, data_reg);
+       outb(base_addr+1, index_reg);
+       outb((val >>  8) & 0xff, data_reg);
+       outb(base_addr+2, index_reg);
+       outb((val >> 16) & 0xff, data_reg);
+       outb(base_addr+3, index_reg);
+       outb((val >> 24) & 0xff, data_reg);
+
+       /*
+        * Clear unnecessary the low three bits,
+        * if chipset is SB8x0(or later)
+        */
+       if (sp5100_tco_pci->revision >= 0x40)
+               val &= ~0x7;
 
        if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
-                                                               "SP5100 TCO")) {
-               pr_err("mmio address 0x%04x already in use\n", val);
-               goto unreg_region;
+                                                                  dev_name)) {
+               pr_err("MMIO address 0x%04x already in use\n", val);
+               goto unreg_resource;
        }
+
+setup_wdt:
        tcobase_phys = val;
 
        tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
@@ -318,26 +537,18 @@ static unsigned char sp5100_tco_setupdevice(void)
                goto unreg_mem_region;
        }
 
-       /* Enable watchdog decode bit */
-       pci_read_config_dword(sp5100_tco_pci,
-                             SP5100_PCI_WATCHDOG_MISC_REG,
-                             &val);
-
-       val |= SP5100_PCI_WATCHDOG_DECODE_EN;
+       pr_info("Using 0x%04x for watchdog MMIO address\n", val);
 
-       pci_write_config_dword(sp5100_tco_pci,
-                              SP5100_PCI_WATCHDOG_MISC_REG,
-                              val);
+       /* Setup the watchdog timer */
+       tco_timer_enable();
 
-       /* Enable Watchdog timer and set the resolution to 1 sec. */
-       outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
-       val = inb(SP5100_IO_PM_DATA_REG);
-       val |= SP5100_PM_WATCHDOG_SECOND_RES;
-       val &= ~SP5100_PM_WATCHDOG_DISABLE;
-       outb(val, SP5100_IO_PM_DATA_REG);
-
-       /* Check that the watchdog action is set to reset the system. */
+       /* Check that the watchdog action is set to reset the system */
        val = readl(SP5100_WDT_CONTROL(tcobase));
+       /*
+        * Save WatchDogFired status, because WatchDogFired flag is
+        * cleared here.
+        */
+       tco_wdt_fired = val & SP5100_PM_WATCHDOG_FIRED;
        val &= ~SP5100_PM_WATCHDOG_ACTION_RESET;
        writel(val, SP5100_WDT_CONTROL(tcobase));
 
@@ -355,6 +566,9 @@ static unsigned char sp5100_tco_setupdevice(void)
 
 unreg_mem_region:
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
+unreg_resource:
+       if (resbase_phys)
+               release_resource(&wdt_res);
 unreg_region:
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 exit:
@@ -364,23 +578,18 @@ exit:
 static int sp5100_tco_init(struct platform_device *dev)
 {
        int ret;
-       u32 val;
+       char addr_str[16];
 
-       /* Check whether or not the hardware watchdog is there. If found, then
+       /*
+        * Check whether or not the hardware watchdog is there. If found, then
         * set it up.
         */
        if (!sp5100_tco_setupdevice())
                return -ENODEV;
 
        /* Check to see if last reboot was due to watchdog timeout */
-       pr_info("Watchdog reboot %sdetected\n",
-               readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
-               "" : "not ");
-
-       /* Clear out the old status */
-       val = readl(SP5100_WDT_CONTROL(tcobase));
-       val &= ~SP5100_PM_WATCHDOG_FIRED;
-       writel(val, SP5100_WDT_CONTROL(tcobase));
+       pr_info("Last reboot was %striggered by watchdog.\n",
+               tco_wdt_fired ? "" : "not ");
 
        /*
         * Check that the heartbeat value is within it's range.
@@ -400,14 +609,24 @@ static int sp5100_tco_init(struct platform_device *dev)
 
        clear_bit(0, &timer_alive);
 
-       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
-               tcobase, heartbeat, nowayout);
+       /* Show module parameters */
+       if (force_addr == tcobase_phys)
+               /* The force_addr is vaild */
+               sprintf(addr_str, "0x%04x", force_addr);
+       else
+               strcpy(addr_str, "none");
+
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d, "
+               "force_addr=%s)\n",
+               tcobase, heartbeat, nowayout, addr_str);
 
        return 0;
 
 exit:
        iounmap(tcobase);
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
+       if (resbase_phys)
+               release_resource(&wdt_res);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
        return ret;
 }
@@ -422,6 +641,8 @@ static void sp5100_tco_cleanup(void)
        misc_deregister(&sp5100_tco_miscdev);
        iounmap(tcobase);
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
+       if (resbase_phys)
+               release_resource(&wdt_res);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
@@ -451,7 +672,7 @@ static int __init sp5100_tco_init_module(void)
 {
        int err;
 
-       pr_info("SP5100 TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
+       pr_info("SP5100/SB800 TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
 
        err = platform_driver_register(&sp5100_tco_driver);
        if (err)
@@ -475,13 +696,13 @@ static void __exit sp5100_tco_cleanup_module(void)
 {
        platform_device_unregister(sp5100_tco_platform_device);
        platform_driver_unregister(&sp5100_tco_driver);
-       pr_info("SP5100 TCO Watchdog Module Unloaded\n");
+       pr_info("SP5100/SB800 TCO Watchdog Module Unloaded\n");
 }
 
 module_init(sp5100_tco_init_module);
 module_exit(sp5100_tco_cleanup_module);
 
 MODULE_AUTHOR("Priyanka Gupta");
-MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset");
+MODULE_DESCRIPTION("TCO timer driver for SP5100/SB800 chipset");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index a5a16cc90a340b3fe29d73f7ad389ac58519077a..71594a0c14b735f56decde5e1ac5e01543fbda6c 100644 (file)
@@ -9,33 +9,57 @@
 /*
  * Some address definitions for the Watchdog
  */
-
 #define SP5100_WDT_MEM_MAP_SIZE                0x08
 #define SP5100_WDT_CONTROL(base)       ((base) + 0x00) /* Watchdog Control */
 #define SP5100_WDT_COUNT(base)         ((base) + 0x04) /* Watchdog Count */
 
-#define SP5100_WDT_START_STOP_BIT      1
+#define SP5100_WDT_START_STOP_BIT      (1 << 0)
 #define SP5100_WDT_TRIGGER_BIT         (1 << 7)
 
-#define SP5100_PCI_WATCHDOG_MISC_REG   0x41
-#define SP5100_PCI_WATCHDOG_DECODE_EN  (1 << 3)
-
 #define SP5100_PM_IOPORTS_SIZE         0x02
 
-/* These two IO registers are hardcoded and there doesn't seem to be a way to
+/*
+ * These two IO registers are hardcoded and there doesn't seem to be a way to
  * read them from a register.
  */
+
+/*  For SP5100/SB7x0 chipset */
 #define SP5100_IO_PM_INDEX_REG         0xCD6
 #define SP5100_IO_PM_DATA_REG          0xCD7
 
+#define SP5100_SB_RESOURCE_MMIO_BASE   0x9C
+
 #define SP5100_PM_WATCHDOG_CONTROL     0x69
-#define SP5100_PM_WATCHDOG_BASE0       0x6C
-#define SP5100_PM_WATCHDOG_BASE1       0x6D
-#define SP5100_PM_WATCHDOG_BASE2       0x6E
-#define SP5100_PM_WATCHDOG_BASE3       0x6F
+#define SP5100_PM_WATCHDOG_BASE                0x6C
 
 #define SP5100_PM_WATCHDOG_FIRED       (1 << 1)
 #define SP5100_PM_WATCHDOG_ACTION_RESET        (1 << 2)
 
-#define SP5100_PM_WATCHDOG_DISABLE     1
+#define SP5100_PCI_WATCHDOG_MISC_REG   0x41
+#define SP5100_PCI_WATCHDOG_DECODE_EN  (1 << 3)
+
+#define SP5100_PM_WATCHDOG_DISABLE     (1 << 0)
 #define SP5100_PM_WATCHDOG_SECOND_RES  (3 << 1)
+
+#define SP5100_DEVNAME                 "SP5100 TCO"
+
+
+/*  For SB8x0(or later) chipset */
+#define SB800_IO_PM_INDEX_REG          0xCD6
+#define SB800_IO_PM_DATA_REG           0xCD7
+
+#define SB800_PM_ACPI_MMIO_EN          0x24
+#define SB800_PM_WATCHDOG_CONTROL      0x48
+#define SB800_PM_WATCHDOG_BASE         0x48
+#define SB800_PM_WATCHDOG_CONFIG       0x4C
+
+#define SB800_PCI_WATCHDOG_DECODE_EN   (1 << 0)
+#define SB800_PM_WATCHDOG_DISABLE      (1 << 2)
+#define SB800_PM_WATCHDOG_SECOND_RES   (3 << 0)
+#define SB800_ACPI_MMIO_DECODE_EN      (1 << 0)
+#define SB800_ACPI_MMIO_SEL            (1 << 2)
+
+
+#define SB800_PM_WDT_MMIO_OFFSET       0xB00
+
+#define SB800_DEVNAME                  "SB800 TCO"
index 76c73cbf00407a89e0176a3d69782988687d3f6e..8872642505c0a71a027ccbce25d2e9f3eebe468a 100644 (file)
@@ -130,16 +130,10 @@ static int wdt_config(struct watchdog_device *wdd, bool ping)
        int ret;
 
        if (!ping) {
-               ret = clk_prepare(wdt->clk);
-               if (ret) {
-                       dev_err(&wdt->adev->dev, "clock prepare fail");
-                       return ret;
-               }
 
-               ret = clk_enable(wdt->clk);
+               ret = clk_prepare_enable(wdt->clk);
                if (ret) {
                        dev_err(&wdt->adev->dev, "clock enable fail");
-                       clk_unprepare(wdt->clk);
                        return ret;
                }
        }
@@ -190,8 +184,7 @@ static int wdt_disable(struct watchdog_device *wdd)
        readl_relaxed(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 
-       clk_disable(wdt->clk);
-       clk_unprepare(wdt->clk);
+       clk_disable_unprepare(wdt->clk);
 
        return 0;
 }
index 9f54b1da7185ecf535b401f6daeb238c0a6e0eb7..0f03106f7516ab8a6d1198b1f4b4dd31b06e09cc 100644 (file)
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
 #include <linux/i2c/twl.h>
 
 #define TWL4030_WATCHDOG_CFG_REG_OFFS  0x3
 
-#define TWL4030_WDT_STATE_OPEN         0x1
-#define TWL4030_WDT_STATE_ACTIVE       0x8
-
-static struct platform_device *twl4030_wdt_dev;
-
-struct twl4030_wdt {
-       struct miscdevice       miscdev;
-       int                     timer_margin;
-       unsigned long           state;
-};
-
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
@@ -49,175 +35,75 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
 
 static int twl4030_wdt_write(unsigned char val)
 {
-       return twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
+       return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, val,
                                        TWL4030_WATCHDOG_CFG_REG_OFFS);
 }
 
-static int twl4030_wdt_enable(struct twl4030_wdt *wdt)
+static int twl4030_wdt_start(struct watchdog_device *wdt)
 {
-       return twl4030_wdt_write(wdt->timer_margin + 1);
+       return twl4030_wdt_write(wdt->timeout + 1);
 }
 
-static int twl4030_wdt_disable(struct twl4030_wdt *wdt)
+static int twl4030_wdt_stop(struct watchdog_device *wdt)
 {
        return twl4030_wdt_write(0);
 }
 
-static int twl4030_wdt_set_timeout(struct twl4030_wdt *wdt, int timeout)
-{
-       if (timeout < 0 || timeout > 30) {
-               dev_warn(wdt->miscdev.parent,
-                       "Timeout can only be in the range [0-30] seconds");
-               return -EINVAL;
-       }
-       wdt->timer_margin = timeout;
-       return twl4030_wdt_enable(wdt);
-}
-
-static ssize_t twl4030_wdt_write_fop(struct file *file,
-               const char __user *data, size_t len, loff_t *ppos)
-{
-       struct twl4030_wdt *wdt = file->private_data;
-
-       if (len)
-               twl4030_wdt_enable(wdt);
-
-       return len;
-}
-
-static long twl4030_wdt_ioctl(struct file *file,
-               unsigned int cmd, unsigned long arg)
+static int twl4030_wdt_set_timeout(struct watchdog_device *wdt,
+                                  unsigned int timeout)
 {
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-       struct twl4030_wdt *wdt = file->private_data;
-
-       static const struct watchdog_info twl4030_wd_ident = {
-               .identity = "TWL4030 Watchdog",
-               .options = WDIOF_SETTIMEOUT,
-               .firmware_version = 0,
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &twl4030_wd_ident,
-                               sizeof(twl4030_wd_ident)) ? -EFAULT : 0;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               twl4030_wdt_enable(wdt);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, p))
-                       return -EFAULT;
-               if (twl4030_wdt_set_timeout(wdt, new_margin))
-                       return -EINVAL;
-               return put_user(wdt->timer_margin, p);
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(wdt->timer_margin, p);
-
-       default:
-               return -ENOTTY;
-       }
-
+       wdt->timeout = timeout;
        return 0;
 }
 
-static int twl4030_wdt_open(struct inode *inode, struct file *file)
-{
-       struct twl4030_wdt *wdt = platform_get_drvdata(twl4030_wdt_dev);
-
-       /* /dev/watchdog can only be opened once */
-       if (test_and_set_bit(0, &wdt->state))
-               return -EBUSY;
-
-       wdt->state |= TWL4030_WDT_STATE_ACTIVE;
-       file->private_data = (void *) wdt;
-
-       twl4030_wdt_enable(wdt);
-       return nonseekable_open(inode, file);
-}
-
-static int twl4030_wdt_release(struct inode *inode, struct file *file)
-{
-       struct twl4030_wdt *wdt = file->private_data;
-       if (nowayout) {
-               dev_alert(wdt->miscdev.parent,
-                      "Unexpected close, watchdog still running!\n");
-               twl4030_wdt_enable(wdt);
-       } else {
-               if (twl4030_wdt_disable(wdt))
-                       return -EFAULT;
-               wdt->state &= ~TWL4030_WDT_STATE_ACTIVE;
-       }
-
-       clear_bit(0, &wdt->state);
-       return 0;
-}
+static const struct watchdog_info twl4030_wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = "TWL4030 Watchdog",
+};
 
-static const struct file_operations twl4030_wdt_fops = {
+static const struct watchdog_ops twl4030_wdt_ops = {
        .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .open           = twl4030_wdt_open,
-       .release        = twl4030_wdt_release,
-       .unlocked_ioctl = twl4030_wdt_ioctl,
-       .write          = twl4030_wdt_write_fop,
+       .start          = twl4030_wdt_start,
+       .stop           = twl4030_wdt_stop,
+       .set_timeout    = twl4030_wdt_set_timeout,
 };
 
 static int twl4030_wdt_probe(struct platform_device *pdev)
 {
        int ret = 0;
-       struct twl4030_wdt *wdt;
+       struct watchdog_device *wdt;
 
-       wdt = kzalloc(sizeof(struct twl4030_wdt), GFP_KERNEL);
+       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
        if (!wdt)
                return -ENOMEM;
 
-       wdt->state              = 0;
-       wdt->timer_margin       = 30;
-       wdt->miscdev.parent     = &pdev->dev;
-       wdt->miscdev.fops       = &twl4030_wdt_fops;
-       wdt->miscdev.minor      = WATCHDOG_MINOR;
-       wdt->miscdev.name       = "watchdog";
+       wdt->info               = &twl4030_wdt_info;
+       wdt->ops                = &twl4030_wdt_ops;
+       wdt->status             = 0;
+       wdt->timeout            = 30;
+       wdt->min_timeout        = 1;
+       wdt->max_timeout        = 30;
 
+       watchdog_set_nowayout(wdt, nowayout);
        platform_set_drvdata(pdev, wdt);
 
-       twl4030_wdt_dev = pdev;
-
-       twl4030_wdt_disable(wdt);
+       twl4030_wdt_stop(wdt);
 
-       ret = misc_register(&wdt->miscdev);
+       ret = watchdog_register_device(wdt);
        if (ret) {
-               dev_err(wdt->miscdev.parent,
-                       "Failed to register misc device\n");
                platform_set_drvdata(pdev, NULL);
-               kfree(wdt);
-               twl4030_wdt_dev = NULL;
                return ret;
        }
+
        return 0;
 }
 
 static int twl4030_wdt_remove(struct platform_device *pdev)
 {
-       struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
-
-       if (wdt->state & TWL4030_WDT_STATE_ACTIVE)
-               if (twl4030_wdt_disable(wdt))
-                       return -EFAULT;
-
-       wdt->state &= ~TWL4030_WDT_STATE_ACTIVE;
-       misc_deregister(&wdt->miscdev);
+       struct watchdog_device *wdt = platform_get_drvdata(pdev);
 
+       watchdog_unregister_device(wdt);
        platform_set_drvdata(pdev, NULL);
-       kfree(wdt);
-       twl4030_wdt_dev = NULL;
 
        return 0;
 }
@@ -225,18 +111,18 @@ static int twl4030_wdt_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int twl4030_wdt_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
-       if (wdt->state & TWL4030_WDT_STATE_ACTIVE)
-               return twl4030_wdt_disable(wdt);
+       struct watchdog_device *wdt = platform_get_drvdata(pdev);
+       if (watchdog_active(wdt))
+               return twl4030_wdt_stop(wdt);
 
        return 0;
 }
 
 static int twl4030_wdt_resume(struct platform_device *pdev)
 {
-       struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
-       if (wdt->state & TWL4030_WDT_STATE_ACTIVE)
-               return twl4030_wdt_enable(wdt);
+       struct watchdog_device *wdt = platform_get_drvdata(pdev);
+       if (watchdog_active(wdt))
+               return twl4030_wdt_start(wdt);
 
        return 0;
 }
@@ -245,14 +131,21 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
 #define twl4030_wdt_resume         NULL
 #endif
 
+static const struct of_device_id twl_wdt_of_match[] = {
+       { .compatible = "ti,twl4030-wdt", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl_wdt_of_match);
+
 static struct platform_driver twl4030_wdt_driver = {
        .probe          = twl4030_wdt_probe,
        .remove         = twl4030_wdt_remove,
        .suspend        = twl4030_wdt_suspend,
        .resume         = twl4030_wdt_resume,
        .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "twl4030_wdt",
+               .owner          = THIS_MODULE,
+               .name           = "twl4030_wdt",
+               .of_match_table = twl_wdt_of_match,
        },
 };
 
@@ -260,6 +153,5 @@ module_platform_driver(twl4030_wdt_driver);
 
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS("platform:twl4030_wdt");
 
index 4dcfced107f50e41c518405b28747064d62d78bc..084041d42c9adabfc40251546d361ad76d8987e5 100644 (file)
@@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu)
 static int vcpu_online(unsigned int cpu)
 {
        int err;
-       char dir[32], state[32];
+       char dir[16], state[16];
 
        sprintf(dir, "cpu/%u", cpu);
-       err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
+       err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state);
        if (err != 1) {
                if (!xen_initial_domain())
                        printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
index 0be4df39e953a5b870948e6ed8a1553a15cc2c2a..74d77dfa5f636001356b2d27d370708b820c885e 100644 (file)
@@ -840,7 +840,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
 
        if (irq == -1) {
                irq = xen_allocate_irq_dynamic();
-               if (irq == -1)
+               if (irq < 0)
                        goto out;
 
                irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
@@ -944,7 +944,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 
        if (irq == -1) {
                irq = xen_allocate_irq_dynamic();
-               if (irq == -1)
+               if (irq < 0)
                        goto out;
 
                irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
index 2e22df2f7a3f8b57fe44ce8842b825602a012658..3c8803feba26cdcba8bd890225ac7995ef72810e 100644 (file)
@@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by "
 static atomic_t pages_mapped = ATOMIC_INIT(0);
 
 static int use_ptemod;
+#define populate_freeable_maps use_ptemod
 
 struct gntdev_priv {
+       /* maps with visible offsets in the file descriptor */
        struct list_head maps;
-       /* lock protects maps from concurrent changes */
+       /* maps that are not visible; will be freed on munmap.
+        * Only populated if populate_freeable_maps == 1 */
+       struct list_head freeable_maps;
+       /* lock protects maps and freeable_maps */
        spinlock_t lock;
        struct mm_struct *mm;
        struct mmu_notifier mn;
@@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
        return NULL;
 }
 
-static void gntdev_put_map(struct grant_map *map)
+static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
 {
        if (!map)
                return;
@@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
+       if (populate_freeable_maps && priv) {
+               spin_lock(&priv->lock);
+               list_del(&map->next);
+               spin_unlock(&priv->lock);
+       }
+
        if (map->pages && !use_ptemod)
                unmap_grant_pages(map, 0, map->count);
        gntdev_free_map(map);
@@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
 
        if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
                int pgno = (map->notify.addr >> PAGE_SHIFT);
-               if (pgno >= offset && pgno < offset + pages && use_ptemod) {
-                       void __user *tmp = (void __user *)
-                               map->vma->vm_start + map->notify.addr;
-                       err = copy_to_user(tmp, &err, 1);
-                       if (err)
-                               return -EFAULT;
-                       map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
-               } else if (pgno >= offset && pgno < offset + pages) {
-                       uint8_t *tmp = kmap(map->pages[pgno]);
+               if (pgno >= offset && pgno < offset + pages) {
+                       /* No need for kmap, pages are in lowmem */
+                       uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno]));
                        tmp[map->notify.addr & (PAGE_SIZE-1)] = 0;
-                       kunmap(map->pages[pgno]);
                        map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
                }
        }
@@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma)
 static void gntdev_vma_close(struct vm_area_struct *vma)
 {
        struct grant_map *map = vma->vm_private_data;
+       struct file *file = vma->vm_file;
+       struct gntdev_priv *priv = file->private_data;
 
        pr_debug("gntdev_vma_close %p\n", vma);
-       map->vma = NULL;
+       if (use_ptemod) {
+               /* It is possible that an mmu notifier could be running
+                * concurrently, so take priv->lock to ensure that the vma won't
+                * vanishing during the unmap_grant_pages call, since we will
+                * spin here until that completes. Such a concurrent call will
+                * not do any unmapping, since that has been done prior to
+                * closing the vma, but it may still iterate the unmap_ops list.
+                */
+               spin_lock(&priv->lock);
+               map->vma = NULL;
+               spin_unlock(&priv->lock);
+       }
        vma->vm_private_data = NULL;
-       gntdev_put_map(map);
+       gntdev_put_map(priv, map);
 }
 
 static struct vm_operations_struct gntdev_vmops = {
@@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = {
 
 /* ------------------------------------------------------------------ */
 
+static void unmap_if_in_range(struct grant_map *map,
+                             unsigned long start, unsigned long end)
+{
+       unsigned long mstart, mend;
+       int err;
+
+       if (!map->vma)
+               return;
+       if (map->vma->vm_start >= end)
+               return;
+       if (map->vma->vm_end <= start)
+               return;
+       mstart = max(start, map->vma->vm_start);
+       mend   = min(end,   map->vma->vm_end);
+       pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
+                       map->index, map->count,
+                       map->vma->vm_start, map->vma->vm_end,
+                       start, end, mstart, mend);
+       err = unmap_grant_pages(map,
+                               (mstart - map->vma->vm_start) >> PAGE_SHIFT,
+                               (mend - mstart) >> PAGE_SHIFT);
+       WARN_ON(err);
+}
+
 static void mn_invl_range_start(struct mmu_notifier *mn,
                                struct mm_struct *mm,
                                unsigned long start, unsigned long end)
 {
        struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
        struct grant_map *map;
-       unsigned long mstart, mend;
-       int err;
 
        spin_lock(&priv->lock);
        list_for_each_entry(map, &priv->maps, next) {
-               if (!map->vma)
-                       continue;
-               if (map->vma->vm_start >= end)
-                       continue;
-               if (map->vma->vm_end <= start)
-                       continue;
-               mstart = max(start, map->vma->vm_start);
-               mend   = min(end,   map->vma->vm_end);
-               pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
-                               map->index, map->count,
-                               map->vma->vm_start, map->vma->vm_end,
-                               start, end, mstart, mend);
-               err = unmap_grant_pages(map,
-                                       (mstart - map->vma->vm_start) >> PAGE_SHIFT,
-                                       (mend - mstart) >> PAGE_SHIFT);
-               WARN_ON(err);
+               unmap_if_in_range(map, start, end);
+       }
+       list_for_each_entry(map, &priv->freeable_maps, next) {
+               unmap_if_in_range(map, start, end);
        }
        spin_unlock(&priv->lock);
 }
@@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn,
                err = unmap_grant_pages(map, /* offset */ 0, map->count);
                WARN_ON(err);
        }
+       list_for_each_entry(map, &priv->freeable_maps, next) {
+               if (!map->vma)
+                       continue;
+               pr_debug("map %d+%d (%lx %lx)\n",
+                               map->index, map->count,
+                               map->vma->vm_start, map->vma->vm_end);
+               err = unmap_grant_pages(map, /* offset */ 0, map->count);
+               WARN_ON(err);
+       }
        spin_unlock(&priv->lock);
 }
 
@@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&priv->maps);
+       INIT_LIST_HEAD(&priv->freeable_maps);
        spin_lock_init(&priv->lock);
 
        if (use_ptemod) {
@@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip)
        while (!list_empty(&priv->maps)) {
                map = list_entry(priv->maps.next, struct grant_map, next);
                list_del(&map->next);
-               gntdev_put_map(map);
+               gntdev_put_map(NULL /* already removed */, map);
        }
+       WARN_ON(!list_empty(&priv->freeable_maps));
 
        if (use_ptemod)
                mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
 
        if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) {
                pr_debug("can't map: over limit\n");
-               gntdev_put_map(map);
+               gntdev_put_map(NULL, map);
                return err;
        }
 
        if (copy_from_user(map->grants, &u->refs,
                           sizeof(map->grants[0]) * op.count) != 0) {
-               gntdev_put_map(map);
-               return err;
+               gntdev_put_map(NULL, map);
+               return -EFAULT;
        }
 
        spin_lock(&priv->lock);
@@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
        map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
        if (map) {
                list_del(&map->next);
+               if (populate_freeable_maps)
+                       list_add_tail(&map->next, &priv->freeable_maps);
                err = 0;
        }
        spin_unlock(&priv->lock);
        if (map)
-               gntdev_put_map(map);
+               gntdev_put_map(priv, map);
        return err;
 }
 
@@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
        struct ioctl_gntdev_get_offset_for_vaddr op;
        struct vm_area_struct *vma;
        struct grant_map *map;
+       int rv = -EINVAL;
 
        if (copy_from_user(&op, u, sizeof(op)) != 0)
                return -EFAULT;
        pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr);
 
+       down_read(&current->mm->mmap_sem);
        vma = find_vma(current->mm, op.vaddr);
        if (!vma || vma->vm_ops != &gntdev_vmops)
-               return -EINVAL;
+               goto out_unlock;
 
        map = vma->vm_private_data;
        if (!map)
-               return -EINVAL;
+               goto out_unlock;
 
        op.offset = map->index << PAGE_SHIFT;
        op.count = map->count;
+       rv = 0;
 
-       if (copy_to_user(u, &op, sizeof(op)) != 0)
+ out_unlock:
+       up_read(&current->mm->mmap_sem);
+
+       if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0)
                return -EFAULT;
-       return 0;
+       return rv;
 }
 
 static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
@@ -778,7 +824,7 @@ out_unlock_put:
 out_put_map:
        if (use_ptemod)
                map->vma = NULL;
-       gntdev_put_map(map);
+       gntdev_put_map(priv, map);
        return err;
 }
 
index b91f14e831648e68093a02f804f82e4113325360..157c0ccda3efdce0e8a3c4b9ab0937ade1d932ec 100644 (file)
 /* External tools reserve first few grant table entries. */
 #define NR_RESERVED_ENTRIES 8
 #define GNTTAB_LIST_END 0xffffffff
-#define GREFS_PER_GRANT_FRAME \
-(grant_table_version == 1 ?                      \
-(PAGE_SIZE / sizeof(struct grant_entry_v1)) :   \
-(PAGE_SIZE / sizeof(union grant_entry_v2)))
 
 static grant_ref_t **gnttab_list;
 static unsigned int nr_grant_frames;
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface;
 static grant_status_t *grstatus;
 
 static int grant_table_version;
+static int grefs_per_grant_frame;
 
 static struct gnttab_free_callback *gnttab_free_callback_list;
 
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames)
        unsigned int new_nr_grant_frames, extra_entries, i;
        unsigned int nr_glist_frames, new_nr_glist_frames;
 
+       BUG_ON(grefs_per_grant_frame == 0);
+
        new_nr_grant_frames = nr_grant_frames + more_frames;
-       extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
+       extra_entries       = more_frames * grefs_per_grant_frame;
 
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        new_nr_glist_frames =
-               (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+               (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
                if (!gnttab_list[i])
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames)
        }
 
 
-       for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
-            i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
+       for (i = grefs_per_grant_frame * nr_grant_frames;
+            i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
                gnttab_entry(i) = i + 1;
 
        gnttab_entry(i) = gnttab_free_head;
-       gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
+       gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
        gnttab_free_count += extra_entries;
 
        nr_grant_frames = new_nr_grant_frames;
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
-       return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
+       BUG_ON(grefs_per_grant_frame == 0);
+       return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
 }
 
 static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void)
        rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
        if (rc == 0 && gsv.version == 2) {
                grant_table_version = 2;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
                gnttab_interface = &gnttab_v2_ops;
        } else if (grant_table_version == 2) {
                /*
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void)
                panic("we need grant tables version 2, but only version 1 is available");
        } else {
                grant_table_version = 1;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
                gnttab_interface = &gnttab_v1_ops;
        }
        printk(KERN_INFO "Grant tables using version %d layout.\n",
                grant_table_version);
 }
 
-int gnttab_resume(void)
+static int gnttab_setup(void)
 {
        unsigned int max_nr_gframes;
 
-       gnttab_request_version();
        max_nr_gframes = gnttab_max_grant_frames();
        if (max_nr_gframes < nr_grant_frames)
                return -ENOSYS;
@@ -1160,6 +1161,12 @@ int gnttab_resume(void)
        return 0;
 }
 
+int gnttab_resume(void)
+{
+       gnttab_request_version();
+       return gnttab_setup();
+}
+
 int gnttab_suspend(void)
 {
        gnttab_interface->unmap_frames();
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries)
        int rc;
        unsigned int cur, extra;
 
+       BUG_ON(grefs_per_grant_frame == 0);
        cur = nr_grant_frames;
-       extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
-                GREFS_PER_GRANT_FRAME);
+       extra = ((req_entries + (grefs_per_grant_frame-1)) /
+                grefs_per_grant_frame);
        if (cur + extra > gnttab_max_grant_frames())
                return -ENOSPC;
 
@@ -1191,21 +1199,23 @@ int gnttab_init(void)
        unsigned int nr_init_grefs;
        int ret;
 
+       gnttab_request_version();
        nr_grant_frames = 1;
        boot_max_nr_grant_frames = __max_nr_grant_frames();
 
        /* Determine the maximum number of frames required for the
         * grant reference free list on the current hypervisor.
         */
+       BUG_ON(grefs_per_grant_frame == 0);
        max_nr_glist_frames = (boot_max_nr_grant_frames *
-                              GREFS_PER_GRANT_FRAME / RPP);
+                              grefs_per_grant_frame / RPP);
 
        gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
                              GFP_KERNEL);
        if (gnttab_list == NULL)
                return -ENOMEM;
 
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = 0; i < nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
                if (gnttab_list[i] == NULL) {
@@ -1214,12 +1224,12 @@ int gnttab_init(void)
                }
        }
 
-       if (gnttab_resume() < 0) {
+       if (gnttab_setup() < 0) {
                ret = -ENODEV;
                goto ini_nomem;
        }
 
-       nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
+       nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
 
        for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
                gnttab_entry(i) = i + 1;
@@ -1239,7 +1249,7 @@ int gnttab_init(void)
 }
 EXPORT_SYMBOL_GPL(gnttab_init);
 
-static int __devinit __gnttab_init(void)
+static int __gnttab_init(void)
 {
        /* Delay grant-table initialization in the PV on HVM case */
        if (xen_hvm_domain())
index 067fcfa1723e0b846b9522038edb5ef1dc96f4e0..5a27a4599a4a8dbb28aab05c305b799b7883d2ac 100644 (file)
@@ -278,8 +278,7 @@ static int sync_pcpu(uint32_t cpu, uint32_t *max_cpu)
         * Only those at cpu present map has its sys interface.
         */
        if (info->flags & XEN_PCPU_FLAGS_INVALID) {
-               if (pcpu)
-                       unregister_and_remove_pcpu(pcpu);
+               unregister_and_remove_pcpu(pcpu);
                return 0;
        }
 
index 97ca359ae2bdfb8d072ee62348114a252660adf9..99db9e1eb8ba47419bc13c5c94803d35537d609d 100644 (file)
@@ -101,8 +101,8 @@ static int platform_pci_resume(struct pci_dev *pdev)
        return 0;
 }
 
-static int __devinit platform_pci_init(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int platform_pci_init(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        int i, ret;
        long ioaddr;
@@ -170,7 +170,7 @@ pci_out:
        return ret;
 }
 
-static struct pci_device_id platform_pci_tbl[] __devinitdata = {
+static struct pci_device_id platform_pci_tbl[] = {
        {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {0,}
index 0bbbccbb1f1296ea305414795b6915679b26d94d..ca2b00e9d558c8fea579f4667106eaccee0adb84 100644 (file)
@@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata)
        LIST_HEAD(pagelist);
        struct mmap_mfn_state state;
 
-       if (!xen_initial_domain())
-               return -EPERM;
-
        /* We only support privcmd_ioctl_mmap_batch for auto translated. */
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return -ENOSYS;
@@ -261,11 +258,12 @@ struct mmap_batch_state {
         *      -ENOENT if at least 1 -ENOENT has happened.
         */
        int global_error;
-       /* An array for individual errors */
-       int *err;
+       int version;
 
        /* User-space mfn array to store errors in the second pass for V1. */
        xen_pfn_t __user *user_mfn;
+       /* User-space int array to store errors in the second pass for V2. */
+       int __user *user_err;
 };
 
 /* auto translated dom0 note: if domU being created is PV, then mfn is
@@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state)
                                         &cur_page);
 
        /* Store error code for second pass. */
-       *(st->err++) = ret;
+       if (st->version == 1) {
+               if (ret < 0) {
+                       /*
+                        * V1 encodes the error codes in the 32bit top nibble of the
+                        * mfn (with its known limitations vis-a-vis 64 bit callers).
+                        */
+                       *mfnp |= (ret == -ENOENT) ?
+                                               PRIVCMD_MMAPBATCH_PAGED_ERROR :
+                                               PRIVCMD_MMAPBATCH_MFN_ERROR;
+               }
+       } else { /* st->version == 2 */
+               *((int *) mfnp) = ret;
+       }
 
        /* And see if it affects the global_error. */
        if (ret < 0) {
@@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state)
        return 0;
 }
 
-static int mmap_return_errors_v1(void *data, void *state)
+static int mmap_return_errors(void *data, void *state)
 {
-       xen_pfn_t *mfnp = data;
        struct mmap_batch_state *st = state;
-       int err = *(st->err++);
 
-       /*
-        * V1 encodes the error codes in the 32bit top nibble of the
-        * mfn (with its known limitations vis-a-vis 64 bit callers).
-        */
-       *mfnp |= (err == -ENOENT) ?
-                               PRIVCMD_MMAPBATCH_PAGED_ERROR :
-                               PRIVCMD_MMAPBATCH_MFN_ERROR;
-       return __put_user(*mfnp, st->user_mfn++);
+       if (st->version == 1) {
+               xen_pfn_t mfnp = *((xen_pfn_t *) data);
+               if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR)
+                       return __put_user(mfnp, st->user_mfn++);
+               else
+                       st->user_mfn++;
+       } else { /* st->version == 2 */
+               int err = *((int *) data);
+               if (err)
+                       return __put_user(err, st->user_err++);
+               else
+                       st->user_err++;
+       }
+
+       return 0;
 }
 
 /* Allocate pfns that are then mapped with gmfns from foreign domid. Update
@@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        struct vm_area_struct *vma;
        unsigned long nr_pages;
        LIST_HEAD(pagelist);
-       int *err_array = NULL;
        struct mmap_batch_state state;
 
-       if (!xen_initial_domain())
-               return -EPERM;
-
        switch (version) {
        case 1:
                if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch)))
@@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
                goto out;
        }
 
-       err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL);
-       if (err_array == NULL) {
-               ret = -ENOMEM;
-               goto out;
+       if (version == 2) {
+               /* Zero error array now to only copy back actual errors. */
+               if (clear_user(m.err, sizeof(int) * m.num)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
        }
 
        down_write(&mm->mmap_sem);
@@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        state.va            = m.addr;
        state.index         = 0;
        state.global_error  = 0;
-       state.err           = err_array;
+       state.version       = version;
 
        /* mmap_batch_fn guarantees ret == 0 */
        BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t),
@@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       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)
-                       ret = -EFAULT;
-       }
+       if (state.global_error) {
+               /* Write back errors in second pass. */
+               state.user_mfn = (xen_pfn_t *)m.arr;
+               state.user_err = m.err;
+               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                                        &pagelist, mmap_return_errors, &state);
+       } else
+               ret = 0;
 
        /* If we have not had any EFAULT-like global errors then set the global
         * error to -ENOENT if necessary. */
@@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
                ret = -ENOENT;
 
 out:
-       kfree(err_array);
        free_page_list(&pagelist);
 
        return ret;
index cd50d251998ee629fc5244add466129d4662e398..9204126f1560ced72321b267b96099acfe71b8dd 100644 (file)
@@ -272,8 +272,8 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
        up_write(&pcistub_sem);
 }
 
-static int __devinit pcistub_match_one(struct pci_dev *dev,
-                                      struct pcistub_device_id *pdev_id)
+static int pcistub_match_one(struct pci_dev *dev,
+                            struct pcistub_device_id *pdev_id)
 {
        /* Match the specified device by domain, bus, slot, func and also if
         * any of the device's parent bridges match.
@@ -292,7 +292,7 @@ static int __devinit pcistub_match_one(struct pci_dev *dev,
        return 0;
 }
 
-static int __devinit pcistub_match(struct pci_dev *dev)
+static int pcistub_match(struct pci_dev *dev)
 {
        struct pcistub_device_id *pdev_id;
        unsigned long flags;
@@ -310,7 +310,7 @@ static int __devinit pcistub_match(struct pci_dev *dev)
        return found;
 }
 
-static int __devinit pcistub_init_device(struct pci_dev *dev)
+static int pcistub_init_device(struct pci_dev *dev)
 {
        struct xen_pcibk_dev_data *dev_data;
        int err = 0;
@@ -428,7 +428,7 @@ static int __init pcistub_init_devices_late(void)
        return 0;
 }
 
-static int __devinit pcistub_seize(struct pci_dev *dev)
+static int pcistub_seize(struct pci_dev *dev)
 {
        struct pcistub_device *psdev;
        unsigned long flags;
@@ -463,8 +463,7 @@ static int __devinit pcistub_seize(struct pci_dev *dev)
        return err;
 }
 
-static int __devinit pcistub_probe(struct pci_dev *dev,
-                                  const struct pci_device_id *id)
+static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int err = 0;
 
index a7def010eba3116ac73375f7704c06165c0e0699..f72af87640e076a429af64d050cd23e397e5ff3c 100644 (file)
@@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
                                             struct pci_dev *dev)
 {
-       if (xen_pcibk_backend && xen_pcibk_backend->free)
+       if (xen_pcibk_backend && xen_pcibk_backend->release)
                return xen_pcibk_backend->release(pdev, dev);
 }
 
index 97f5d264c31ee6f464b92e5b6a2656bff6f00b7f..37c1f825f513764c998e808acf482d9d20cda7e0 100644 (file)
@@ -135,7 +135,6 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
                         struct pci_dev *dev, struct xen_pci_op *op)
 {
        struct xen_pcibk_dev_data *dev_data;
-       int otherend = pdev->xdev->otherend_id;
        int status;
 
        if (unlikely(verbose_request))
@@ -144,8 +143,9 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
        status = pci_enable_msi(dev);
 
        if (status) {
-               printk(KERN_ERR "error enable msi for guest %x status %x\n",
-                       otherend, status);
+               pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI for guest %u: err %d\n",
+                                   pci_name(dev), pdev->xdev->otherend_id,
+                                   status);
                op->value = 0;
                return XEN_PCI_ERR_op_failed;
        }
@@ -223,10 +223,10 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
                                                pci_name(dev), i,
                                                op->msix_entries[i].vector);
                }
-       } else {
-               printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n",
-                       pci_name(dev), result);
-       }
+       } else
+               pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI-X for guest %u: err %d!\n",
+                                   pci_name(dev), pdev->xdev->otherend_id,
+                                   result);
        kfree(entries);
 
        op->value = result;
index 229624f867d3533f09173b276065457955878568..ac1db7f1bcab7731e9366cfc4bce832c4258cd35 100644 (file)
@@ -142,7 +142,6 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv)
 
 static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-#ifdef CONFIG_HOTPLUG
        struct zorro_dev *z;
 
        if (!dev)
@@ -159,9 +158,6 @@ static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
                return -ENOMEM;
 
        return 0;
-#else /* !CONFIG_HOTPLUG */
-       return -ENODEV;
-#endif /* !CONFIG_HOTPLUG */
 }
 
 struct bus_type zorro_bus_type = {
index eaff24a19502aaf815cb8407152871da5d065665..780725a463b1b9001dd089ecb4fddce87b35c51a 100644 (file)
@@ -68,16 +68,6 @@ source "fs/quota/Kconfig"
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config CUSE
-       tristate "Character device in Userspace support"
-       depends on FUSE_FS
-       help
-         This FUSE extension allows character devices to be
-         implemented in userspace.
-
-         If you want to develop or use userspace character device
-         based on CUSE, answer Y or M.
-
 config GENERIC_ACL
        bool
        select FS_POSIX_ACL
@@ -220,6 +210,7 @@ source "fs/pstore/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
+source "fs/f2fs/Kconfig"
 
 endif # MISC_FILESYSTEMS
 
index 1d7af79288a04915ca0d1788bc84f32bd03793a0..9d53192236fc5ca2ffd6507ebd7d17e4109e582d 100644 (file)
@@ -123,6 +123,7 @@ obj-$(CONFIG_DEBUG_FS)              += debugfs/
 obj-$(CONFIG_OCFS2_FS)         += ocfs2/
 obj-$(CONFIG_BTRFS_FS)         += btrfs/
 obj-$(CONFIG_GFS2_FS)           += gfs2/
+obj-$(CONFIG_F2FS_FS)          += f2fs/
 obj-y                          += exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)          += ceph/
 obj-$(CONFIG_PSTORE)           += pstore/
index e9bad5093a3f92f45761a534e38cae37661fddea..5f95d1ed9c6dbf882e3b73e85b6cf0469f7d63af 100644 (file)
@@ -45,6 +45,14 @@ static int adfs_readpage(struct file *file, struct page *page)
        return block_read_full_page(page, adfs_get_block);
 }
 
+static void adfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size)
+               truncate_pagecache(inode, to, inode->i_size);
+}
+
 static int adfs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -55,11 +63,8 @@ static int adfs_write_begin(struct file *file, struct address_space *mapping,
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                adfs_get_block,
                                &ADFS_I(mapping->host)->mmu_private);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               adfs_write_failed(mapping, pos + len);
 
        return ret;
 }
index 2f4c935cb3276e544b321e89bfddd4fa2525d2d5..af3261b781021f0a51dda6b73b5fb5b3d051baa7 100644 (file)
@@ -39,7 +39,6 @@ const struct file_operations affs_file_operations = {
 };
 
 const struct inode_operations affs_file_inode_operations = {
-       .truncate       = affs_truncate,
        .setattr        = affs_notify_change,
 };
 
@@ -402,6 +401,16 @@ static int affs_readpage(struct file *file, struct page *page)
        return block_read_full_page(page, affs_get_block);
 }
 
+static void affs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               affs_truncate(inode);
+       }
+}
+
 static int affs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -412,11 +421,8 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                affs_get_block,
                                &AFFS_I(mapping->host)->mmu_private);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               affs_write_failed(mapping, pos + len);
 
        return ret;
 }
index 15c4842682292784ce095d85fb01a52615f7326a..0e092d08680edde3307aae65067bd41460e17b66 100644 (file)
@@ -237,9 +237,12 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        return error;
+
+               truncate_setsize(inode, attr->ia_size);
+               affs_truncate(inode);
        }
 
        setattr_copy(inode, attr);
index f20e8a71062f4d2bc15e1daacf44398b8cab4906..ad3ea1497cc3825d4fdf795cd6b5735618005e0e 100644 (file)
@@ -161,6 +161,14 @@ static int bfs_readpage(struct file *file, struct page *page)
        return block_read_full_page(page, bfs_get_block);
 }
 
+static void bfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size)
+               truncate_pagecache(inode, to, inode->i_size);
+}
+
 static int bfs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -169,11 +177,8 @@ static int bfs_write_begin(struct file *file, struct address_space *mapping,
 
        ret = block_write_begin(mapping, pos, len, flags, pagep,
                                bfs_get_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               bfs_write_failed(mapping, pos + len);
 
        return ret;
 }
index 0c42cdbabecff0c4c8d9d0e597273ff4fce79507..49d0b43458b700d54a02bb1fc54a84d6cec10efa 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/elf.h>
 #include <linux/utsname.h>
 #include <linux/coredump.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
@@ -1320,8 +1321,11 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
                cputime_to_timeval(cputime.utime, &prstatus->pr_utime);
                cputime_to_timeval(cputime.stime, &prstatus->pr_stime);
        } else {
-               cputime_to_timeval(p->utime, &prstatus->pr_utime);
-               cputime_to_timeval(p->stime, &prstatus->pr_stime);
+               cputime_t utime, stime;
+
+               task_cputime(p, &utime, &stime);
+               cputime_to_timeval(utime, &prstatus->pr_utime);
+               cputime_to_timeval(stime, &prstatus->pr_stime);
        }
        cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
        cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
index dc84732e554f679dee6de0d95e7eab2b5bcda5b9..cb240dd3b402bafa8bc7fdca8f8d84526b558e82 100644 (file)
@@ -1375,8 +1375,11 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
                cputime_to_timeval(cputime.utime, &prstatus->pr_utime);
                cputime_to_timeval(cputime.stime, &prstatus->pr_stime);
        } else {
-               cputime_to_timeval(p->utime, &prstatus->pr_utime);
-               cputime_to_timeval(p->stime, &prstatus->pr_stime);
+               cputime_t utime, stime;
+
+               task_cputime(p, &utime, &stime);
+               cputime_to_timeval(utime, &prstatus->pr_utime);
+               cputime_to_timeval(stime, &prstatus->pr_stime);
        }
        cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
        cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
index 9be335fb8a7cd3f9f480d0c5a46de7cfbcdd1c1f..0c8869fdd14ebf9291eb700ccd099c910584910d 100644 (file)
@@ -172,7 +172,10 @@ static int load_misc_binary(struct linux_binprm *bprm)
                goto _error;
        bprm->argc ++;
 
-       bprm->interp = iname;   /* for binfmt_script */
+       /* Update interp in case binfmt_script needs it. */
+       retval = bprm_change_interp(iname, bprm);
+       if (retval < 0)
+               goto _error;
 
        interp_file = open_exec (iname);
        retval = PTR_ERR (interp_file);
index 1610a91637e57d88c54b1a88d6a3ba1e4a230ac4..5027a3e149222bd5945c87d9521e6e7a6108dc77 100644 (file)
@@ -80,7 +80,9 @@ static int load_script(struct linux_binprm *bprm)
        retval = copy_strings_kernel(1, &i_name, bprm);
        if (retval) return retval; 
        bprm->argc++;
-       bprm->interp = interp;
+       retval = bprm_change_interp(interp, bprm);
+       if (retval < 0)
+               return retval;
 
        /*
         * OK, now restart the process with the interpreter's dentry.
index c7b67cf24bba54f85a6eb488ea899190961bac09..eea5da7a2b9aa38ce28ee9b55d1c8ff5c141fa16 100644 (file)
@@ -1138,13 +1138,13 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
                switch (tm->op) {
                case MOD_LOG_KEY_REMOVE_WHILE_FREEING:
                        BUG_ON(tm->slot < n);
-               case MOD_LOG_KEY_REMOVE:
-                       n++;
                case MOD_LOG_KEY_REMOVE_WHILE_MOVING:
+               case MOD_LOG_KEY_REMOVE:
                        btrfs_set_node_key(eb, &tm->key, tm->slot);
                        btrfs_set_node_blockptr(eb, tm->slot, tm->blockptr);
                        btrfs_set_node_ptr_generation(eb, tm->slot,
                                                      tm->generation);
+                       n++;
                        break;
                case MOD_LOG_KEY_REPLACE:
                        BUG_ON(tm->slot >= n);
@@ -4611,12 +4611,6 @@ static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        u32 nritems;
        int ret;
 
-       if (level) {
-               ret = tree_mod_log_insert_key(root->fs_info, parent, slot,
-                                             MOD_LOG_KEY_REMOVE);
-               BUG_ON(ret < 0);
-       }
-
        nritems = btrfs_header_nritems(parent);
        if (slot != nritems - 1) {
                if (level)
@@ -4627,6 +4621,10 @@ static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                              btrfs_node_key_ptr_offset(slot + 1),
                              sizeof(struct btrfs_key_ptr) *
                              (nritems - slot - 1));
+       } else if (level) {
+               ret = tree_mod_log_insert_key(root->fs_info, parent, slot,
+                                             MOD_LOG_KEY_REMOVE);
+               BUG_ON(ret < 0);
        }
 
        nritems--;
index 521e9d4424f64f81d69d98709031a342d5ee808f..5a3327b8f90d557db144b360b3df4ec9bce9ff50 100644 (file)
@@ -3997,7 +3997,7 @@ again:
         * We make the other tasks wait for the flush only when we can flush
         * all things.
         */
-       if (ret && flush == BTRFS_RESERVE_FLUSH_ALL) {
+       if (ret && flush != BTRFS_RESERVE_NO_FLUSH) {
                flushing = true;
                space_info->flush = 1;
        }
@@ -4534,7 +4534,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        unsigned nr_extents = 0;
        int extra_reserve = 0;
        enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
-       int ret;
+       int ret = 0;
        bool delalloc_lock = true;
 
        /* If we are a free space inode we need to not flush since we will be in
@@ -4579,20 +4579,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        csum_bytes = BTRFS_I(inode)->csum_bytes;
        spin_unlock(&BTRFS_I(inode)->lock);
 
-       if (root->fs_info->quota_enabled) {
+       if (root->fs_info->quota_enabled)
                ret = btrfs_qgroup_reserve(root, num_bytes +
                                           nr_extents * root->leafsize);
-               if (ret) {
-                       spin_lock(&BTRFS_I(inode)->lock);
-                       calc_csum_metadata_size(inode, num_bytes, 0);
-                       spin_unlock(&BTRFS_I(inode)->lock);
-                       if (delalloc_lock)
-                               mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
-                       return ret;
-               }
-       }
 
-       ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
+       /*
+        * ret != 0 here means the qgroup reservation failed, we go straight to
+        * the shared error handling then.
+        */
+       if (ret == 0)
+               ret = reserve_metadata_bytes(root, block_rsv,
+                                            to_reserve, flush);
+
        if (ret) {
                u64 to_free = 0;
                unsigned dropped;
@@ -5560,7 +5558,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        int empty_cluster = 2 * 1024 * 1024;
        struct btrfs_space_info *space_info;
        int loop = 0;
-       int index = 0;
+       int index = __get_raid_index(data);
        int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ?
                RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC;
        bool found_uncached_bg = false;
@@ -6788,11 +6786,13 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                                                       &wc->flags[level]);
                        if (ret < 0) {
                                btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               path->locks[level] = 0;
                                return ret;
                        }
                        BUG_ON(wc->refs[level] == 0);
                        if (wc->refs[level] == 1) {
                                btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               path->locks[level] = 0;
                                return 1;
                        }
                }
index f169d6b11d7f6a093158428352a44f35d4bae952..fdb7a8db3b5748911e5820f9b588c5a264a6a8bc 100644 (file)
@@ -171,6 +171,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next)
        if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags))
                return 0;
 
+       if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) ||
+           test_bit(EXTENT_FLAG_LOGGING, &next->flags))
+               return 0;
+
        if (extent_map_end(prev) == next->start &&
            prev->flags == next->flags &&
            prev->bdev == next->bdev &&
@@ -255,7 +259,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len,
        if (!em)
                goto out;
 
-       list_move(&em->list, &tree->modified_extents);
+       if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
+               list_move(&em->list, &tree->modified_extents);
        em->generation = gen;
        clear_bit(EXTENT_FLAG_PINNED, &em->flags);
        em->mod_start = em->start;
@@ -280,6 +285,13 @@ out:
 
 }
 
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)
+{
+       clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
+       if (em->in_tree)
+               try_merge_map(tree, em);
+}
+
 /**
  * add_extent_mapping - add new extent map to the extent tree
  * @tree:      tree to insert new map in
index 922943ce29e8caebe0a69feda2a7e481bed0d556..c6598c89cff8c48676dd6179f649ef6f0638acad 100644 (file)
@@ -69,6 +69,7 @@ void free_extent_map(struct extent_map *em);
 int __init extent_map_init(void);
 void extent_map_exit(void);
 int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
 struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
                                         u64 start, u64 len);
 #endif
index bd38cef4235882425c08eb6a5d10306736a14237..94aa53b387213bbfc13181163368e5e168574d77 100644 (file)
@@ -460,8 +460,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
                if (!contig)
                        offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 
-               if (!contig && (offset >= ordered->file_offset + ordered->len ||
-                   offset < ordered->file_offset)) {
+               if (offset >= ordered->file_offset + ordered->len ||
+                   offset < ordered->file_offset) {
                        unsigned long bytes_left;
                        sums->len = this_sum_bytes;
                        this_sum_bytes = 0;
index 77061bf43edbae995bf55ce73dcc89bf73012400..aeb84469d2c4c0621b002084617578f7ac5f49b1 100644 (file)
@@ -293,15 +293,24 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
        struct btrfs_key key;
        struct btrfs_ioctl_defrag_range_args range;
        int num_defrag;
+       int index;
+       int ret;
 
        /* get the inode */
        key.objectid = defrag->root;
        btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
        key.offset = (u64)-1;
+
+       index = srcu_read_lock(&fs_info->subvol_srcu);
+
        inode_root = btrfs_read_fs_root_no_name(fs_info, &key);
        if (IS_ERR(inode_root)) {
-               kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
-               return PTR_ERR(inode_root);
+               ret = PTR_ERR(inode_root);
+               goto cleanup;
+       }
+       if (btrfs_root_refs(&inode_root->root_item) == 0) {
+               ret = -ENOENT;
+               goto cleanup;
        }
 
        key.objectid = defrag->ino;
@@ -309,9 +318,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
        key.offset = 0;
        inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL);
        if (IS_ERR(inode)) {
-               kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
-               return PTR_ERR(inode);
+               ret = PTR_ERR(inode);
+               goto cleanup;
        }
+       srcu_read_unlock(&fs_info->subvol_srcu, index);
 
        /* do a chunk of defrag */
        clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags);
@@ -346,6 +356,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
 
        iput(inode);
        return 0;
+cleanup:
+       srcu_read_unlock(&fs_info->subvol_srcu, index);
+       kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
+       return ret;
 }
 
 /*
@@ -1594,9 +1608,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                if (err < 0 && num_written > 0)
                        num_written = err;
        }
-out:
+
        if (sync)
                atomic_dec(&BTRFS_I(inode)->sync_writers);
+out:
        sb_end_write(inode->i_sb);
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
@@ -2241,6 +2256,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
        if (lockend <= lockstart)
                lockend = lockstart + root->sectorsize;
 
+       lockend--;
        len = lockend - lockstart + 1;
 
        len = max_t(u64, len, root->sectorsize);
@@ -2307,9 +2323,12 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
                                        }
                                }
 
-                               *offset = start;
-                               free_extent_map(em);
-                               break;
+                               if (!test_bit(EXTENT_FLAG_PREALLOC,
+                                             &em->flags)) {
+                                       *offset = start;
+                                       free_extent_map(em);
+                                       break;
+                               }
                        }
                }
 
index 59ea2e4349c9cdbecb105a3a384376f52b0a5da6..0be7a8742a43bb502c9b9294661baaef6e5514e1 100644 (file)
@@ -1862,11 +1862,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *info;
-       int ret = 0;
+       int ret;
+       bool re_search = false;
 
        spin_lock(&ctl->tree_lock);
 
 again:
+       ret = 0;
        if (!bytes)
                goto out_lock;
 
@@ -1879,17 +1881,17 @@ again:
                info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
-                       /* the tree logging code might be calling us before we
-                        * have fully loaded the free space rbtree for this
-                        * block group.  So it is possible the entry won't
-                        * be in the rbtree yet at all.  The caching code
-                        * will make sure not to put it in the rbtree if
-                        * the logging code has pinned it.
+                       /*
+                        * If we found a partial bit of our free space in a
+                        * bitmap but then couldn't find the other part this may
+                        * be a problem, so WARN about it.
                         */
+                       WARN_ON(re_search);
                        goto out_lock;
                }
        }
 
+       re_search = false;
        if (!info->bitmap) {
                unlink_free_space(ctl, info);
                if (offset == info->offset) {
@@ -1935,8 +1937,10 @@ again:
        }
 
        ret = remove_from_bitmap(ctl, info, &offset, &bytes);
-       if (ret == -EAGAIN)
+       if (ret == -EAGAIN) {
+               re_search = true;
                goto again;
+       }
        BUG_ON(ret); /* logic error */
 out_lock:
        spin_unlock(&ctl->tree_lock);
index 67ed24ae86bbc1c475517d2593eeca72e56880ac..cc93b23ca3520c9ad7bf2919e77f61cf400c2e4c 100644 (file)
@@ -88,7 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
        [S_IFLNK >> S_SHIFT]    = BTRFS_FT_SYMLINK,
 };
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_setsize(struct inode *inode, struct iattr *attr);
 static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
 static noinline int cow_file_range(struct inode *inode,
@@ -2478,6 +2478,18 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                                continue;
                        }
                        nr_truncate++;
+
+                       /* 1 for the orphan item deletion. */
+                       trans = btrfs_start_transaction(root, 1);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                               goto out;
+                       }
+                       ret = btrfs_orphan_add(trans, inode);
+                       btrfs_end_transaction(trans, root);
+                       if (ret)
+                               goto out;
+
                        ret = btrfs_truncate(inode);
                } else {
                        nr_unlink++;
@@ -3665,6 +3677,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                                block_end - cur_offset, 0);
                if (IS_ERR(em)) {
                        err = PTR_ERR(em);
+                       em = NULL;
                        break;
                }
                last_byte = min(extent_map_end(em), block_end);
@@ -3748,16 +3761,27 @@ next:
        return err;
 }
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize)
+static int btrfs_setsize(struct inode *inode, struct iattr *attr)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
        loff_t oldsize = i_size_read(inode);
+       loff_t newsize = attr->ia_size;
+       int mask = attr->ia_valid;
        int ret;
 
        if (newsize == oldsize)
                return 0;
 
+       /*
+        * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a
+        * special case where we need to update the times despite not having
+        * these flags set.  For all other operations the VFS set these flags
+        * explicitly if it wants a timestamp update.
+        */
+       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME))))
+               inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+
        if (newsize > oldsize) {
                truncate_pagecache(inode, oldsize, newsize);
                ret = btrfs_cont_expand(inode, oldsize, newsize);
@@ -3783,9 +3807,34 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize)
                        set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE,
                                &BTRFS_I(inode)->runtime_flags);
 
+               /*
+                * 1 for the orphan item we're going to add
+                * 1 for the orphan item deletion.
+                */
+               trans = btrfs_start_transaction(root, 2);
+               if (IS_ERR(trans))
+                       return PTR_ERR(trans);
+
+               /*
+                * We need to do this in case we fail at _any_ point during the
+                * actual truncate.  Once we do the truncate_setsize we could
+                * invalidate pages which forces any outstanding ordered io to
+                * be instantly completed which will give us extents that need
+                * to be truncated.  If we fail to get an orphan inode down we
+                * could have left over extents that were never meant to live,
+                * so we need to garuntee from this point on that everything
+                * will be consistent.
+                */
+               ret = btrfs_orphan_add(trans, inode);
+               btrfs_end_transaction(trans, root);
+               if (ret)
+                       return ret;
+
                /* we don't support swapfiles, so vmtruncate shouldn't fail */
                truncate_setsize(inode, newsize);
                ret = btrfs_truncate(inode);
+               if (ret && inode->i_nlink)
+                       btrfs_orphan_del(NULL, inode);
        }
 
        return ret;
@@ -3805,7 +3854,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               err = btrfs_setsize(inode, attr->ia_size);
+               err = btrfs_setsize(inode, attr);
                if (err)
                        return err;
        }
@@ -4262,16 +4311,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
        if (dentry->d_name.len > BTRFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       if (unlikely(d_need_lookup(dentry))) {
-               memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
-               kfree(dentry->d_fsdata);
-               dentry->d_fsdata = NULL;
-               /* This thing is hashed, drop it for now */
-               d_drop(dentry);
-       } else {
-               ret = btrfs_inode_by_name(dir, dentry, &location);
-       }
-
+       ret = btrfs_inode_by_name(dir, dentry, &location);
        if (ret < 0)
                return ERR_PTR(ret);
 
@@ -4341,11 +4381,6 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *ret;
 
        ret = d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
-       if (unlikely(d_need_lookup(dentry))) {
-               spin_lock(&dentry->d_lock);
-               dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
-               spin_unlock(&dentry->d_lock);
-       }
        return ret;
 }
 
@@ -5586,10 +5621,13 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
                return em;
        if (em) {
                /*
-                * if our em maps to a hole, there might
-                * actually be delalloc bytes behind it
+                * if our em maps to
+                * -  a hole or
+                * -  a pre-alloc extent,
+                * there might actually be delalloc bytes behind it.
                 */
-               if (em->block_start != EXTENT_MAP_HOLE)
+               if (em->block_start != EXTENT_MAP_HOLE &&
+                   !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
                        return em;
                else
                        hole_em = em;
@@ -5671,6 +5709,8 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
                         */
                        em->block_start = hole_em->block_start;
                        em->block_len = hole_len;
+                       if (test_bit(EXTENT_FLAG_PREALLOC, &hole_em->flags))
+                               set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
                } else {
                        em->start = range_start;
                        em->len = found;
@@ -6929,11 +6969,9 @@ static int btrfs_truncate(struct inode *inode)
 
        /*
         * 1 for the truncate slack space
-        * 1 for the orphan item we're going to add
-        * 1 for the orphan item deletion
         * 1 for updating the inode.
         */
-       trans = btrfs_start_transaction(root, 4);
+       trans = btrfs_start_transaction(root, 2);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
                goto out;
@@ -6944,12 +6982,6 @@ static int btrfs_truncate(struct inode *inode)
                                      min_size);
        BUG_ON(ret);
 
-       ret = btrfs_orphan_add(trans, inode);
-       if (ret) {
-               btrfs_end_transaction(trans, root);
-               goto out;
-       }
-
        /*
         * setattr is responsible for setting the ordered_data_close flag,
         * but that is only tested during the last file release.  That
@@ -7018,12 +7050,6 @@ static int btrfs_truncate(struct inode *inode)
                ret = btrfs_orphan_del(trans, inode);
                if (ret)
                        err = ret;
-       } else if (ret && inode->i_nlink > 0) {
-               /*
-                * Failed to do the truncate, remove us from the in memory
-                * orphan list.
-                */
-               ret = btrfs_orphan_del(NULL, inode);
        }
 
        if (trans) {
@@ -7545,41 +7571,61 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work)
  */
 int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
-       struct list_head *head = &root->fs_info->delalloc_inodes;
        struct btrfs_inode *binode;
        struct inode *inode;
        struct btrfs_delalloc_work *work, *next;
        struct list_head works;
+       struct list_head splice;
        int ret = 0;
 
        if (root->fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
 
        INIT_LIST_HEAD(&works);
-
+       INIT_LIST_HEAD(&splice);
+again:
        spin_lock(&root->fs_info->delalloc_lock);
-       while (!list_empty(head)) {
-               binode = list_entry(head->next, struct btrfs_inode,
+       list_splice_init(&root->fs_info->delalloc_inodes, &splice);
+       while (!list_empty(&splice)) {
+               binode = list_entry(splice.next, struct btrfs_inode,
                                    delalloc_inodes);
+
+               list_del_init(&binode->delalloc_inodes);
+
                inode = igrab(&binode->vfs_inode);
                if (!inode)
-                       list_del_init(&binode->delalloc_inodes);
+                       continue;
+
+               list_add_tail(&binode->delalloc_inodes,
+                             &root->fs_info->delalloc_inodes);
                spin_unlock(&root->fs_info->delalloc_lock);
-               if (inode) {
-                       work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
-                       if (!work) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       list_add_tail(&work->list, &works);
-                       btrfs_queue_worker(&root->fs_info->flush_workers,
-                                          &work->work);
+
+               work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
+               if (unlikely(!work)) {
+                       ret = -ENOMEM;
+                       goto out;
                }
+               list_add_tail(&work->list, &works);
+               btrfs_queue_worker(&root->fs_info->flush_workers,
+                                  &work->work);
+
                cond_resched();
                spin_lock(&root->fs_info->delalloc_lock);
        }
        spin_unlock(&root->fs_info->delalloc_lock);
 
+       list_for_each_entry_safe(work, next, &works, list) {
+               list_del_init(&work->list);
+               btrfs_wait_and_free_delalloc_work(work);
+       }
+
+       spin_lock(&root->fs_info->delalloc_lock);
+       if (!list_empty(&root->fs_info->delalloc_inodes)) {
+               spin_unlock(&root->fs_info->delalloc_lock);
+               goto again;
+       }
+       spin_unlock(&root->fs_info->delalloc_lock);
+
        /* the filemap_flush will queue IO into the worker threads, but
         * we have to make sure the IO is actually started and that
         * ordered extents get created before we return
@@ -7592,11 +7638,18 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
                    atomic_read(&root->fs_info->async_delalloc_pages) == 0));
        }
        atomic_dec(&root->fs_info->async_submit_draining);
+       return 0;
 out:
        list_for_each_entry_safe(work, next, &works, list) {
                list_del_init(&work->list);
                btrfs_wait_and_free_delalloc_work(work);
        }
+
+       if (!list_empty_careful(&splice)) {
+               spin_lock(&root->fs_info->delalloc_lock);
+               list_splice_tail(&splice, &root->fs_info->delalloc_inodes);
+               spin_unlock(&root->fs_info->delalloc_lock);
+       }
        return ret;
 }
 
index 4b4516770f055432964da1e82fe591e1e2128ef8..338f2597bf7f8da2215e0d87289b01c94f9cfe7c 100644 (file)
@@ -515,7 +515,6 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        BUG_ON(ret);
 
-       d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
        if (async_transid) {
                *async_transid = trans->transid;
@@ -525,6 +524,10 @@ fail:
        }
        if (err && !ret)
                ret = err;
+
+       if (!ret)
+               d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
+
        return ret;
 }
 
@@ -1339,7 +1342,8 @@ static noinline int btrfs_ioctl_resize(struct file *file,
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               mnt_drop_write_file(file);
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -1362,6 +1366,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                printk(KERN_INFO "btrfs: resizing devid %llu\n",
                       (unsigned long long)devid);
        }
+
        device = btrfs_find_device(root->fs_info, devid, NULL, NULL);
        if (!device) {
                printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
@@ -1369,9 +1374,10 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                ret = -EINVAL;
                goto out_free;
        }
-       if (device->fs_devices && device->fs_devices->seeding) {
+
+       if (!device->writeable) {
                printk(KERN_INFO "btrfs: resizer unable to apply on "
-                      "seeding device %llu\n",
+                      "readonly device %llu\n",
                       (unsigned long long)devid);
                ret = -EINVAL;
                goto out_free;
@@ -1443,8 +1449,8 @@ out_free:
        kfree(vol_args);
 out:
        mutex_unlock(&root->fs_info->volume_mutex);
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -2095,13 +2101,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
                if (err)
                        goto out_dput;
-
-               /* check if subvolume may be deleted by a non-root user */
-               err = btrfs_may_delete(dir, dentry, 1);
-               if (err)
-                       goto out_dput;
        }
 
+       /* check if subvolume may be deleted by a user */
+       err = btrfs_may_delete(dir, dentry, 1);
+       if (err)
+               goto out_dput;
+
        if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
                err = -EINVAL;
                goto out_dput;
@@ -2183,19 +2189,20 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
        struct btrfs_ioctl_defrag_range_args *range;
        int ret;
 
-       if (btrfs_root_readonly(root))
-               return -EROFS;
+       ret = mnt_want_write_file(file);
+       if (ret)
+               return ret;
 
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               mnt_drop_write_file(file);
+               return -EINVAL;
        }
-       ret = mnt_want_write_file(file);
-       if (ret) {
-               atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-                          0);
-               return ret;
+
+       if (btrfs_root_readonly(root)) {
+               ret = -EROFS;
+               goto out;
        }
 
        switch (inode->i_mode & S_IFMT) {
@@ -2247,8 +2254,8 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
                ret = -EINVAL;
        }
 out:
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -2263,7 +2270,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -2300,7 +2307,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
                mnt_drop_write_file(file);
-               return -EINPROGRESS;
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -2316,8 +2323,8 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        kfree(vol_args);
 out:
        mutex_unlock(&root->fs_info->volume_mutex);
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -3437,8 +3444,8 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_ioctl_balance_args *bargs;
        struct btrfs_balance_control *bctl;
+       bool need_unlock; /* for mut. excl. ops lock */
        int ret;
-       int need_to_clear_lock = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -3447,14 +3454,61 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        if (ret)
                return ret;
 
-       mutex_lock(&fs_info->volume_mutex);
+again:
+       if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+               mutex_lock(&fs_info->volume_mutex);
+               mutex_lock(&fs_info->balance_mutex);
+               need_unlock = true;
+               goto locked;
+       }
+
+       /*
+        * mut. excl. ops lock is locked.  Three possibilites:
+        *   (1) some other op is running
+        *   (2) balance is running
+        *   (3) balance is paused -- special case (think resume)
+        */
        mutex_lock(&fs_info->balance_mutex);
+       if (fs_info->balance_ctl) {
+               /* this is either (2) or (3) */
+               if (!atomic_read(&fs_info->balance_running)) {
+                       mutex_unlock(&fs_info->balance_mutex);
+                       if (!mutex_trylock(&fs_info->volume_mutex))
+                               goto again;
+                       mutex_lock(&fs_info->balance_mutex);
+
+                       if (fs_info->balance_ctl &&
+                           !atomic_read(&fs_info->balance_running)) {
+                               /* this is (3) */
+                               need_unlock = false;
+                               goto locked;
+                       }
+
+                       mutex_unlock(&fs_info->balance_mutex);
+                       mutex_unlock(&fs_info->volume_mutex);
+                       goto again;
+               } else {
+                       /* this is (2) */
+                       mutex_unlock(&fs_info->balance_mutex);
+                       ret = -EINPROGRESS;
+                       goto out;
+               }
+       } else {
+               /* this is (1) */
+               mutex_unlock(&fs_info->balance_mutex);
+               pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+locked:
+       BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
 
        if (arg) {
                bargs = memdup_user(arg, sizeof(*bargs));
                if (IS_ERR(bargs)) {
                        ret = PTR_ERR(bargs);
-                       goto out;
+                       goto out_unlock;
                }
 
                if (bargs->flags & BTRFS_BALANCE_RESUME) {
@@ -3474,13 +3528,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
                bargs = NULL;
        }
 
-       if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
-                       1)) {
-               pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+       if (fs_info->balance_ctl) {
                ret = -EINPROGRESS;
                goto out_bargs;
        }
-       need_to_clear_lock = 1;
 
        bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
        if (!bctl) {
@@ -3501,11 +3552,17 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        }
 
 do_balance:
-       ret = btrfs_balance(bctl, bargs);
        /*
-        * bctl is freed in __cancel_balance or in free_fs_info if
-        * restriper was paused all the way until unmount
+        * Ownership of bctl and mutually_exclusive_operation_running
+        * goes to to btrfs_balance.  bctl is freed in __cancel_balance,
+        * or, if restriper was paused all the way until unmount, in
+        * free_fs_info.  mutually_exclusive_operation_running is
+        * cleared in __cancel_balance.
         */
+       need_unlock = false;
+
+       ret = btrfs_balance(bctl, bargs);
+
        if (arg) {
                if (copy_to_user(arg, bargs, sizeof(*bargs)))
                        ret = -EFAULT;
@@ -3513,12 +3570,12 @@ do_balance:
 
 out_bargs:
        kfree(bargs);
-out:
-       if (need_to_clear_lock)
-               atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-                          0);
+out_unlock:
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
+       if (need_unlock)
+               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+out:
        mnt_drop_write_file(file);
        return ret;
 }
@@ -3698,6 +3755,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
                goto drop_write;
        }
 
+       if (!sa->qgroupid) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
index f107312970405da1e3218118a8d0555894955c59..e5ed56729607a82246cac22a229d105efa562509 100644 (file)
@@ -836,9 +836,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
         * if the disk i_size is already at the inode->i_size, or
         * this ordered extent is inside the disk i_size, we're done
         */
-       if (disk_i_size == i_size || offset <= disk_i_size) {
+       if (disk_i_size == i_size)
+               goto out;
+
+       /*
+        * We still need to update disk_i_size if outstanding_isize is greater
+        * than disk_i_size.
+        */
+       if (offset <= disk_i_size &&
+           (!ordered || ordered->outstanding_isize <= disk_i_size))
                goto out;
-       }
 
        /*
         * walk backward from this ordered extent to disk_i_size.
@@ -870,7 +877,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                        break;
                if (test->file_offset >= i_size)
                        break;
-               if (test->file_offset >= disk_i_size) {
+               if (entry_end(test) > disk_i_size) {
                        /*
                         * we don't update disk_i_size now, so record this
                         * undealt i_size. Or we will not know the real
index fe9d02c45f8e521f87b44d6deff3e5f8d99aa3a9..a5c856234323241c22dde18e1ee072c8bed3ccaa 100644 (file)
@@ -379,6 +379,13 @@ next1:
 
                ret = add_relation_rb(fs_info, found_key.objectid,
                                      found_key.offset);
+               if (ret == -ENOENT) {
+                       printk(KERN_WARNING
+                               "btrfs: orphan qgroup relation 0x%llx->0x%llx\n",
+                               (unsigned long long)found_key.objectid,
+                               (unsigned long long)found_key.offset);
+                       ret = 0;        /* ignore the error */
+               }
                if (ret)
                        goto out;
 next2:
@@ -956,17 +963,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
                        struct btrfs_fs_info *fs_info, u64 qgroupid)
 {
        struct btrfs_root *quota_root;
+       struct btrfs_qgroup *qgroup;
        int ret = 0;
 
        quota_root = fs_info->quota_root;
        if (!quota_root)
                return -EINVAL;
 
+       /* check if there are no relations to this qgroup */
+       spin_lock(&fs_info->qgroup_lock);
+       qgroup = find_qgroup_rb(fs_info, qgroupid);
+       if (qgroup) {
+               if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) {
+                       spin_unlock(&fs_info->qgroup_lock);
+                       return -EBUSY;
+               }
+       }
+       spin_unlock(&fs_info->qgroup_lock);
+
        ret = del_qgroup_item(trans, quota_root, qgroupid);
 
        spin_lock(&fs_info->qgroup_lock);
        del_qgroup_rb(quota_root->fs_info, qgroupid);
-
        spin_unlock(&fs_info->qgroup_lock);
 
        return ret;
index bdbb94f245c9070802c65acb6eba392ba1a4c932..67783e03d1211bdcba1e84a20aa56a528916c370 100644 (file)
@@ -580,20 +580,29 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
        int corrected = 0;
        struct btrfs_key key;
        struct inode *inode = NULL;
+       struct btrfs_fs_info *fs_info;
        u64 end = offset + PAGE_SIZE - 1;
        struct btrfs_root *local_root;
+       int srcu_index;
 
        key.objectid = root;
        key.type = BTRFS_ROOT_ITEM_KEY;
        key.offset = (u64)-1;
-       local_root = btrfs_read_fs_root_no_name(fixup->root->fs_info, &key);
-       if (IS_ERR(local_root))
+
+       fs_info = fixup->root->fs_info;
+       srcu_index = srcu_read_lock(&fs_info->subvol_srcu);
+
+       local_root = btrfs_read_fs_root_no_name(fs_info, &key);
+       if (IS_ERR(local_root)) {
+               srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
                return PTR_ERR(local_root);
+       }
 
        key.type = BTRFS_INODE_ITEM_KEY;
        key.objectid = inum;
        key.offset = 0;
-       inode = btrfs_iget(fixup->root->fs_info->sb, &key, local_root, NULL);
+       inode = btrfs_iget(fs_info->sb, &key, local_root, NULL);
+       srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
@@ -606,7 +615,6 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
        }
 
        if (PageUptodate(page)) {
-               struct btrfs_fs_info *fs_info;
                if (PageDirty(page)) {
                        /*
                         * we need to write the data to the defect sector. the
@@ -3180,18 +3188,25 @@ static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx)
        u64 physical_for_dev_replace;
        u64 len;
        struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info;
+       int srcu_index;
 
        key.objectid = root;
        key.type = BTRFS_ROOT_ITEM_KEY;
        key.offset = (u64)-1;
+
+       srcu_index = srcu_read_lock(&fs_info->subvol_srcu);
+
        local_root = btrfs_read_fs_root_no_name(fs_info, &key);
-       if (IS_ERR(local_root))
+       if (IS_ERR(local_root)) {
+               srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
                return PTR_ERR(local_root);
+       }
 
        key.type = BTRFS_INODE_ITEM_KEY;
        key.objectid = inum;
        key.offset = 0;
        inode = btrfs_iget(fs_info->sb, &key, local_root, NULL);
+       srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
index 54454542ad4073352ddcabf27fd9e0bc528e2136..321b7fb4e4417573e9c404069c6b249afb8ab488 100644 (file)
@@ -1814,8 +1814,10 @@ static int name_cache_insert(struct send_ctx *sctx,
                        (unsigned long)nce->ino);
        if (!nce_head) {
                nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS);
-               if (!nce_head)
+               if (!nce_head) {
+                       kfree(nce);
                        return -ENOMEM;
+               }
                INIT_LIST_HEAD(nce_head);
 
                ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head);
index 99545df1b86c18071fed0cbf68dcbb8e745d5524..d8982e9601d37862e6405df95df15c1ba34eecb9 100644 (file)
@@ -267,7 +267,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
                             function, line, errstr);
                return;
        }
-       trans->transaction->aborted = errno;
+       ACCESS_ONCE(trans->transaction->aborted) = errno;
        __btrfs_std_error(root->fs_info, function, line, errno, NULL);
 }
 /*
index 87fac9a21ea56578625536ac1229678e854ec5f7..fc03aa60b68440862e4884f90cb88113d15610a7 100644 (file)
@@ -333,12 +333,14 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
                                          &root->fs_info->trans_block_rsv,
                                          num_bytes, flush);
                if (ret)
-                       return ERR_PTR(ret);
+                       goto reserve_fail;
        }
 again:
        h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
-       if (!h)
-               return ERR_PTR(-ENOMEM);
+       if (!h) {
+               ret = -ENOMEM;
+               goto alloc_fail;
+       }
 
        /*
         * If we are JOIN_NOLOCK we're already committing a transaction and
@@ -365,11 +367,7 @@ again:
        if (ret < 0) {
                /* We must get the transaction if we are JOIN_NOLOCK. */
                BUG_ON(type == TRANS_JOIN_NOLOCK);
-
-               if (type < TRANS_JOIN_NOLOCK)
-                       sb_end_intwrite(root->fs_info->sb);
-               kmem_cache_free(btrfs_trans_handle_cachep, h);
-               return ERR_PTR(ret);
+               goto join_fail;
        }
 
        cur_trans = root->fs_info->running_transaction;
@@ -410,6 +408,19 @@ got_it:
        if (!current->journal_info && type != TRANS_USERSPACE)
                current->journal_info = h;
        return h;
+
+join_fail:
+       if (type < TRANS_JOIN_NOLOCK)
+               sb_end_intwrite(root->fs_info->sb);
+       kmem_cache_free(btrfs_trans_handle_cachep, h);
+alloc_fail:
+       if (num_bytes)
+               btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv,
+                                       num_bytes);
+reserve_fail:
+       if (qgroup_reserved)
+               btrfs_qgroup_free(root, qgroup_reserved);
+       return ERR_PTR(ret);
 }
 
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
@@ -1468,7 +1479,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                goto cleanup_transaction;
        }
 
-       if (cur_trans->aborted) {
+       /* Stop the commit early if ->aborted is set */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
                ret = cur_trans->aborted;
                goto cleanup_transaction;
        }
@@ -1574,6 +1586,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        wait_event(cur_trans->writer_wait,
                   atomic_read(&cur_trans->num_writers) == 1);
 
+       /* ->aborted might be set after the previous check, so check it */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+               ret = cur_trans->aborted;
+               goto cleanup_transaction;
+       }
        /*
         * the reloc mutex makes sure that we stop
         * the balancing code from coming in and moving
@@ -1657,6 +1674,17 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                goto cleanup_transaction;
        }
 
+       /*
+        * The tasks which save the space cache and inode cache may also
+        * update ->aborted, check it.
+        */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+               ret = cur_trans->aborted;
+               mutex_unlock(&root->fs_info->tree_log_mutex);
+               mutex_unlock(&root->fs_info->reloc_mutex);
+               goto cleanup_transaction;
+       }
+
        btrfs_prepare_extent_commit(trans, root);
 
        cur_trans = root->fs_info->running_transaction;
index 83186c7e45d40db89192abad9da56628874cf5d1..9027bb1e74660758328a3d133fe58b59ddc460e6 100644 (file)
@@ -3357,6 +3357,11 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
        if (skip_csum)
                return 0;
 
+       if (em->compress_type) {
+               csum_offset = 0;
+               csum_len = block_len;
+       }
+
        /* block start is already adjusted for the file extent offset. */
        ret = btrfs_lookup_csums_range(log->fs_info->csum_root,
                                       em->block_start + csum_offset,
@@ -3410,13 +3415,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
                em = list_entry(extents.next, struct extent_map, list);
 
                list_del_init(&em->list);
-               clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
 
                /*
                 * If we had an error we just need to delete everybody from our
                 * private list.
                 */
                if (ret) {
+                       clear_em_logging(tree, em);
                        free_extent_map(em);
                        continue;
                }
@@ -3424,8 +3429,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
                write_unlock(&tree->lock);
 
                ret = log_one_extent(trans, inode, root, em, path);
-               free_extent_map(em);
                write_lock(&tree->lock);
+               clear_em_logging(tree, em);
+               free_extent_map(em);
        }
        WARN_ON(!list_empty(&extents));
        write_unlock(&tree->lock);
index 5cce6aa7401287322c31673cf039f0e32918c6c4..5cbb7f4b16720fc3c3442ffb09752983195836a5 100644 (file)
@@ -1431,7 +1431,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
                }
        } else {
                ret = btrfs_get_bdev_and_sb(device_path,
-                                           FMODE_READ | FMODE_EXCL,
+                                           FMODE_WRITE | FMODE_EXCL,
                                            root->fs_info->bdev_holder, 0,
                                            &bdev, &bh);
                if (ret)
@@ -1556,7 +1556,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        ret = 0;
 
        /* Notify udev that device has changed */
-       btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
+       if (bdev)
+               btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
 
 error_brelse:
        brelse(bh);
@@ -2614,7 +2615,14 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
        cache = btrfs_lookup_block_group(fs_info, chunk_offset);
        chunk_used = btrfs_block_group_used(&cache->item);
 
-       user_thresh = div_factor_fine(cache->key.offset, bargs->usage);
+       if (bargs->usage == 0)
+               user_thresh = 0;
+       else if (bargs->usage > 100)
+               user_thresh = cache->key.offset;
+       else
+               user_thresh = div_factor_fine(cache->key.offset,
+                                             bargs->usage);
+
        if (chunk_used < user_thresh)
                ret = 0;
 
@@ -2959,6 +2967,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
        unset_balance_control(fs_info);
        ret = del_balance_item(fs_info->tree_root);
        BUG_ON(ret);
+
+       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 }
 
 void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
@@ -3138,8 +3148,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
 out:
        if (bctl->flags & BTRFS_BALANCE_RESUME)
                __cancel_balance(fs_info);
-       else
+       else {
                kfree(bctl);
+               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       }
        return ret;
 }
 
@@ -3156,7 +3168,6 @@ static int balance_kthread(void *data)
                ret = btrfs_balance(fs_info->balance_ctl, NULL);
        }
 
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
 
@@ -3179,7 +3190,6 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
                return 0;
        }
 
-       WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
        tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
        if (IS_ERR(tsk))
                return PTR_ERR(tsk);
@@ -3233,6 +3243,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
        btrfs_balance_sys(leaf, item, &disk_bargs);
        btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
 
+       WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
+
        mutex_lock(&fs_info->volume_mutex);
        mutex_lock(&fs_info->balance_mutex);
 
@@ -3496,7 +3508,7 @@ struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        { 1, 1, 2, 2, 2, 2 /* raid1 */ },
        { 1, 2, 1, 1, 1, 2 /* dup */ },
        { 1, 1, 0, 2, 1, 1 /* raid0 */ },
-       { 1, 1, 0, 1, 1, 1 /* single */ },
+       { 1, 1, 1, 1, 1, 1 /* single */ },
 };
 
 static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
index c017a2dfb9097e73837230d244ffb14f73dd0e1c..7a75c3e0fd5896b7fc59595fff859c41f23f65b1 100644 (file)
@@ -2935,6 +2935,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
                void *kaddr = kmap_atomic(bh->b_page);
                memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes);
                kunmap_atomic(kaddr);
+               flush_dcache_page(bh->b_page);
        }
 }
 
index 67bef6d01484a1b058f6513fce1277db72903650..746ce532e130ac3f49b7a31096b95fda6ef1d18e 100644 (file)
@@ -41,12 +41,12 @@ static struct fscache_object *cachefiles_alloc_object(
 
        _enter("{%s},%p,", cache->cache.identifier, cookie);
 
-       lookup_data = kmalloc(sizeof(*lookup_data), GFP_KERNEL);
+       lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp);
        if (!lookup_data)
                goto nomem_lookup_data;
 
        /* create a new object record and a temporary leaf image */
-       object = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL);
+       object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp);
        if (!object)
                goto nomem_object;
 
@@ -63,7 +63,7 @@ static struct fscache_object *cachefiles_alloc_object(
         * - stick the length on the front and leave space on the back for the
         *   encoder
         */
-       buffer = kmalloc((2 + 512) + 3, GFP_KERNEL);
+       buffer = kmalloc((2 + 512) + 3, cachefiles_gfp);
        if (!buffer)
                goto nomem_buffer;
 
@@ -219,7 +219,7 @@ static void cachefiles_update_object(struct fscache_object *_object)
                return;
        }
 
-       auxdata = kmalloc(2 + 512 + 3, GFP_KERNEL);
+       auxdata = kmalloc(2 + 512 + 3, cachefiles_gfp);
        if (!auxdata) {
                _leave(" [nomem]");
                return;
@@ -440,6 +440,54 @@ truncate_failed:
        return ret;
 }
 
+/*
+ * Invalidate an object
+ */
+static void cachefiles_invalidate_object(struct fscache_operation *op)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+       const struct cred *saved_cred;
+       struct path path;
+       uint64_t ni_size;
+       int ret;
+
+       object = container_of(op->object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache,
+                            struct cachefiles_cache, cache);
+
+       op->object->cookie->def->get_attr(op->object->cookie->netfs_data,
+                                         &ni_size);
+
+       _enter("{OBJ%x},[%llu]",
+              op->object->debug_id, (unsigned long long)ni_size);
+
+       if (object->backer) {
+               ASSERT(S_ISREG(object->backer->d_inode->i_mode));
+
+               fscache_set_store_limit(&object->fscache, ni_size);
+
+               path.dentry = object->backer;
+               path.mnt = cache->mnt;
+
+               cachefiles_begin_secure(cache, &saved_cred);
+               ret = vfs_truncate(&path, 0);
+               if (ret == 0)
+                       ret = vfs_truncate(&path, ni_size);
+               cachefiles_end_secure(cache, saved_cred);
+
+               if (ret != 0) {
+                       fscache_set_store_limit(&object->fscache, 0);
+                       if (ret == -EIO)
+                               cachefiles_io_error_obj(object,
+                                                       "Invalidate failed");
+               }
+       }
+
+       fscache_op_complete(op, true);
+       _leave("");
+}
+
 /*
  * dissociate a cache from all the pages it was backing
  */
@@ -455,6 +503,7 @@ const struct fscache_cache_ops cachefiles_cache_ops = {
        .lookup_complete        = cachefiles_lookup_complete,
        .grab_object            = cachefiles_grab_object,
        .update_object          = cachefiles_update_object,
+       .invalidate_object      = cachefiles_invalidate_object,
        .drop_object            = cachefiles_drop_object,
        .put_object             = cachefiles_put_object,
        .sync_cache             = cachefiles_sync_cache,
index bd6bc1bde2d725afc0260ddc77502d5031dcee98..49382519907a28ec7addc1f3a6257871cba9a025 100644 (file)
@@ -23,6 +23,8 @@ extern unsigned cachefiles_debug;
 #define CACHEFILES_DEBUG_KLEAVE        2
 #define CACHEFILES_DEBUG_KDEBUG        4
 
+#define cachefiles_gfp (__GFP_WAIT | __GFP_NORETRY | __GFP_NOMEMALLOC)
+
 /*
  * node records
  */
index 81b8b2b3a67476e238650701561474d7c90ed04a..33b58c60f2d11ff83662b6d23b144daf4ee44712 100644 (file)
@@ -78,7 +78,7 @@ char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
 
        _debug("max: %d", max);
 
-       key = kmalloc(max, GFP_KERNEL);
+       key = kmalloc(max, cachefiles_gfp);
        if (!key)
                return NULL;
 
index b0b5f7cdfffa98de3e30e0857d64bf954e8b3518..8c01c5fcdf75c32bab21a6265599ba2a02cdee83 100644 (file)
@@ -40,8 +40,7 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
        printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
               prefix, fscache_object_states[object->fscache.state],
               object->fscache.flags, work_busy(&object->fscache.work),
-              object->fscache.events,
-              object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK);
+              object->fscache.events, object->fscache.event_mask);
        printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
               prefix, object->fscache.n_ops, object->fscache.n_in_progress,
               object->fscache.n_exclusive);
index c994691d94454254cfcb75e796b6fcaaeab8e2b1..480992259707fe4f932646353245a640c5c9dfec 100644 (file)
@@ -77,25 +77,25 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,
        struct page *backpage = monitor->back_page, *backpage2;
        int ret;
 
-       kenter("{ino=%lx},{%lx,%lx}",
+       _enter("{ino=%lx},{%lx,%lx}",
               object->backer->d_inode->i_ino,
               backpage->index, backpage->flags);
 
        /* skip if the page was truncated away completely */
        if (backpage->mapping != bmapping) {
-               kleave(" = -ENODATA [mapping]");
+               _leave(" = -ENODATA [mapping]");
                return -ENODATA;
        }
 
        backpage2 = find_get_page(bmapping, backpage->index);
        if (!backpage2) {
-               kleave(" = -ENODATA [gone]");
+               _leave(" = -ENODATA [gone]");
                return -ENODATA;
        }
 
        if (backpage != backpage2) {
                put_page(backpage2);
-               kleave(" = -ENODATA [different]");
+               _leave(" = -ENODATA [different]");
                return -ENODATA;
        }
 
@@ -114,7 +114,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,
                if (PageUptodate(backpage))
                        goto unlock_discard;
 
-               kdebug("reissue read");
+               _debug("reissue read");
                ret = bmapping->a_ops->readpage(NULL, backpage);
                if (ret < 0)
                        goto unlock_discard;
@@ -129,7 +129,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,
        }
 
        /* it'll reappear on the todo list */
-       kleave(" = -EINPROGRESS");
+       _leave(" = -EINPROGRESS");
        return -EINPROGRESS;
 
 unlock_discard:
@@ -137,7 +137,7 @@ unlock_discard:
        spin_lock_irq(&object->work_lock);
        list_del(&monitor->op_link);
        spin_unlock_irq(&object->work_lock);
-       kleave(" = %d", ret);
+       _leave(" = %d", ret);
        return ret;
 }
 
@@ -174,11 +174,13 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
                _debug("- copy {%lu}", monitor->back_page->index);
 
        recheck:
-               if (PageUptodate(monitor->back_page)) {
+               if (test_bit(FSCACHE_COOKIE_INVALIDATING,
+                            &object->fscache.cookie->flags)) {
+                       error = -ESTALE;
+               } else if (PageUptodate(monitor->back_page)) {
                        copy_highpage(monitor->netfs_page, monitor->back_page);
-
-                       pagevec_add(&pagevec, monitor->netfs_page);
-                       fscache_mark_pages_cached(monitor->op, &pagevec);
+                       fscache_mark_page_cached(monitor->op,
+                                                monitor->netfs_page);
                        error = 0;
                } else if (!PageError(monitor->back_page)) {
                        /* the page has probably been truncated */
@@ -198,6 +200,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
 
                fscache_end_io(op, monitor->netfs_page, error);
                page_cache_release(monitor->netfs_page);
+               fscache_retrieval_complete(op, 1);
                fscache_put_retrieval(op);
                kfree(monitor);
 
@@ -239,7 +242,7 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
        _debug("read back %p{%lu,%d}",
               netpage, netpage->index, page_count(netpage));
 
-       monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
+       monitor = kzalloc(sizeof(*monitor), cachefiles_gfp);
        if (!monitor)
                goto nomem;
 
@@ -258,13 +261,14 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
                        goto backing_page_already_present;
 
                if (!newpage) {
-                       newpage = page_cache_alloc_cold(bmapping);
+                       newpage = __page_cache_alloc(cachefiles_gfp |
+                                                    __GFP_COLD);
                        if (!newpage)
                                goto nomem_monitor;
                }
 
                ret = add_to_page_cache(newpage, bmapping,
-                                       netpage->index, GFP_KERNEL);
+                                       netpage->index, cachefiles_gfp);
                if (ret == 0)
                        goto installed_new_backing_page;
                if (ret != -EEXIST)
@@ -335,11 +339,11 @@ backing_page_already_present:
 backing_page_already_uptodate:
        _debug("- uptodate");
 
-       pagevec_add(pagevec, netpage);
-       fscache_mark_pages_cached(op, pagevec);
+       fscache_mark_page_cached(op, netpage);
 
        copy_highpage(netpage, backpage);
        fscache_end_io(op, netpage, 0);
+       fscache_retrieval_complete(op, 1);
 
 success:
        _debug("success");
@@ -357,10 +361,13 @@ out:
 
 read_error:
        _debug("read error %d", ret);
-       if (ret == -ENOMEM)
+       if (ret == -ENOMEM) {
+               fscache_retrieval_complete(op, 1);
                goto out;
+       }
 io_error:
        cachefiles_io_error_obj(object, "Page read error on backing file");
+       fscache_retrieval_complete(op, 1);
        ret = -ENOBUFS;
        goto out;
 
@@ -370,6 +377,7 @@ nomem_monitor:
        fscache_put_retrieval(monitor->op);
        kfree(monitor);
 nomem:
+       fscache_retrieval_complete(op, 1);
        _leave(" = -ENOMEM");
        return -ENOMEM;
 }
@@ -408,7 +416,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
        _enter("{%p},{%lx},,,", object, page->index);
 
        if (!object->backer)
-               return -ENOBUFS;
+               goto enobufs;
 
        inode = object->backer->d_inode;
        ASSERT(S_ISREG(inode->i_mode));
@@ -417,7 +425,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
 
        /* calculate the shift required to use bmap */
        if (inode->i_sb->s_blocksize > PAGE_SIZE)
-               return -ENOBUFS;
+               goto enobufs;
 
        shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
 
@@ -448,15 +456,20 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
                                                       &pagevec);
        } else if (cachefiles_has_space(cache, 0, 1) == 0) {
                /* there's space in the cache we can use */
-               pagevec_add(&pagevec, page);
-               fscache_mark_pages_cached(op, &pagevec);
+               fscache_mark_page_cached(op, page);
+               fscache_retrieval_complete(op, 1);
                ret = -ENODATA;
        } else {
-               ret = -ENOBUFS;
+               goto enobufs;
        }
 
        _leave(" = %d", ret);
        return ret;
+
+enobufs:
+       fscache_retrieval_complete(op, 1);
+       _leave(" = -ENOBUFS");
+       return -ENOBUFS;
 }
 
 /*
@@ -465,8 +478,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
  */
 static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                        struct fscache_retrieval *op,
-                                       struct list_head *list,
-                                       struct pagevec *mark_pvec)
+                                       struct list_head *list)
 {
        struct cachefiles_one_read *monitor = NULL;
        struct address_space *bmapping = object->backer->d_inode->i_mapping;
@@ -485,7 +497,7 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                       netpage, netpage->index, page_count(netpage));
 
                if (!monitor) {
-                       monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
+                       monitor = kzalloc(sizeof(*monitor), cachefiles_gfp);
                        if (!monitor)
                                goto nomem;
 
@@ -500,13 +512,14 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                goto backing_page_already_present;
 
                        if (!newpage) {
-                               newpage = page_cache_alloc_cold(bmapping);
+                               newpage = __page_cache_alloc(cachefiles_gfp |
+                                                            __GFP_COLD);
                                if (!newpage)
                                        goto nomem;
                        }
 
                        ret = add_to_page_cache(newpage, bmapping,
-                                               netpage->index, GFP_KERNEL);
+                                               netpage->index, cachefiles_gfp);
                        if (ret == 0)
                                goto installed_new_backing_page;
                        if (ret != -EEXIST)
@@ -536,10 +549,11 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                _debug("- monitor add");
 
                ret = add_to_page_cache(netpage, op->mapping, netpage->index,
-                                       GFP_KERNEL);
+                                       cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
                                page_cache_release(netpage);
+                               fscache_retrieval_complete(op, 1);
                                continue;
                        }
                        goto nomem;
@@ -612,10 +626,11 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                _debug("- uptodate");
 
                ret = add_to_page_cache(netpage, op->mapping, netpage->index,
-                                       GFP_KERNEL);
+                                       cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
                                page_cache_release(netpage);
+                               fscache_retrieval_complete(op, 1);
                                continue;
                        }
                        goto nomem;
@@ -626,16 +641,17 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                page_cache_release(backpage);
                backpage = NULL;
 
-               if (!pagevec_add(mark_pvec, netpage))
-                       fscache_mark_pages_cached(op, mark_pvec);
+               fscache_mark_page_cached(op, netpage);
 
                page_cache_get(netpage);
                if (!pagevec_add(&lru_pvec, netpage))
                        __pagevec_lru_add_file(&lru_pvec);
 
+               /* the netpage is unlocked and marked up to date here */
                fscache_end_io(op, netpage, 0);
                page_cache_release(netpage);
                netpage = NULL;
+               fscache_retrieval_complete(op, 1);
                continue;
        }
 
@@ -661,6 +677,7 @@ out:
        list_for_each_entry_safe(netpage, _n, list, lru) {
                list_del(&netpage->lru);
                page_cache_release(netpage);
+               fscache_retrieval_complete(op, 1);
        }
 
        _leave(" = %d", ret);
@@ -669,15 +686,17 @@ out:
 nomem:
        _debug("nomem");
        ret = -ENOMEM;
-       goto out;
+       goto record_page_complete;
 
 read_error:
        _debug("read error %d", ret);
        if (ret == -ENOMEM)
-               goto out;
+               goto record_page_complete;
 io_error:
        cachefiles_io_error_obj(object, "Page read error on backing file");
        ret = -ENOBUFS;
+record_page_complete:
+       fscache_retrieval_complete(op, 1);
        goto out;
 }
 
@@ -709,7 +728,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
               *nr_pages);
 
        if (!object->backer)
-               return -ENOBUFS;
+               goto all_enobufs;
 
        space = 1;
        if (cachefiles_has_space(cache, 0, *nr_pages) < 0)
@@ -722,7 +741,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
 
        /* calculate the shift required to use bmap */
        if (inode->i_sb->s_blocksize > PAGE_SIZE)
-               return -ENOBUFS;
+               goto all_enobufs;
 
        shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
 
@@ -762,7 +781,10 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
                        nrbackpages++;
                } else if (space && pagevec_add(&pagevec, page) == 0) {
                        fscache_mark_pages_cached(op, &pagevec);
+                       fscache_retrieval_complete(op, 1);
                        ret = -ENODATA;
+               } else {
+                       fscache_retrieval_complete(op, 1);
                }
        }
 
@@ -775,18 +797,18 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
        /* submit the apparently valid pages to the backing fs to be read from
         * disk */
        if (nrbackpages > 0) {
-               ret2 = cachefiles_read_backing_file(object, op, &backpages,
-                                                   &pagevec);
+               ret2 = cachefiles_read_backing_file(object, op, &backpages);
                if (ret2 == -ENOMEM || ret2 == -EINTR)
                        ret = ret2;
        }
 
-       if (pagevec_count(&pagevec) > 0)
-               fscache_mark_pages_cached(op, &pagevec);
-
        _leave(" = %d [nr=%u%s]",
               ret, *nr_pages, list_empty(pages) ? " empty" : "");
        return ret;
+
+all_enobufs:
+       fscache_retrieval_complete(op, *nr_pages);
+       return -ENOBUFS;
 }
 
 /*
@@ -806,7 +828,6 @@ int cachefiles_allocate_page(struct fscache_retrieval *op,
 {
        struct cachefiles_object *object;
        struct cachefiles_cache *cache;
-       struct pagevec pagevec;
        int ret;
 
        object = container_of(op->op.object,
@@ -817,14 +838,12 @@ int cachefiles_allocate_page(struct fscache_retrieval *op,
        _enter("%p,{%lx},", object, page->index);
 
        ret = cachefiles_has_space(cache, 0, 1);
-       if (ret == 0) {
-               pagevec_init(&pagevec, 0);
-               pagevec_add(&pagevec, page);
-               fscache_mark_pages_cached(op, &pagevec);
-       } else {
+       if (ret == 0)
+               fscache_mark_page_cached(op, page);
+       else
                ret = -ENOBUFS;
-       }
 
+       fscache_retrieval_complete(op, 1);
        _leave(" = %d", ret);
        return ret;
 }
@@ -874,6 +893,7 @@ int cachefiles_allocate_pages(struct fscache_retrieval *op,
                ret = -ENOBUFS;
        }
 
+       fscache_retrieval_complete(op, *nr_pages);
        _leave(" = %d", ret);
        return ret;
 }
index e18b183b47e1c2e11aa49ad37ec6cf227305f68f..73b46288b54b839c523289a5471a376f14097e9c 100644 (file)
@@ -174,7 +174,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,
        ASSERT(dentry);
        ASSERT(dentry->d_inode);
 
-       auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
+       auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp);
        if (!auxbuf) {
                _leave(" = -ENOMEM");
                return -ENOMEM;
index 6690269f5dde2c5617cff3238167788f93636985..064d1a68d2c1d561cc3cd2b4bf63b511b4a76430 100644 (file)
@@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg)
        kfree(req->r_pages);
 }
 
+static void ceph_unlock_page_vector(struct page **pages, int num_pages)
+{
+       int i;
+
+       for (i = 0; i < num_pages; i++)
+               unlock_page(pages[i]);
+}
+
 /*
  * start an async read(ahead) operation.  return nr_pages we submitted
  * a read for on success, or negative error code.
@@ -347,6 +355,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
        return nr_pages;
 
 out_pages:
+       ceph_unlock_page_vector(pages, nr_pages);
        ceph_release_page_vector(pages, nr_pages);
 out:
        ceph_osdc_put_request(req);
@@ -1078,23 +1087,51 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
                            struct page **pagep, void **fsdata)
 {
        struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *fi = file->private_data;
        struct page *page;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-       int r;
+       int r, want, got = 0;
+
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
+       else
+               want = CEPH_CAP_FILE_BUFFER;
+
+       dout("write_begin %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
+            inode, ceph_vinop(inode), pos, len, inode->i_size);
+       r = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, pos+len);
+       if (r < 0)
+               return r;
+       dout("write_begin %p %llx.%llx %llu~%u  got cap refs on %s\n",
+            inode, ceph_vinop(inode), pos, len, ceph_cap_string(got));
+       if (!(got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO))) {
+               ceph_put_cap_refs(ci, got);
+               return -EAGAIN;
+       }
 
        do {
                /* get a page */
                page = grab_cache_page_write_begin(mapping, index, 0);
-               if (!page)
-                       return -ENOMEM;
-               *pagep = page;
+               if (!page) {
+                       r = -ENOMEM;
+                       break;
+               }
 
                dout("write_begin file %p inode %p page %p %d~%d\n", file,
                     inode, page, (int)pos, (int)len);
 
                r = ceph_update_writeable_page(file, pos, len, page);
+               if (r)
+                       page_cache_release(page);
        } while (r == -EAGAIN);
 
+       if (r) {
+               ceph_put_cap_refs(ci, got);
+       } else {
+               *pagep = page;
+               *(int *)fsdata = got;
+       }
        return r;
 }
 
@@ -1108,10 +1145,12 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
                          struct page *page, void *fsdata)
 {
        struct inode *inode = file->f_dentry->d_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        unsigned from = pos & (PAGE_CACHE_SIZE - 1);
        int check_cap = 0;
+       int got = (unsigned long)fsdata;
 
        dout("write_end file %p inode %p page %p %d~%d (%d)\n", file,
             inode, page, (int)pos, (int)copied, (int)len);
@@ -1134,6 +1173,19 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
        up_read(&mdsc->snap_rwsem);
        page_cache_release(page);
 
+       if (copied > 0) {
+               int dirty;
+               spin_lock(&ci->i_ceph_lock);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               spin_unlock(&ci->i_ceph_lock);
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
+       }
+
+       dout("write_end %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
+            inode, ceph_vinop(inode), pos, len, ceph_cap_string(got));
+       ceph_put_cap_refs(ci, got);
+
        if (check_cap)
                ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY, NULL);
 
index 3251e9cc64014fc99f7660d46388427732c88114..a1d9bb30c1bf9fc5460286ff465e2bcbc338bf30 100644 (file)
@@ -236,8 +236,10 @@ static struct ceph_cap *get_cap(struct ceph_mds_client *mdsc,
        if (!ctx) {
                cap = kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS);
                if (cap) {
+                       spin_lock(&mdsc->caps_list_lock);
                        mdsc->caps_use_count++;
                        mdsc->caps_total_count++;
+                       spin_unlock(&mdsc->caps_list_lock);
                }
                return cap;
        }
@@ -1349,11 +1351,15 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
                if (!ci->i_head_snapc)
                        ci->i_head_snapc = ceph_get_snap_context(
                                ci->i_snap_realm->cached_context);
-               dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode,
-                       ci->i_head_snapc);
+               dout(" inode %p now dirty snapc %p auth cap %p\n",
+                    &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap);
                BUG_ON(!list_empty(&ci->i_dirty_item));
                spin_lock(&mdsc->cap_dirty_lock);
-               list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
+               if (ci->i_auth_cap)
+                       list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
+               else
+                       list_add(&ci->i_dirty_item,
+                                &mdsc->cap_dirty_migrating);
                spin_unlock(&mdsc->cap_dirty_lock);
                if (ci->i_flushing_caps == 0) {
                        ihold(inode);
@@ -2388,7 +2394,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                            &atime);
 
        /* max size increase? */
-       if (max_size != ci->i_max_size) {
+       if (ci->i_auth_cap == cap && max_size != ci->i_max_size) {
                dout("max_size %lld -> %llu\n", ci->i_max_size, max_size);
                ci->i_max_size = max_size;
                if (max_size >= ci->i_wanted_max_size) {
@@ -2745,6 +2751,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
 
        /* make sure we re-request max_size, if necessary */
        spin_lock(&ci->i_ceph_lock);
+       ci->i_wanted_max_size = 0;  /* reset */
        ci->i_requested_max_size = 0;
        spin_unlock(&ci->i_ceph_lock);
 }
@@ -2840,8 +2847,6 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        case CEPH_CAP_OP_IMPORT:
                handle_cap_import(mdsc, inode, h, session,
                                  snaptrace, snaptrace_len);
-               ceph_check_caps(ceph_inode(inode), 0, session);
-               goto done_unlocked;
        }
 
        /* the rest require a cap */
@@ -2858,6 +2863,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        switch (op) {
        case CEPH_CAP_OP_REVOKE:
        case CEPH_CAP_OP_GRANT:
+       case CEPH_CAP_OP_IMPORT:
                handle_cap_grant(inode, h, session, cap, msg->middle);
                goto done_unlocked;
 
index d4dfdcf76d7fdfbff4c318e1e4f5d9a2487d0088..e51558fca3a346a93797561e26e148de037d971a 100644 (file)
@@ -712,63 +712,53 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct ceph_osd_client *osdc =
                &ceph_sb_to_client(inode->i_sb)->client->osdc;
        loff_t endoff = pos + iov->iov_len;
-       int want, got = 0;
-       int ret, err;
+       int got = 0;
+       int ret, err, written;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
 
 retry_snap:
+       written = 0;
        if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL))
                return -ENOSPC;
        __ceph_do_pending_vmtruncate(inode);
-       dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            inode->i_size);
-       if (fi->fmode & CEPH_FILE_MODE_LAZY)
-               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
-       else
-               want = CEPH_CAP_FILE_BUFFER;
-       ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff);
-       if (ret < 0)
-               goto out_put;
-
-       dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            ceph_cap_string(got));
-
-       if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
-           (fi->flags & CEPH_F_SYNC)) {
-               ret = ceph_sync_write(file, iov->iov_base, iov->iov_len,
-                       &iocb->ki_pos);
-       } else {
-               /*
-                * buffered write; drop Fw early to avoid slow
-                * revocation if we get stuck on balance_dirty_pages
-                */
-               int dirty;
-
-               spin_lock(&ci->i_ceph_lock);
-               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
-               spin_unlock(&ci->i_ceph_lock);
-               ceph_put_cap_refs(ci, got);
 
+       /*
+        * try to do a buffered write.  if we don't have sufficient
+        * caps, we'll get -EAGAIN from generic_file_aio_write, or a
+        * short write if we only get caps for some pages.
+        */
+       if (!(iocb->ki_filp->f_flags & O_DIRECT) &&
+           !(inode->i_sb->s_flags & MS_SYNCHRONOUS) &&
+           !(fi->flags & CEPH_F_SYNC)) {
                ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+               if (ret >= 0)
+                       written = ret;
+
                if ((ret >= 0 || ret == -EIOCBQUEUED) &&
                    ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host)
                     || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) {
-                       err = vfs_fsync_range(file, pos, pos + ret - 1, 1);
+                       err = vfs_fsync_range(file, pos, pos + written - 1, 1);
                        if (err < 0)
                                ret = err;
                }
+               if ((ret < 0 && ret != -EAGAIN) || pos + written >= endoff)
+                       goto out;
+       }
 
-               if (dirty)
-                       __mark_inode_dirty(inode, dirty);
+       dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, inode->i_size);
+       ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, 0, &got, endoff);
+       if (ret < 0)
                goto out;
-       }
 
+       dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, ceph_cap_string(got));
+       ret = ceph_sync_write(file, iov->iov_base + written,
+                             iov->iov_len - written, &iocb->ki_pos);
        if (ret >= 0) {
                int dirty;
                spin_lock(&ci->i_ceph_lock);
@@ -777,13 +767,10 @@ retry_snap:
                if (dirty)
                        __mark_inode_dirty(inode, dirty);
        }
-
-out_put:
        dout("aio_write %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
-            ceph_cap_string(got));
+            inode, ceph_vinop(inode), pos + written,
+            (unsigned)iov->iov_len - written, ceph_cap_string(got));
        ceph_put_cap_refs(ci, got);
-
 out:
        if (ret == -EOLDSNAPC) {
                dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n",
index ba95eea201bf1ef8e809159d6b41019fb9169752..2971eaa65cdce9b3b31edca64ea979eeb814ab7a 100644 (file)
@@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        u64 to;
-       int wrbuffer_refs, wake = 0;
+       int wrbuffer_refs, finish = 0;
 
 retry:
        spin_lock(&ci->i_ceph_lock);
@@ -1498,15 +1498,18 @@ retry:
        truncate_inode_pages(inode->i_mapping, to);
 
        spin_lock(&ci->i_ceph_lock);
-       ci->i_truncate_pending--;
-       if (ci->i_truncate_pending == 0)
-               wake = 1;
+       if (to == ci->i_truncate_size) {
+               ci->i_truncate_pending = 0;
+               finish = 1;
+       }
        spin_unlock(&ci->i_ceph_lock);
+       if (!finish)
+               goto retry;
 
        if (wrbuffer_refs == 0)
                ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
-       if (wake)
-               wake_up_all(&ci->i_cap_wq);
+
+       wake_up_all(&ci->i_cap_wq);
 }
 
 
index 1bcf712655d90a6001db4e8de8e86cfa3a70187d..9165eb8309eba442efa237aaa313a43c92641607 100644 (file)
@@ -1590,7 +1590,7 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
        } else if (rpath || rino) {
                *ino = rino;
                *ppath = rpath;
-               *pathlen = strlen(rpath);
+               *pathlen = rpath ? strlen(rpath) : 0;
                dout(" path %.*s\n", *pathlen, rpath);
        }
 
@@ -1876,9 +1876,14 @@ finish:
 static void __wake_requests(struct ceph_mds_client *mdsc,
                            struct list_head *head)
 {
-       struct ceph_mds_request *req, *nreq;
+       struct ceph_mds_request *req;
+       LIST_HEAD(tmp_list);
+
+       list_splice_init(head, &tmp_list);
 
-       list_for_each_entry_safe(req, nreq, head, r_wait) {
+       while (!list_empty(&tmp_list)) {
+               req = list_entry(tmp_list.next,
+                                struct ceph_mds_request, r_wait);
                list_del_init(&req->r_wait);
                __do_request(mdsc, req);
        }
index 2eb43f211325860a9d8c4eb870fa32c494568966..e86aa9948124b3601e1734515e4fb629627855de 100644 (file)
@@ -403,8 +403,6 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
        if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
                seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
-       if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
-               seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
        if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
                seq_printf(m, ",osdkeepalivetimeout=%d",
                           opt->osd_keepalive_timeout);
@@ -849,7 +847,7 @@ static int ceph_register_bdi(struct super_block *sb,
                fsc->backing_dev_info.ra_pages =
                        default_backing_dev_info.ra_pages;
 
-       err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
+       err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%ld",
                           atomic_long_inc_return(&bdi_seq));
        if (!err)
                sb->s_bdi = &fsc->backing_dev_info;
index 86e92ef2abc1e8c3aa5cdfe142acbc2adb73f9f0..69ae3d3c3b3159827ba073551146d72022caedcc 100644 (file)
@@ -37,7 +37,6 @@ void dump_smb(void *, int);
 #define CIFS_TIMER     0x04
 
 extern int cifsFYI;
-extern int cifsERROR;
 
 /*
  *     debug ON
@@ -64,10 +63,7 @@ do {                                                                 \
 
 /* error event message: e.g., i/o error */
 #define cifserror(fmt, ...)                                            \
-do {                                                                   \
-       if (cifsERROR)                                                  \
-               printk(KERN_ERR "CIFS VFS: " fmt "\n", ##__VA_ARGS__);  \
-} while (0)
+       printk(KERN_ERR "CIFS VFS: " fmt "\n", ##__VA_ARGS__);          \
 
 #define cERROR(set, fmt, ...)                                          \
 do {                                                                   \
index ce5cbd717bfc54be99e746089efe1fd17a8d593c..210fce2df3087a3738291f714e9ac99c18f390f8 100644 (file)
@@ -226,6 +226,8 @@ compose_mount_options_out:
 compose_mount_options_err:
        kfree(mountdata);
        mountdata = ERR_PTR(rc);
+       kfree(*devname);
+       *devname = NULL;
        goto compose_mount_options_out;
 }
 
index ce9f3c5421bf61d3d3bf828cc40820047c9b010c..de7f9168a1185ace14e8212040c96285c6c0bc31 100644 (file)
@@ -54,7 +54,6 @@
 #endif
 
 int cifsFYI = 0;
-int cifsERROR = 1;
 int traceSMB = 0;
 bool enable_oplocks = true;
 unsigned int linuxExtEnabled = 1;
@@ -229,7 +228,6 @@ cifs_alloc_inode(struct super_block *sb)
        cifs_set_oplock_level(cifs_inode, 0);
        cifs_inode->delete_pending = false;
        cifs_inode->invalid_mapping = false;
-       cifs_inode->leave_pages_clean = false;
        cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
        cifs_inode->server_eof = 0;
        cifs_inode->uniqueid = 0;
index aea1eec649116a3891ce00c9ff6d073d7183fc6a..e6899cea1c3580e6e9217f9cb3f0ff68e8d7626c 100644 (file)
@@ -386,6 +386,7 @@ struct smb_version_values {
        unsigned int    cap_unix;
        unsigned int    cap_nt_find;
        unsigned int    cap_large_files;
+       unsigned int    oplock_read;
 };
 
 #define HEADER_SIZE(server) (server->vals->header_size)
@@ -1030,7 +1031,6 @@ struct cifsInodeInfo {
        bool clientCanCacheAll;         /* read and writebehind oplock */
        bool delete_pending;            /* DELETE_ON_CLOSE is set */
        bool invalid_mapping;           /* pagecache is invalid */
-       bool leave_pages_clean; /* protected by i_mutex, not set pages dirty */
        unsigned long time;             /* jiffies of last update of inode */
        u64  server_eof;                /* current file size on server -- protected by i_lock */
        u64  uniqueid;                  /* server inode number */
index 7635b5db26a7d78fc0140ecc556054592388ad95..12b3da39733b2bc180cd1ac4a164d9f0d071e99a 100644 (file)
@@ -1624,14 +1624,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_unc:
                        string = vol->UNC;
                        vol->UNC = match_strdup(args);
-                       if (vol->UNC == NULL) {
-                               kfree(string);
+                       if (vol->UNC == NULL)
                                goto out_nomem;
-                       }
 
                        convert_delimiter(vol->UNC, '\\');
                        if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
-                               kfree(string);
                                printk(KERN_ERR "CIFS: UNC Path does not "
                                                "begin with // or \\\\\n");
                                goto cifs_parse_mount_err;
@@ -1687,10 +1684,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
                        string = vol->prepath;
                        vol->prepath = match_strdup(args);
-                       if (vol->prepath == NULL) {
-                               kfree(string);
+                       if (vol->prepath == NULL)
                                goto out_nomem;
-                       }
                        /* Compare old prefixpath= option to new one */
                        if (!string || strcmp(string, vol->prepath))
                                printk(KERN_WARNING "CIFS: the value of the "
@@ -1922,7 +1917,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
        }
        case AF_INET6: {
                struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
-               struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
+               struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
                return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
        }
        default:
index 0a6677ba212b11ef73fbf83465c32f6ffe4fa2c1..8ea6ca50a665cd4dcb016042b52d16ef5492bab4 100644 (file)
@@ -238,6 +238,23 @@ out:
        return rc;
 }
 
+static bool
+cifs_has_mand_locks(struct cifsInodeInfo *cinode)
+{
+       struct cifs_fid_locks *cur;
+       bool has_locks = false;
+
+       down_read(&cinode->lock_sem);
+       list_for_each_entry(cur, &cinode->llist, llist) {
+               if (!list_empty(&cur->locks)) {
+                       has_locks = true;
+                       break;
+               }
+       }
+       up_read(&cinode->lock_sem);
+       return has_locks;
+}
+
 struct cifsFileInfo *
 cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
                  struct tcon_link *tlink, __u32 oplock)
@@ -248,6 +265,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        struct cifsFileInfo *cfile;
        struct cifs_fid_locks *fdlocks;
        struct cifs_tcon *tcon = tlink_tcon(tlink);
+       struct TCP_Server_Info *server = tcon->ses->server;
 
        cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
        if (cfile == NULL)
@@ -276,12 +294,22 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
        mutex_init(&cfile->fh_mutex);
 
+       /*
+        * If the server returned a read oplock and we have mandatory brlocks,
+        * set oplock level to None.
+        */
+       if (oplock == server->vals->oplock_read &&
+                                               cifs_has_mand_locks(cinode)) {
+               cFYI(1, "Reset oplock val from read to None due to mand locks");
+               oplock = 0;
+       }
+
        spin_lock(&cifs_file_list_lock);
-       if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE)
+       if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
                oplock = fid->pending_open->oplock;
        list_del(&fid->pending_open->olist);
 
-       tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock);
+       server->ops->set_fid(cfile, fid, oplock);
 
        list_add(&cfile->tlist, &tcon->openFileList);
        /* if readable file instance put first in list*/
@@ -1422,6 +1450,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
        struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
+       struct inode *inode = cfile->dentry->d_inode;
 
        if (posix_lck) {
                int posix_lock_type;
@@ -1459,6 +1488,21 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
                if (!rc)
                        goto out;
 
+               /*
+                * Windows 7 server can delay breaking lease from read to None
+                * if we set a byte-range lock on a file - break it explicitly
+                * before sending the lock to the server to be sure the next
+                * read won't conflict with non-overlapted locks due to
+                * pagereading.
+                */
+               if (!CIFS_I(inode)->clientCanCacheAll &&
+                                       CIFS_I(inode)->clientCanCacheRead) {
+                       cifs_invalidate_mapping(inode);
+                       cFYI(1, "Set no oplock for inode=%p due to mand locks",
+                            inode);
+                       CIFS_I(inode)->clientCanCacheRead = false;
+               }
+
                rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
                                            type, 1, 0, wait_flag);
                if (rc) {
@@ -2103,15 +2147,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
        } else {
                rc = copied;
                pos += copied;
-               /*
-                * When we use strict cache mode and cifs_strict_writev was run
-                * with level II oplock (indicated by leave_pages_clean field of
-                * CIFS_I(inode)), we can leave pages clean - cifs_strict_writev
-                * sent the data to the server itself.
-                */
-               if (!CIFS_I(inode)->leave_pages_clean ||
-                   !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO))
-                       set_page_dirty(page);
+               set_page_dirty(page);
        }
 
        if (rc > 0) {
@@ -2462,8 +2498,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
 }
 
 static ssize_t
-cifs_pagecache_writev(struct kiocb *iocb, const struct iovec *iov,
-                     unsigned long nr_segs, loff_t pos, bool cache_ex)
+cifs_writev(struct kiocb *iocb, const struct iovec *iov,
+           unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
        struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
@@ -2485,12 +2521,8 @@ cifs_pagecache_writev(struct kiocb *iocb, const struct iovec *iov,
                                     server->vals->exclusive_lock_type, NULL,
                                     CIFS_WRITE_OP)) {
                mutex_lock(&inode->i_mutex);
-               if (!cache_ex)
-                       cinode->leave_pages_clean = true;
                rc = __generic_file_aio_write(iocb, iov, nr_segs,
-                                             &iocb->ki_pos);
-               if (!cache_ex)
-                       cinode->leave_pages_clean = false;
+                                              &iocb->ki_pos);
                mutex_unlock(&inode->i_mutex);
        }
 
@@ -2517,60 +2549,32 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
        struct cifsFileInfo *cfile = (struct cifsFileInfo *)
                                                iocb->ki_filp->private_data;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       ssize_t written, written2;
-       /*
-        * We need to store clientCanCacheAll here to prevent race
-        * conditions - this value can be changed during an execution
-        * of generic_file_aio_write. For CIFS it can be changed from
-        * true to false only, but for SMB2 it can be changed both from
-        * true to false and vice versa. So, we can end up with a data
-        * stored in the cache, not marked dirty and not sent to the
-        * server if this value changes its state from false to true
-        * after cifs_write_end.
-        */
-       bool cache_ex = cinode->clientCanCacheAll;
-       bool cache_read = cinode->clientCanCacheRead;
-       int rc;
-       loff_t saved_pos;
+       ssize_t written;
 
-       if (cache_ex) {
+       if (cinode->clientCanCacheAll) {
                if (cap_unix(tcon->ses) &&
-                   ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) &&
-                   (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(
-                                               tcon->fsUnixInfo.Capability)))
+               (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
+                   && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
                        return generic_file_aio_write(iocb, iov, nr_segs, pos);
-               return cifs_pagecache_writev(iocb, iov, nr_segs, pos, cache_ex);
+               return cifs_writev(iocb, iov, nr_segs, pos);
        }
-
        /*
-        * For files without exclusive oplock in strict cache mode we need to
-        * write the data to the server exactly from the pos to pos+len-1 rather
-        * than flush all affected pages because it may cause a error with
-        * mandatory locks on these pages but not on the region from pos to
-        * ppos+len-1.
+        * For non-oplocked files in strict cache mode we need to write the data
+        * to the server exactly from the pos to pos+len-1 rather than flush all
+        * affected pages because it may cause a error with mandatory locks on
+        * these pages but not on the region from pos to ppos+len-1.
         */
        written = cifs_user_writev(iocb, iov, nr_segs, pos);
-       if (!cache_read || written <= 0)
-               return written;
-
-       saved_pos = iocb->ki_pos;
-       iocb->ki_pos = pos;
-       /* we have a read oplock - need to store a data in the page cache */
-       if (cap_unix(tcon->ses) &&
-           ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) &&
-           (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(
-                                       tcon->fsUnixInfo.Capability)))
-               written2 = generic_file_aio_write(iocb, iov, nr_segs, pos);
-       else
-               written2 = cifs_pagecache_writev(iocb, iov, nr_segs, pos,
-                                                cache_ex);
-       /* errors occured during writing - invalidate the page cache */
-       if (written2 < 0) {
-               rc = cifs_invalidate_mapping(inode);
-               if (rc)
-                       written = (ssize_t)rc;
-               else
-                       iocb->ki_pos = saved_pos;
+       if (written > 0 && cinode->clientCanCacheRead) {
+               /*
+                * Windows 7 server can delay breaking level2 oplock if a write
+                * request comes - break it on the client to prevent reading
+                * an old data.
+                */
+               cifs_invalidate_mapping(inode);
+               cFYI(1, "Set no oplock for inode=%p after a write operation",
+                    inode);
+               cinode->clientCanCacheRead = false;
        }
        return written;
 }
@@ -3577,6 +3581,13 @@ void cifs_oplock_break(struct work_struct *work)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
+       if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead &&
+                                               cifs_has_mand_locks(cinode)) {
+               cFYI(1, "Reset oplock to None for inode=%p due to mand locks",
+                    inode);
+               cinode->clientCanCacheRead = false;
+       }
+
        if (inode && S_ISREG(inode->i_mode)) {
                if (cinode->clientCanCacheRead)
                        break_lease(inode, O_RDONLY);
index 6002fdc920ae402dabad902e623b875288fa988e..cdd6ff48246b2d8e79ae79f5de747eac9059030e 100644 (file)
@@ -78,6 +78,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
        struct dentry *dentry, *alias;
        struct inode *inode;
        struct super_block *sb = parent->d_inode->i_sb;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
        cFYI(1, "%s: for %s", __func__, name->name);
 
@@ -91,10 +92,20 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
                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);
-                       goto out;
+               if (inode) {
+                       /*
+                        * If we're generating inode numbers, then we don't
+                        * want to clobber the existing one with the one that
+                        * the readdir code created.
+                        */
+                       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
+                               fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
+
+                       /* update inode in place if i_ino didn't change */
+                       if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
+                               cifs_fattr_to_inode(inode, fattr);
+                               goto out;
+                       }
                }
                err = d_invalidate(dentry);
                dput(dentry);
index a5d234c8d5d9295f41e947188ba020da68ec33dd..47bc5a87f94e9fd841b9c7bc391462f81ca872c9 100644 (file)
@@ -53,6 +53,13 @@ send_nt_cancel(struct TCP_Server_Info *server, void *buf,
                mutex_unlock(&server->srv_mutex);
                return rc;
        }
+
+       /*
+        * The response to this call was already factored into the sequence
+        * number when the call went out, so we must adjust it back downward
+        * after signing here.
+        */
+       --server->sequence_number;
        rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
        mutex_unlock(&server->srv_mutex);
 
@@ -952,4 +959,5 @@ struct smb_version_values smb1_values = {
        .cap_unix = CAP_UNIX,
        .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
        .cap_large_files = CAP_LARGE_FILES,
+       .oplock_read = OPLOCK_READ,
 };
index d79de7bc4435094a3d94657e1d98c390e1389d41..c9c7aa7ed96685bc94b36103350204c68a19b827 100644 (file)
@@ -708,6 +708,7 @@ struct smb_version_values smb20_values = {
        .cap_unix = 0,
        .cap_nt_find = SMB2_NT_FIND,
        .cap_large_files = SMB2_LARGE_FILES,
+       .oplock_read = SMB2_OPLOCK_LEVEL_II,
 };
 
 struct smb_version_values smb21_values = {
@@ -725,6 +726,7 @@ struct smb_version_values smb21_values = {
        .cap_unix = 0,
        .cap_nt_find = SMB2_NT_FIND,
        .cap_large_files = SMB2_LARGE_FILES,
+       .oplock_read = SMB2_OPLOCK_LEVEL_II,
 };
 
 struct smb_version_values smb30_values = {
index 76d974c952fe93126a31d437dc0e362ffef6087c..1a528680ec5a29e4b59485fba5df54568a1e3787 100644 (file)
@@ -144,9 +144,6 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
 
        *sent = 0;
 
-       if (ssocket == NULL)
-               return -ENOTSOCK; /* BB eventually add reconnect code here */
-
        smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
        smb_msg.msg_namelen = sizeof(struct sockaddr);
        smb_msg.msg_control = NULL;
@@ -291,6 +288,9 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
        struct socket *ssocket = server->ssocket;
        int val = 1;
 
+       if (ssocket == NULL)
+               return -ENOTSOCK;
+
        cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
        dump_smb(iov[0].iov_base, iov[0].iov_len);
 
index 3a463d0c4fe830d5c33c9dcf9ebd05e5caf5fb43..19153a0a810c1d12de751d5d416a5c1b6fe8c9bb 100644 (file)
@@ -454,24 +454,6 @@ void d_drop(struct dentry *dentry)
 }
 EXPORT_SYMBOL(d_drop);
 
-/*
- * d_clear_need_lookup - drop a dentry from cache and clear the need lookup flag
- * @dentry: dentry to drop
- *
- * This is called when we do a lookup on a placeholder dentry that needed to be
- * looked up.  The dentry should have been hashed in order for it to be found by
- * the lookup code, but now needs to be unhashed while we do the actual lookup
- * and clear the DCACHE_NEED_LOOKUP flag.
- */
-void d_clear_need_lookup(struct dentry *dentry)
-{
-       spin_lock(&dentry->d_lock);
-       __d_drop(dentry);
-       dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
-       spin_unlock(&dentry->d_lock);
-}
-EXPORT_SYMBOL(d_clear_need_lookup);
-
 /*
  * Finish off a dentry we've decided to kill.
  * dentry->d_lock must be held, returns with it unlocked.
@@ -565,13 +547,7 @@ repeat:
        if (d_unhashed(dentry))
                goto kill_it;
 
-       /*
-        * If this dentry needs lookup, don't set the referenced flag so that it
-        * is more likely to be cleaned up by the dcache shrinker in case of
-        * memory pressure.
-        */
-       if (!d_need_lookup(dentry))
-               dentry->d_flags |= DCACHE_REFERENCED;
+       dentry->d_flags |= DCACHE_REFERENCED;
        dentry_lru_add(dentry);
 
        dentry->d_count--;
@@ -1583,7 +1559,7 @@ EXPORT_SYMBOL(d_find_any_alias);
  */
 struct dentry *d_obtain_alias(struct inode *inode)
 {
-       static const struct qstr anonstring = { .name = "" };
+       static const struct qstr anonstring = QSTR_INIT("/", 1);
        struct dentry *tmp;
        struct dentry *res;
 
@@ -1736,13 +1712,6 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
                return found;
        }
 
-       /*
-        * We are going to instantiate this dentry, unhash it and clear the
-        * lookup flag so we can do that.
-        */
-       if (unlikely(d_need_lookup(found)))
-               d_clear_need_lookup(found);
-
        /*
         * Negative dentry: instantiate it unless the inode is a directory and
         * already has a dentry.
index 153bb1e42e631e07b41c5d87d82fd660388ed22e..a5f12b7e228d487029ea83ab72482cdfc8bb2a61 100644 (file)
@@ -176,7 +176,7 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
                        opts->uid = uid;
                        break;
                case Opt_gid:
-                       if (match_octal(&args[0], &option))
+                       if (match_int(&args[0], &option))
                                return -EINVAL;
                        gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(gid))
index 7ff49852b0cb75163ff9646dfb16195678971899..911649a47dd5ae5b000bfabb2b73b0c71a95ec52 100644 (file)
@@ -503,11 +503,11 @@ static ssize_t device_write(struct file *file, const char __user *buf,
 #endif
                return -EINVAL;
 
-#ifdef CONFIG_COMPAT
-       if (count > sizeof(struct dlm_write_request32) + DLM_RESNAME_MAXLEN)
-#else
+       /*
+        * can't compare against COMPAT/dlm_write_request32 because
+        * we don't yet know if is64bit is zero
+        */
        if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
-#endif
                return -EINVAL;
 
        kbuf = kzalloc(count + 1, GFP_NOFS);
index ea9931281557ad8d3ed4049b48c66110df5f0811..a7b0c2dfb3db76066703076ab43f4d589637523d 100644 (file)
@@ -1935,7 +1935,7 @@ static const unsigned char filename_rev_map[256] = {
  * @src: Source location for the filename to encode
  * @src_size: Size of the source in bytes
  */
-void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size,
+static void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size,
                                  unsigned char *src, size_t src_size)
 {
        size_t num_blocks;
index 809e67d05ca34fa32eb1363c555db71757d1a6a7..f1ea610362c6c160a9d955c6a8e946da03b83ccb 100644 (file)
@@ -102,12 +102,12 @@ int __init ecryptfs_init_kthread(void)
 
 void ecryptfs_destroy_kthread(void)
 {
-       struct ecryptfs_open_req *req;
+       struct ecryptfs_open_req *req, *tmp;
 
        mutex_lock(&ecryptfs_kthread_ctl.mux);
        ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
-       list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
-                           kthread_ctl_list) {
+       list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list,
+                                kthread_ctl_list) {
                list_del(&req->kthread_ctl_list);
                *req->lower_file = ERR_PTR(-EIO);
                complete(&req->done);
index bd1d57f98f746af552df4af0acda732f92f6d2f9..564a1fa34b9941a4672d3b455db928ebcd4e4fa1 100644 (file)
@@ -338,7 +338,8 @@ static int ecryptfs_write_begin(struct file *file,
                        if (prev_page_end_size
                            >= i_size_read(page->mapping->host)) {
                                zero_user(page, 0, PAGE_CACHE_SIZE);
-                       } else {
+                               SetPageUptodate(page);
+                       } else if (len < PAGE_CACHE_SIZE) {
                                rc = ecryptfs_decrypt_page(page);
                                if (rc) {
                                        printk(KERN_ERR "%s: Error decrypting "
@@ -348,8 +349,8 @@ static int ecryptfs_write_begin(struct file *file,
                                        ClearPageUptodate(page);
                                        goto out;
                                }
+                               SetPageUptodate(page);
                        }
-                       SetPageUptodate(page);
                }
        }
        /* If creating a page or more of holes, zero them out via truncate.
@@ -499,6 +500,13 @@ static int ecryptfs_write_end(struct file *file,
                }
                goto out;
        }
+       if (!PageUptodate(page)) {
+               if (copied < PAGE_CACHE_SIZE) {
+                       rc = 0;
+                       goto out;
+               }
+               SetPageUptodate(page);
+       }
        /* Fills in zeros if 'to' goes beyond inode size */
        rc = fill_zeros_to_end_of_page(page, to);
        if (rc) {
index be56b21435f8c4e5170fdb2c0963abdd24dc9291..9fec1836057a9298ad9f121afcea03c64388eb88 100644 (file)
@@ -1313,7 +1313,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
         * otherwise we might miss an event that happens between the
         * f_op->poll() call and the new event set registering.
         */
-       epi->event.events = event->events;
+       epi->event.events = event->events; /* need barrier below */
        pt._key = event->events;
        epi->event.data = event->data; /* protected by mtx */
        if (epi->event.events & EPOLLWAKEUP) {
@@ -1323,6 +1323,26 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
                ep_destroy_wakeup_source(epi);
        }
 
+       /*
+        * The following barrier has two effects:
+        *
+        * 1) Flush epi changes above to other CPUs.  This ensures
+        *    we do not miss events from ep_poll_callback if an
+        *    event occurs immediately after we call f_op->poll().
+        *    We need this because we did not take ep->lock while
+        *    changing epi above (but ep_poll_callback does take
+        *    ep->lock).
+        *
+        * 2) We also need to ensure we do not miss _past_ events
+        *    when calling f_op->poll().  This barrier also
+        *    pairs with the barrier in wq_has_sleeper (see
+        *    comments for wq_has_sleeper).
+        *
+        * This barrier will now guarantee ep_poll_callback or f_op->poll
+        * (or both) will notice the readiness of an item.
+        */
+       smp_mb();
+
        /*
         * Get current event bits. We can safely use the file* here because
         * its usage count has been increased by the caller of this function.
index d8e1191cb112eb2d77154908a32699a06c4bda78..20df02c1cc70190b04802493d5a25b802e0adcba 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -434,8 +434,9 @@ static int count(struct user_arg_ptr argv, int max)
                        if (IS_ERR(p))
                                return -EFAULT;
 
-                       if (i++ >= max)
+                       if (i >= max)
                                return -E2BIG;
+                       ++i;
 
                        if (fatal_signal_pending(current))
                                return -ERESTARTNOHAND;
@@ -1175,9 +1176,24 @@ void free_bprm(struct linux_binprm *bprm)
                mutex_unlock(&current->signal->cred_guard_mutex);
                abort_creds(bprm->cred);
        }
+       /* If a binfmt changed the interp, free it. */
+       if (bprm->interp != bprm->filename)
+               kfree(bprm->interp);
        kfree(bprm);
 }
 
+int bprm_change_interp(char *interp, struct linux_binprm *bprm)
+{
+       /* If a binfmt changed the interp, free it first. */
+       if (bprm->interp != bprm->filename)
+               kfree(bprm->interp);
+       bprm->interp = kstrdup(interp, GFP_KERNEL);
+       if (!bprm->interp)
+               return -ENOMEM;
+       return 0;
+}
+EXPORT_SYMBOL(bprm_change_interp);
+
 /*
  * install the new credentials for this executable
  */
@@ -1654,7 +1670,6 @@ int get_dumpable(struct mm_struct *mm)
        return __get_dumpable(mm->flags);
 }
 
-#ifdef __ARCH_WANT_SYS_EXECVE
 SYSCALL_DEFINE3(execve,
                const char __user *, filename,
                const char __user *const __user *, argv,
@@ -1682,23 +1697,3 @@ asmlinkage long compat_sys_execve(const char __user * filename,
        return error;
 }
 #endif
-#endif
-
-#ifdef __ARCH_WANT_KERNEL_EXECVE
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       int ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       ret_from_kernel_execve(current_pt_regs());
-}
-#endif
index 606bb074c501842a1cf11df97464002e6d098f30..5df4bb4aab145dff9edc58408f2c1d923a5c8552 100644 (file)
@@ -322,10 +322,10 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
 
        if (parent && (len < 4)) {
                *max_len = 4;
-               return 255;
+               return FILEID_INVALID;
        } else if (len < 2) {
                *max_len = 2;
-               return 255;
+               return FILEID_INVALID;
        }
 
        len = 2;
index 0a475c881852666d6f21b9a0fc82207d35b6be46..987358740cb970dab82917f952f8cc8bfae4361c 100644 (file)
@@ -41,6 +41,7 @@ config EXT4_USE_FOR_EXT23
 
 config EXT4_FS_POSIX_ACL
        bool "Ext4 POSIX Access Control Lists"
+       depends on EXT4_FS
        select FS_POSIX_ACL
        help
          POSIX Access Control Lists (ACLs) support permissions for users and
@@ -53,6 +54,7 @@ config EXT4_FS_POSIX_ACL
 
 config EXT4_FS_SECURITY
        bool "Ext4 Security Labels"
+       depends on EXT4_FS
        help
          Security labels support alternative access control models
          implemented by security modules like SELinux.  This option
index 26af22832a846d43d94c20e67e92a2ab825d835c..5ae1674ec12f16b7eea6635244f9b68f252d9ba2 100644 (file)
@@ -2226,13 +2226,14 @@ errout:
  * removes index from the index block.
  */
 static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
-                       struct ext4_ext_path *path)
+                       struct ext4_ext_path *path, int depth)
 {
        int err;
        ext4_fsblk_t leaf;
 
        /* free index block */
-       path--;
+       depth--;
+       path = path + depth;
        leaf = ext4_idx_pblock(path->p_idx);
        if (unlikely(path->p_hdr->eh_entries == 0)) {
                EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
@@ -2257,6 +2258,19 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
 
        ext4_free_blocks(handle, inode, NULL, leaf, 1,
                         EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
+
+       while (--depth >= 0) {
+               if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr))
+                       break;
+               path--;
+               err = ext4_ext_get_access(handle, inode, path);
+               if (err)
+                       break;
+               path->p_idx->ei_block = (path+1)->p_idx->ei_block;
+               err = ext4_ext_dirty(handle, inode, path);
+               if (err)
+                       break;
+       }
        return err;
 }
 
@@ -2599,7 +2613,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
        /* if this leaf is free, then we should
         * remove it from index block above */
        if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
-               err = ext4_ext_rm_idx(handle, inode, path + depth);
+               err = ext4_ext_rm_idx(handle, inode, path, depth);
 
 out:
        return err;
@@ -2802,7 +2816,7 @@ again:
                                /* index is empty, remove it;
                                 * handle must be already prepared by the
                                 * truncatei_leaf() */
-                               err = ext4_ext_rm_idx(handle, inode, path + i);
+                               err = ext4_ext_rm_idx(handle, inode, path, i);
                        }
                        /* root level has p_bh == NULL, brelse() eats this */
                        brelse(path[i].p_bh);
index d07c27ca594a4578887ed898e71c9b60684730df..405565a62277c5bbbf9d5ea91efbeea4118531b2 100644 (file)
@@ -108,14 +108,6 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
 
        /* Unaligned direct AIO must be serialized; see comment above */
        if (unaligned_aio) {
-               static unsigned long unaligned_warn_time;
-
-               /* Warn about this once per day */
-               if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ))
-                       ext4_msg(inode->i_sb, KERN_WARNING,
-                                "Unaligned AIO/DIO on inode %ld by %s; "
-                                "performance will be poor.",
-                                inode->i_ino, current->comm);
                mutex_lock(ext4_aio_mutex(inode));
                ext4_unwritten_wait(inode);
        }
index dfbc1fe9667487518d965ecb361d1724f822f983..3278e64e57b61ac51a41db3ceebeecd21003985a 100644 (file)
@@ -109,8 +109,6 @@ static int __sync_inode(struct inode *inode, int datasync)
  *
  * What we do is just kick off a commit and wait on it.  This will snapshot the
  * inode to disk.
- *
- * i_mutex lock is held when entering and exiting this function
  */
 
 int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
index cb1c1ab2720bd6c08c641879adb5ac77c11ca104..cbfe13bf5b2aa3f39b4845fe4fce4f45a02b5f43 100644 (file)
@@ -2880,8 +2880,6 @@ static void ext4_invalidatepage_free_endio(struct page *page, unsigned long offs
 
 static void ext4_invalidatepage(struct page *page, unsigned long offset)
 {
-       journal_t *journal = EXT4_JOURNAL(page->mapping->host);
-
        trace_ext4_invalidatepage(page, offset);
 
        /*
@@ -2889,16 +2887,34 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset)
         */
        if (ext4_should_dioread_nolock(page->mapping->host))
                ext4_invalidatepage_free_endio(page, offset);
+
+       /* No journalling happens on data buffers when this function is used */
+       WARN_ON(page_has_buffers(page) && buffer_jbd(page_buffers(page)));
+
+       block_invalidatepage(page, offset);
+}
+
+static int __ext4_journalled_invalidatepage(struct page *page,
+                                           unsigned long offset)
+{
+       journal_t *journal = EXT4_JOURNAL(page->mapping->host);
+
+       trace_ext4_journalled_invalidatepage(page, offset);
+
        /*
         * If it's a full truncate we just forget about the pending dirtying
         */
        if (offset == 0)
                ClearPageChecked(page);
 
-       if (journal)
-               jbd2_journal_invalidatepage(journal, page, offset);
-       else
-               block_invalidatepage(page, offset);
+       return jbd2_journal_invalidatepage(journal, page, offset);
+}
+
+/* Wrapper for aops... */
+static void ext4_journalled_invalidatepage(struct page *page,
+                                          unsigned long offset)
+{
+       WARN_ON(__ext4_journalled_invalidatepage(page, offset) < 0);
 }
 
 static int ext4_releasepage(struct page *page, gfp_t wait)
@@ -3264,7 +3280,7 @@ static const struct address_space_operations ext4_journalled_aops = {
        .write_end              = ext4_journalled_write_end,
        .set_page_dirty         = ext4_journalled_set_page_dirty,
        .bmap                   = ext4_bmap,
-       .invalidatepage         = ext4_invalidatepage,
+       .invalidatepage         = ext4_journalled_invalidatepage,
        .releasepage            = ext4_releasepage,
        .direct_IO              = ext4_direct_IO,
        .is_partially_uptodate  = block_is_partially_uptodate,
@@ -4304,6 +4320,47 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
        return err;
 }
 
+/*
+ * In data=journal mode ext4_journalled_invalidatepage() may fail to invalidate
+ * buffers that are attached to a page stradding i_size and are undergoing
+ * commit. In that case we have to wait for commit to finish and try again.
+ */
+static void ext4_wait_for_tail_page_commit(struct inode *inode)
+{
+       struct page *page;
+       unsigned offset;
+       journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+       tid_t commit_tid = 0;
+       int ret;
+
+       offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+       /*
+        * All buffers in the last page remain valid? Then there's nothing to
+        * do. We do the check mainly to optimize the common PAGE_CACHE_SIZE ==
+        * blocksize case
+        */
+       if (offset > PAGE_CACHE_SIZE - (1 << inode->i_blkbits))
+               return;
+       while (1) {
+               page = find_lock_page(inode->i_mapping,
+                                     inode->i_size >> PAGE_CACHE_SHIFT);
+               if (!page)
+                       return;
+               ret = __ext4_journalled_invalidatepage(page, offset);
+               unlock_page(page);
+               page_cache_release(page);
+               if (ret != -EBUSY)
+                       return;
+               commit_tid = 0;
+               read_lock(&journal->j_state_lock);
+               if (journal->j_committing_transaction)
+                       commit_tid = journal->j_committing_transaction->t_tid;
+               read_unlock(&journal->j_state_lock);
+               if (commit_tid)
+                       jbd2_log_wait_commit(journal, commit_tid);
+       }
+}
+
 /*
  * ext4_setattr()
  *
@@ -4417,16 +4474,28 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        if (attr->ia_valid & ATTR_SIZE) {
-               if (attr->ia_size != i_size_read(inode)) {
-                       truncate_setsize(inode, attr->ia_size);
-                       /* Inode size will be reduced, wait for dio in flight.
-                        * Temporarily disable dioread_nolock to prevent
-                        * livelock. */
+               if (attr->ia_size != inode->i_size) {
+                       loff_t oldsize = inode->i_size;
+
+                       i_size_write(inode, attr->ia_size);
+                       /*
+                        * Blocks are going to be removed from the inode. Wait
+                        * for dio in flight.  Temporarily disable
+                        * dioread_nolock to prevent livelock.
+                        */
                        if (orphan) {
-                               ext4_inode_block_unlocked_dio(inode);
-                               inode_dio_wait(inode);
-                               ext4_inode_resume_unlocked_dio(inode);
+                               if (!ext4_should_journal_data(inode)) {
+                                       ext4_inode_block_unlocked_dio(inode);
+                                       inode_dio_wait(inode);
+                                       ext4_inode_resume_unlocked_dio(inode);
+                               } else
+                                       ext4_wait_for_tail_page_commit(inode);
                        }
+                       /*
+                        * Truncate pagecache after we've waited for commit
+                        * in data=journal mode to make pages freeable.
+                        */
+                       truncate_pagecache(inode, oldsize, inode->i_size);
                }
                ext4_truncate(inode);
        }
index cac44828233159bfeb1d93c502943fe82b813b2a..f9ed946a448ebb4a7704c5d08fcfe44c42a75f80 100644 (file)
@@ -722,7 +722,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
                        ext4_warning(dir->i_sb, "Node failed checksum");
                        brelse(bh);
                        *err = ERR_BAD_DX_DIR;
-                       goto fail;
+                       goto fail2;
                }
                set_buffer_verified(bh);
 
@@ -2368,7 +2368,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        }
 
        inode->i_size = EXT4_I(inode)->i_disksize = blocksize;
-       dir_block = ext4_bread(handle, inode, 0, 1, &err);
        if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) {
                if (!err) {
                        err = -EIO;
@@ -2648,7 +2647,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
        struct ext4_iloc iloc;
        int err = 0;
 
-       if (!EXT4_SB(inode->i_sb)->s_journal)
+       if ((!EXT4_SB(inode->i_sb)->s_journal) &&
+           !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS))
                return 0;
 
        mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
index 3cdb0a2fc64856b041ec4b5f184fb41a5a346771..3d4fb81bacd540ca7b81fd4005f392aa7a516b53 100644 (file)
@@ -1645,9 +1645,7 @@ static int parse_options(char *options, struct super_block *sb,
                         unsigned int *journal_ioprio,
                         int is_remount)
 {
-#ifdef CONFIG_QUOTA
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-#endif
        char *p;
        substring_t args[MAX_OPT_ARGS];
        int token;
@@ -1696,6 +1694,16 @@ static int parse_options(char *options, struct super_block *sb,
                }
        }
 #endif
+       if (test_opt(sb, DIOREAD_NOLOCK)) {
+               int blocksize =
+                       BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
+
+               if (blocksize < PAGE_CACHE_SIZE) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+                                "dioread_nolock if block size != PAGE_SIZE");
+                       return 0;
+               }
+       }
        return 1;
 }
 
@@ -2212,7 +2220,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
                                __func__, inode->i_ino, inode->i_size);
                        jbd_debug(2, "truncating inode %lu to %lld bytes\n",
                                  inode->i_ino, inode->i_size);
+                       mutex_lock(&inode->i_mutex);
                        ext4_truncate(inode);
+                       mutex_unlock(&inode->i_mutex);
                        nr_truncates++;
                } else {
                        ext4_msg(sb, KERN_DEBUG,
@@ -3223,6 +3233,10 @@ int ext4_calculate_overhead(struct super_block *sb)
                        memset(buf, 0, PAGE_SIZE);
                cond_resched();
        }
+       /* Add the journal blocks as well */
+       if (sbi->s_journal)
+               overhead += EXT4_B2C(sbi, sbi->s_journal->j_maxlen);
+
        sbi->s_overhead = overhead;
        smp_wmb();
        free_page((unsigned long) buf);
@@ -3436,15 +3450,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        clear_opt(sb, DELALLOC);
        }
 
-       blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
-       if (test_opt(sb, DIOREAD_NOLOCK)) {
-               if (blocksize < PAGE_SIZE) {
-                       ext4_msg(sb, KERN_ERR, "can't mount with "
-                                "dioread_nolock if block size != PAGE_SIZE");
-                       goto failed_mount;
-               }
-       }
-
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
@@ -3486,6 +3491,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
                goto failed_mount;
 
+       blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
        if (blocksize < EXT4_MIN_BLOCK_SIZE ||
            blocksize > EXT4_MAX_BLOCK_SIZE) {
                ext4_msg(sb, KERN_ERR,
@@ -4725,7 +4731,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        }
 
        ext4_setup_system_zone(sb);
-       if (sbi->s_journal == NULL)
+       if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY))
                ext4_commit_super(sb, 1);
 
 #ifdef CONFIG_QUOTA
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
new file mode 100644 (file)
index 0000000..fd27e7e
--- /dev/null
@@ -0,0 +1,53 @@
+config F2FS_FS
+       tristate "F2FS filesystem support (EXPERIMENTAL)"
+       depends on BLOCK
+       help
+         F2FS is based on Log-structured File System (LFS), which supports
+         versatile "flash-friendly" features. The design has been focused on
+         addressing the fundamental issues in LFS, which are snowball effect
+         of wandering tree and high cleaning overhead.
+
+         Since flash-based storages show different characteristics according to
+         the internal geometry or flash memory management schemes aka FTL, F2FS
+         and tools support various parameters not only for configuring on-disk
+         layout, but also for selecting allocation and cleaning algorithms.
+
+         If unsure, say N.
+
+config F2FS_STAT_FS
+       bool "F2FS Status Information"
+       depends on F2FS_FS && DEBUG_FS
+       default y
+       help
+         /sys/kernel/debug/f2fs/ contains information about all the partitions
+         mounted as f2fs. Each file shows the whole f2fs information.
+
+         /sys/kernel/debug/f2fs/status includes:
+           - major file system information managed by f2fs currently
+           - average SIT information about whole segments
+           - current memory footprint consumed by f2fs.
+
+config F2FS_FS_XATTR
+       bool "F2FS extended attributes"
+       depends on F2FS_FS
+       default y
+       help
+         Extended attributes are name:value pairs associated with inodes by
+         the kernel or by users (see the attr(5) manual page, or visit
+         <http://acl.bestbits.at/> for details).
+
+         If unsure, say N.
+
+config F2FS_FS_POSIX_ACL
+       bool "F2FS Access Control Lists"
+       depends on F2FS_FS_XATTR
+       select FS_POSIX_ACL
+       default y
+       help
+         Posix Access Control Lists (ACLs) support permissions for users and
+         gourps beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the POSIX ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N
diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
new file mode 100644 (file)
index 0000000..27a0820
--- /dev/null
@@ -0,0 +1,7 @@
+obj-$(CONFIG_F2FS_FS) += f2fs.o
+
+f2fs-y         := dir.o file.o inode.o namei.o hash.o super.o
+f2fs-y         += checkpoint.o gc.o data.o node.o segment.o recovery.o
+f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
+f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
new file mode 100644 (file)
index 0000000..137af42
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * fs/f2fs/acl.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/acl.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.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.
+ */
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "xattr.h"
+#include "acl.h"
+
+#define get_inode_mode(i)      ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+                                       (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
+
+static inline size_t f2fs_acl_size(int count)
+{
+       if (count <= 4) {
+               return sizeof(struct f2fs_acl_header) +
+                       count * sizeof(struct f2fs_acl_entry_short);
+       } else {
+               return sizeof(struct f2fs_acl_header) +
+                       4 * sizeof(struct f2fs_acl_entry_short) +
+                       (count - 4) * sizeof(struct f2fs_acl_entry);
+       }
+}
+
+static inline int f2fs_acl_count(size_t size)
+{
+       ssize_t s;
+       size -= sizeof(struct f2fs_acl_header);
+       s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+       if (s < 0) {
+               if (size % sizeof(struct f2fs_acl_entry_short))
+                       return -1;
+               return size / sizeof(struct f2fs_acl_entry_short);
+       } else {
+               if (s % sizeof(struct f2fs_acl_entry))
+                       return -1;
+               return s / sizeof(struct f2fs_acl_entry) + 4;
+       }
+}
+
+static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
+{
+       int i, count;
+       struct posix_acl *acl;
+       struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+       struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+       const char *end = value + size;
+
+       if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
+               return ERR_PTR(-EINVAL);
+
+       count = f2fs_acl_count(size);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+
+       acl = posix_acl_alloc(count, GFP_KERNEL);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < count; i++) {
+
+               if ((char *)entry > end)
+                       goto fail;
+
+               acl->a_entries[i].e_tag  = le16_to_cpu(entry->e_tag);
+               acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
+
+               switch (acl->a_entries[i].e_tag) {
+               case ACL_USER_OBJ:
+               case ACL_GROUP_OBJ:
+               case ACL_MASK:
+               case ACL_OTHER:
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry_short));
+                       break;
+
+               case ACL_USER:
+                       acl->a_entries[i].e_uid =
+                               make_kuid(&init_user_ns,
+                                               le32_to_cpu(entry->e_id));
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry));
+                       break;
+               case ACL_GROUP:
+                       acl->a_entries[i].e_gid =
+                               make_kgid(&init_user_ns,
+                                               le32_to_cpu(entry->e_id));
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry));
+                       break;
+               default:
+                       goto fail;
+               }
+       }
+       if ((char *)entry != end)
+               goto fail;
+       return acl;
+fail:
+       posix_acl_release(acl);
+       return ERR_PTR(-EINVAL);
+}
+
+static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
+{
+       struct f2fs_acl_header *f2fs_acl;
+       struct f2fs_acl_entry *entry;
+       int i;
+
+       f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
+                       sizeof(struct f2fs_acl_entry), GFP_KERNEL);
+       if (!f2fs_acl)
+               return ERR_PTR(-ENOMEM);
+
+       f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION);
+       entry = (struct f2fs_acl_entry *)(f2fs_acl + 1);
+
+       for (i = 0; i < acl->a_count; i++) {
+
+               entry->e_tag  = cpu_to_le16(acl->a_entries[i].e_tag);
+               entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm);
+
+               switch (acl->a_entries[i].e_tag) {
+               case ACL_USER:
+                       entry->e_id = cpu_to_le32(
+                                       from_kuid(&init_user_ns,
+                                               acl->a_entries[i].e_uid));
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry));
+                       break;
+               case ACL_GROUP:
+                       entry->e_id = cpu_to_le32(
+                                       from_kgid(&init_user_ns,
+                                               acl->a_entries[i].e_gid));
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry));
+                       break;
+               case ACL_USER_OBJ:
+               case ACL_GROUP_OBJ:
+               case ACL_MASK:
+               case ACL_OTHER:
+                       entry = (struct f2fs_acl_entry *)((char *)entry +
+                                       sizeof(struct f2fs_acl_entry_short));
+                       break;
+               default:
+                       goto fail;
+               }
+       }
+       *size = f2fs_acl_size(acl->a_count);
+       return (void *)f2fs_acl;
+
+fail:
+       kfree(f2fs_acl);
+       return ERR_PTR(-EINVAL);
+}
+
+struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+       void *value = NULL;
+       struct posix_acl *acl;
+       int retval;
+
+       if (!test_opt(sbi, POSIX_ACL))
+               return NULL;
+
+       acl = get_cached_acl(inode, type);
+       if (acl != ACL_NOT_CACHED)
+               return acl;
+
+       if (type == ACL_TYPE_ACCESS)
+               name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
+
+       retval = f2fs_getxattr(inode, name_index, "", NULL, 0);
+       if (retval > 0) {
+               value = kmalloc(retval, GFP_KERNEL);
+               if (!value)
+                       return ERR_PTR(-ENOMEM);
+               retval = f2fs_getxattr(inode, name_index, "", value, retval);
+       }
+
+       if (retval > 0)
+               acl = f2fs_acl_from_disk(value, retval);
+       else if (retval == -ENODATA)
+               acl = NULL;
+       else
+               acl = ERR_PTR(retval);
+       kfree(value);
+
+       if (!IS_ERR(acl))
+               set_cached_acl(inode, type, acl);
+
+       return acl;
+}
+
+static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       int name_index;
+       void *value = NULL;
+       size_t size = 0;
+       int error;
+
+       if (!test_opt(sbi, POSIX_ACL))
+               return 0;
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
+               if (acl) {
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
+                       if (error < 0)
+                               return error;
+                       set_acl_inode(fi, inode->i_mode);
+                       if (error == 0)
+                               acl = NULL;
+               }
+               break;
+
+       case ACL_TYPE_DEFAULT:
+               name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+               if (!S_ISDIR(inode->i_mode))
+                       return acl ? -EACCES : 0;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (acl) {
+               value = f2fs_acl_to_disk(acl, &size);
+               if (IS_ERR(value)) {
+                       cond_clear_inode_flag(fi, FI_ACL_MODE);
+                       return (int)PTR_ERR(value);
+               }
+       }
+
+       error = f2fs_setxattr(inode, name_index, "", value, size);
+
+       kfree(value);
+       if (!error)
+               set_cached_acl(inode, type, acl);
+
+       cond_clear_inode_flag(fi, FI_ACL_MODE);
+       return error;
+}
+
+int f2fs_init_acl(struct inode *inode, struct inode *dir)
+{
+       struct posix_acl *acl = NULL;
+       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       int error = 0;
+
+       if (!S_ISLNK(inode->i_mode)) {
+               if (test_opt(sbi, POSIX_ACL)) {
+                       acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
+                       if (IS_ERR(acl))
+                               return PTR_ERR(acl);
+               }
+               if (!acl)
+                       inode->i_mode &= ~current_umask();
+       }
+
+       if (test_opt(sbi, POSIX_ACL) && acl) {
+
+               if (S_ISDIR(inode->i_mode)) {
+                       error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+                       if (error)
+                               goto cleanup;
+               }
+               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
+               if (error < 0)
+                       return error;
+               if (error > 0)
+                       error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+       }
+cleanup:
+       posix_acl_release(acl);
+       return error;
+}
+
+int f2fs_acl_chmod(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct posix_acl *acl;
+       int error;
+       mode_t mode = get_inode_mode(inode);
+
+       if (!test_opt(sbi, POSIX_ACL))
+               return 0;
+       if (S_ISLNK(mode))
+               return -EOPNOTSUPP;
+
+       acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl) || !acl)
+               return PTR_ERR(acl);
+
+       error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
+       if (error)
+               return error;
+       error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+       posix_acl_release(acl);
+       return error;
+}
+
+static size_t f2fs_xattr_list_acl(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       const char *xname = POSIX_ACL_XATTR_DEFAULT;
+       size_t size;
+
+       if (!test_opt(sbi, POSIX_ACL))
+               return 0;
+
+       if (type == ACL_TYPE_ACCESS)
+               xname = POSIX_ACL_XATTR_ACCESS;
+
+       size = strlen(xname) + 1;
+       if (list && size <= list_size)
+               memcpy(list, xname, size);
+       return size;
+}
+
+static int f2fs_xattr_get_acl(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       struct posix_acl *acl;
+       int error;
+
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(sbi, POSIX_ACL))
+               return -EOPNOTSUPP;
+
+       acl = f2fs_get_acl(dentry->d_inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (!acl)
+               return -ENODATA;
+       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
+       posix_acl_release(acl);
+
+       return error;
+}
+
+static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       struct inode *inode = dentry->d_inode;
+       struct posix_acl *acl = NULL;
+       int error;
+
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(sbi, POSIX_ACL))
+               return -EOPNOTSUPP;
+       if (!inode_owner_or_capable(inode))
+               return -EPERM;
+
+       if (value) {
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (acl) {
+                       error = posix_acl_valid(acl);
+                       if (error)
+                               goto release_and_out;
+               }
+       } else {
+               acl = NULL;
+       }
+
+       error = f2fs_set_acl(inode, type, acl);
+
+release_and_out:
+       posix_acl_release(acl);
+       return error;
+}
+
+const struct xattr_handler f2fs_xattr_acl_default_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags = ACL_TYPE_DEFAULT,
+       .list = f2fs_xattr_list_acl,
+       .get = f2fs_xattr_get_acl,
+       .set = f2fs_xattr_set_acl,
+};
+
+const struct xattr_handler f2fs_xattr_acl_access_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags = ACL_TYPE_ACCESS,
+       .list = f2fs_xattr_list_acl,
+       .get = f2fs_xattr_get_acl,
+       .set = f2fs_xattr_set_acl,
+};
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
new file mode 100644 (file)
index 0000000..80f4306
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * fs/f2fs/acl.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/acl.h
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.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 __F2FS_ACL_H__
+#define __F2FS_ACL_H__
+
+#include <linux/posix_acl_xattr.h>
+
+#define F2FS_ACL_VERSION       0x0001
+
+struct f2fs_acl_entry {
+       __le16 e_tag;
+       __le16 e_perm;
+       __le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+       __le16 e_tag;
+       __le16 e_perm;
+};
+
+struct f2fs_acl_header {
+       __le32 a_version;
+};
+
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+
+extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type);
+extern int f2fs_acl_chmod(struct inode *inode);
+extern int f2fs_init_acl(struct inode *inode, struct inode *dir);
+#else
+#define f2fs_check_acl NULL
+#define f2fs_get_acl   NULL
+#define f2fs_set_acl   NULL
+
+static inline int f2fs_acl_chmod(struct inode *inode)
+{
+       return 0;
+}
+
+static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
+{
+       return 0;
+}
+#endif
+#endif /* __F2FS_ACL_H__ */
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
new file mode 100644 (file)
index 0000000..ff3c843
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * fs/f2fs/checkpoint.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/bio.h>
+#include <linux/mpage.h>
+#include <linux/writeback.h>
+#include <linux/blkdev.h>
+#include <linux/f2fs_fs.h>
+#include <linux/pagevec.h>
+#include <linux/swap.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *orphan_entry_slab;
+static struct kmem_cache *inode_entry_slab;
+
+/*
+ * We guarantee no failure on the returned page.
+ */
+struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+       struct address_space *mapping = sbi->meta_inode->i_mapping;
+       struct page *page = NULL;
+repeat:
+       page = grab_cache_page(mapping, index);
+       if (!page) {
+               cond_resched();
+               goto repeat;
+       }
+
+       /* We wait writeback only inside grab_meta_page() */
+       wait_on_page_writeback(page);
+       SetPageUptodate(page);
+       return page;
+}
+
+/*
+ * We guarantee no failure on the returned page.
+ */
+struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+       struct address_space *mapping = sbi->meta_inode->i_mapping;
+       struct page *page;
+repeat:
+       page = grab_cache_page(mapping, index);
+       if (!page) {
+               cond_resched();
+               goto repeat;
+       }
+       if (f2fs_readpage(sbi, page, index, READ_SYNC)) {
+               f2fs_put_page(page, 1);
+               goto repeat;
+       }
+       mark_page_accessed(page);
+
+       /* We do not allow returning an errorneous page */
+       return page;
+}
+
+static int f2fs_write_meta_page(struct page *page,
+                               struct writeback_control *wbc)
+{
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       int err;
+
+       wait_on_page_writeback(page);
+
+       err = write_meta_page(sbi, page, wbc);
+       if (err) {
+               wbc->pages_skipped++;
+               set_page_dirty(page);
+       }
+
+       dec_page_count(sbi, F2FS_DIRTY_META);
+
+       /* In this case, we should not unlock this page */
+       if (err != AOP_WRITEPAGE_ACTIVATE)
+               unlock_page(page);
+       return err;
+}
+
+static int f2fs_write_meta_pages(struct address_space *mapping,
+                               struct writeback_control *wbc)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+       struct block_device *bdev = sbi->sb->s_bdev;
+       long written;
+
+       if (wbc->for_kupdate)
+               return 0;
+
+       if (get_pages(sbi, F2FS_DIRTY_META) == 0)
+               return 0;
+
+       /* if mounting is failed, skip writing node pages */
+       mutex_lock(&sbi->cp_mutex);
+       written = sync_meta_pages(sbi, META, bio_get_nr_vecs(bdev));
+       mutex_unlock(&sbi->cp_mutex);
+       wbc->nr_to_write -= written;
+       return 0;
+}
+
+long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
+                                               long nr_to_write)
+{
+       struct address_space *mapping = sbi->meta_inode->i_mapping;
+       pgoff_t index = 0, end = LONG_MAX;
+       struct pagevec pvec;
+       long nwritten = 0;
+       struct writeback_control wbc = {
+               .for_reclaim = 0,
+       };
+
+       pagevec_init(&pvec, 0);
+
+       while (index <= end) {
+               int i, nr_pages;
+               nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+                               PAGECACHE_TAG_DIRTY,
+                               min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+               if (nr_pages == 0)
+                       break;
+
+               for (i = 0; i < nr_pages; i++) {
+                       struct page *page = pvec.pages[i];
+                       lock_page(page);
+                       BUG_ON(page->mapping != mapping);
+                       BUG_ON(!PageDirty(page));
+                       clear_page_dirty_for_io(page);
+                       f2fs_write_meta_page(page, &wbc);
+                       if (nwritten++ >= nr_to_write)
+                               break;
+               }
+               pagevec_release(&pvec);
+               cond_resched();
+       }
+
+       if (nwritten)
+               f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
+
+       return nwritten;
+}
+
+static int f2fs_set_meta_page_dirty(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+
+       SetPageUptodate(page);
+       if (!PageDirty(page)) {
+               __set_page_dirty_nobuffers(page);
+               inc_page_count(sbi, F2FS_DIRTY_META);
+               F2FS_SET_SB_DIRT(sbi);
+               return 1;
+       }
+       return 0;
+}
+
+const struct address_space_operations f2fs_meta_aops = {
+       .writepage      = f2fs_write_meta_page,
+       .writepages     = f2fs_write_meta_pages,
+       .set_page_dirty = f2fs_set_meta_page_dirty,
+};
+
+int check_orphan_space(struct f2fs_sb_info *sbi)
+{
+       unsigned int max_orphans;
+       int err = 0;
+
+       /*
+        * considering 512 blocks in a segment 5 blocks are needed for cp
+        * and log segment summaries. Remaining blocks are used to keep
+        * orphan entries with the limitation one reserved segment
+        * for cp pack we can have max 1020*507 orphan entries
+        */
+       max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
+       mutex_lock(&sbi->orphan_inode_mutex);
+       if (sbi->n_orphans >= max_orphans)
+               err = -ENOSPC;
+       mutex_unlock(&sbi->orphan_inode_mutex);
+       return err;
+}
+
+void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+{
+       struct list_head *head, *this;
+       struct orphan_inode_entry *new = NULL, *orphan = NULL;
+
+       mutex_lock(&sbi->orphan_inode_mutex);
+       head = &sbi->orphan_inode_list;
+       list_for_each(this, head) {
+               orphan = list_entry(this, struct orphan_inode_entry, list);
+               if (orphan->ino == ino)
+                       goto out;
+               if (orphan->ino > ino)
+                       break;
+               orphan = NULL;
+       }
+retry:
+       new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
+       if (!new) {
+               cond_resched();
+               goto retry;
+       }
+       new->ino = ino;
+
+       /* add new_oentry into list which is sorted by inode number */
+       if (orphan) {
+               struct orphan_inode_entry *prev;
+
+               /* get previous entry */
+               prev = list_entry(orphan->list.prev, typeof(*prev), list);
+               if (&prev->list != head)
+                       /* insert new orphan inode entry */
+                       list_add(&new->list, &prev->list);
+               else
+                       list_add(&new->list, head);
+       } else {
+               list_add_tail(&new->list, head);
+       }
+       sbi->n_orphans++;
+out:
+       mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+{
+       struct list_head *this, *next, *head;
+       struct orphan_inode_entry *orphan;
+
+       mutex_lock(&sbi->orphan_inode_mutex);
+       head = &sbi->orphan_inode_list;
+       list_for_each_safe(this, next, head) {
+               orphan = list_entry(this, struct orphan_inode_entry, list);
+               if (orphan->ino == ino) {
+                       list_del(&orphan->list);
+                       kmem_cache_free(orphan_entry_slab, orphan);
+                       sbi->n_orphans--;
+                       break;
+               }
+       }
+       mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+{
+       struct inode *inode = f2fs_iget(sbi->sb, ino);
+       BUG_ON(IS_ERR(inode));
+       clear_nlink(inode);
+
+       /* truncate all the data during iput */
+       iput(inode);
+}
+
+int recover_orphan_inodes(struct f2fs_sb_info *sbi)
+{
+       block_t start_blk, orphan_blkaddr, i, j;
+
+       if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
+               return 0;
+
+       sbi->por_doing = 1;
+       start_blk = __start_cp_addr(sbi) + 1;
+       orphan_blkaddr = __start_sum_addr(sbi) - 1;
+
+       for (i = 0; i < orphan_blkaddr; i++) {
+               struct page *page = get_meta_page(sbi, start_blk + i);
+               struct f2fs_orphan_block *orphan_blk;
+
+               orphan_blk = (struct f2fs_orphan_block *)page_address(page);
+               for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
+                       nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
+                       recover_orphan_inode(sbi, ino);
+               }
+               f2fs_put_page(page, 1);
+       }
+       /* clear Orphan Flag */
+       clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
+       sbi->por_doing = 0;
+       return 0;
+}
+
+static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+       struct list_head *head, *this, *next;
+       struct f2fs_orphan_block *orphan_blk = NULL;
+       struct page *page = NULL;
+       unsigned int nentries = 0;
+       unsigned short index = 1;
+       unsigned short orphan_blocks;
+
+       orphan_blocks = (unsigned short)((sbi->n_orphans +
+               (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
+
+       mutex_lock(&sbi->orphan_inode_mutex);
+       head = &sbi->orphan_inode_list;
+
+       /* loop for each orphan inode entry and write them in Jornal block */
+       list_for_each_safe(this, next, head) {
+               struct orphan_inode_entry *orphan;
+
+               orphan = list_entry(this, struct orphan_inode_entry, list);
+
+               if (nentries == F2FS_ORPHANS_PER_BLOCK) {
+                       /*
+                        * an orphan block is full of 1020 entries,
+                        * then we need to flush current orphan blocks
+                        * and bring another one in memory
+                        */
+                       orphan_blk->blk_addr = cpu_to_le16(index);
+                       orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
+                       orphan_blk->entry_count = cpu_to_le32(nentries);
+                       set_page_dirty(page);
+                       f2fs_put_page(page, 1);
+                       index++;
+                       start_blk++;
+                       nentries = 0;
+                       page = NULL;
+               }
+               if (page)
+                       goto page_exist;
+
+               page = grab_meta_page(sbi, start_blk);
+               orphan_blk = (struct f2fs_orphan_block *)page_address(page);
+               memset(orphan_blk, 0, sizeof(*orphan_blk));
+page_exist:
+               orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
+       }
+       if (!page)
+               goto end;
+
+       orphan_blk->blk_addr = cpu_to_le16(index);
+       orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
+       orphan_blk->entry_count = cpu_to_le32(nentries);
+       set_page_dirty(page);
+       f2fs_put_page(page, 1);
+end:
+       mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
+                               block_t cp_addr, unsigned long long *version)
+{
+       struct page *cp_page_1, *cp_page_2 = NULL;
+       unsigned long blk_size = sbi->blocksize;
+       struct f2fs_checkpoint *cp_block;
+       unsigned long long cur_version = 0, pre_version = 0;
+       unsigned int crc = 0;
+       size_t crc_offset;
+
+       /* Read the 1st cp block in this CP pack */
+       cp_page_1 = get_meta_page(sbi, cp_addr);
+
+       /* get the version number */
+       cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1);
+       crc_offset = le32_to_cpu(cp_block->checksum_offset);
+       if (crc_offset >= blk_size)
+               goto invalid_cp1;
+
+       crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+       if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+               goto invalid_cp1;
+
+       pre_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+       /* Read the 2nd cp block in this CP pack */
+       cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
+       cp_page_2 = get_meta_page(sbi, cp_addr);
+
+       cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
+       crc_offset = le32_to_cpu(cp_block->checksum_offset);
+       if (crc_offset >= blk_size)
+               goto invalid_cp2;
+
+       crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+       if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+               goto invalid_cp2;
+
+       cur_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+       if (cur_version == pre_version) {
+               *version = cur_version;
+               f2fs_put_page(cp_page_2, 1);
+               return cp_page_1;
+       }
+invalid_cp2:
+       f2fs_put_page(cp_page_2, 1);
+invalid_cp1:
+       f2fs_put_page(cp_page_1, 1);
+       return NULL;
+}
+
+int get_valid_checkpoint(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_checkpoint *cp_block;
+       struct f2fs_super_block *fsb = sbi->raw_super;
+       struct page *cp1, *cp2, *cur_page;
+       unsigned long blk_size = sbi->blocksize;
+       unsigned long long cp1_version = 0, cp2_version = 0;
+       unsigned long long cp_start_blk_no;
+
+       sbi->ckpt = kzalloc(blk_size, GFP_KERNEL);
+       if (!sbi->ckpt)
+               return -ENOMEM;
+       /*
+        * Finding out valid cp block involves read both
+        * sets( cp pack1 and cp pack 2)
+        */
+       cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr);
+       cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
+
+       /* The second checkpoint pack should start at the next segment */
+       cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+       cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
+
+       if (cp1 && cp2) {
+               if (ver_after(cp2_version, cp1_version))
+                       cur_page = cp2;
+               else
+                       cur_page = cp1;
+       } else if (cp1) {
+               cur_page = cp1;
+       } else if (cp2) {
+               cur_page = cp2;
+       } else {
+               goto fail_no_cp;
+       }
+
+       cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
+       memcpy(sbi->ckpt, cp_block, blk_size);
+
+       f2fs_put_page(cp1, 1);
+       f2fs_put_page(cp2, 1);
+       return 0;
+
+fail_no_cp:
+       kfree(sbi->ckpt);
+       return -EINVAL;
+}
+
+void set_dirty_dir_page(struct inode *inode, struct page *page)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct list_head *head = &sbi->dir_inode_list;
+       struct dir_inode_entry *new;
+       struct list_head *this;
+
+       if (!S_ISDIR(inode->i_mode))
+               return;
+retry:
+       new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
+       if (!new) {
+               cond_resched();
+               goto retry;
+       }
+       new->inode = inode;
+       INIT_LIST_HEAD(&new->list);
+
+       spin_lock(&sbi->dir_inode_lock);
+       list_for_each(this, head) {
+               struct dir_inode_entry *entry;
+               entry = list_entry(this, struct dir_inode_entry, list);
+               if (entry->inode == inode) {
+                       kmem_cache_free(inode_entry_slab, new);
+                       goto out;
+               }
+       }
+       list_add_tail(&new->list, head);
+       sbi->n_dirty_dirs++;
+
+       BUG_ON(!S_ISDIR(inode->i_mode));
+out:
+       inc_page_count(sbi, F2FS_DIRTY_DENTS);
+       inode_inc_dirty_dents(inode);
+       SetPagePrivate(page);
+
+       spin_unlock(&sbi->dir_inode_lock);
+}
+
+void remove_dirty_dir_inode(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct list_head *head = &sbi->dir_inode_list;
+       struct list_head *this;
+
+       if (!S_ISDIR(inode->i_mode))
+               return;
+
+       spin_lock(&sbi->dir_inode_lock);
+       if (atomic_read(&F2FS_I(inode)->dirty_dents))
+               goto out;
+
+       list_for_each(this, head) {
+               struct dir_inode_entry *entry;
+               entry = list_entry(this, struct dir_inode_entry, list);
+               if (entry->inode == inode) {
+                       list_del(&entry->list);
+                       kmem_cache_free(inode_entry_slab, entry);
+                       sbi->n_dirty_dirs--;
+                       break;
+               }
+       }
+out:
+       spin_unlock(&sbi->dir_inode_lock);
+}
+
+void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
+{
+       struct list_head *head = &sbi->dir_inode_list;
+       struct dir_inode_entry *entry;
+       struct inode *inode;
+retry:
+       spin_lock(&sbi->dir_inode_lock);
+       if (list_empty(head)) {
+               spin_unlock(&sbi->dir_inode_lock);
+               return;
+       }
+       entry = list_entry(head->next, struct dir_inode_entry, list);
+       inode = igrab(entry->inode);
+       spin_unlock(&sbi->dir_inode_lock);
+       if (inode) {
+               filemap_flush(inode->i_mapping);
+               iput(inode);
+       } else {
+               /*
+                * We should submit bio, since it exists several
+                * wribacking dentry pages in the freeing inode.
+                */
+               f2fs_submit_bio(sbi, DATA, true);
+       }
+       goto retry;
+}
+
+/*
+ * Freeze all the FS-operations for checkpoint.
+ */
+void block_operations(struct f2fs_sb_info *sbi)
+{
+       int t;
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .for_reclaim = 0,
+       };
+
+       /* Stop renaming operation */
+       mutex_lock_op(sbi, RENAME);
+       mutex_lock_op(sbi, DENTRY_OPS);
+
+retry_dents:
+       /* write all the dirty dentry pages */
+       sync_dirty_dir_inodes(sbi);
+
+       mutex_lock_op(sbi, DATA_WRITE);
+       if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
+               mutex_unlock_op(sbi, DATA_WRITE);
+               goto retry_dents;
+       }
+
+       /* block all the operations */
+       for (t = DATA_NEW; t <= NODE_TRUNC; t++)
+               mutex_lock_op(sbi, t);
+
+       mutex_lock(&sbi->write_inode);
+
+       /*
+        * POR: we should ensure that there is no dirty node pages
+        * until finishing nat/sit flush.
+        */
+retry:
+       sync_node_pages(sbi, 0, &wbc);
+
+       mutex_lock_op(sbi, NODE_WRITE);
+
+       if (get_pages(sbi, F2FS_DIRTY_NODES)) {
+               mutex_unlock_op(sbi, NODE_WRITE);
+               goto retry;
+       }
+       mutex_unlock(&sbi->write_inode);
+}
+
+static void unblock_operations(struct f2fs_sb_info *sbi)
+{
+       int t;
+       for (t = NODE_WRITE; t >= RENAME; t--)
+               mutex_unlock_op(sbi, t);
+}
+
+static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       nid_t last_nid = 0;
+       block_t start_blk;
+       struct page *cp_page;
+       unsigned int data_sum_blocks, orphan_blocks;
+       unsigned int crc32 = 0;
+       void *kaddr;
+       int i;
+
+       /* Flush all the NAT/SIT pages */
+       while (get_pages(sbi, F2FS_DIRTY_META))
+               sync_meta_pages(sbi, META, LONG_MAX);
+
+       next_free_nid(sbi, &last_nid);
+
+       /*
+        * modify checkpoint
+        * version number is already updated
+        */
+       ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
+       ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
+       ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
+       for (i = 0; i < 3; i++) {
+               ckpt->cur_node_segno[i] =
+                       cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
+               ckpt->cur_node_blkoff[i] =
+                       cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE));
+               ckpt->alloc_type[i + CURSEG_HOT_NODE] =
+                               curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
+       }
+       for (i = 0; i < 3; i++) {
+               ckpt->cur_data_segno[i] =
+                       cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
+               ckpt->cur_data_blkoff[i] =
+                       cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA));
+               ckpt->alloc_type[i + CURSEG_HOT_DATA] =
+                               curseg_alloc_type(sbi, i + CURSEG_HOT_DATA);
+       }
+
+       ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
+       ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
+       ckpt->next_free_nid = cpu_to_le32(last_nid);
+
+       /* 2 cp  + n data seg summary + orphan inode blocks */
+       data_sum_blocks = npages_for_summary_flush(sbi);
+       if (data_sum_blocks < 3)
+               set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
+       else
+               clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
+
+       orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
+                                       / F2FS_ORPHANS_PER_BLOCK;
+       ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
+
+       if (is_umount) {
+               set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
+               ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
+                       data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
+       } else {
+               clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
+               ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
+                       data_sum_blocks + orphan_blocks);
+       }
+
+       if (sbi->n_orphans)
+               set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
+       else
+               clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
+
+       /* update SIT/NAT bitmap */
+       get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
+       get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
+
+       crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
+       *(__le32 *)((unsigned char *)ckpt +
+                               le32_to_cpu(ckpt->checksum_offset))
+                               = cpu_to_le32(crc32);
+
+       start_blk = __start_cp_addr(sbi);
+
+       /* write out checkpoint buffer at block 0 */
+       cp_page = grab_meta_page(sbi, start_blk++);
+       kaddr = page_address(cp_page);
+       memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
+       set_page_dirty(cp_page);
+       f2fs_put_page(cp_page, 1);
+
+       if (sbi->n_orphans) {
+               write_orphan_inodes(sbi, start_blk);
+               start_blk += orphan_blocks;
+       }
+
+       write_data_summaries(sbi, start_blk);
+       start_blk += data_sum_blocks;
+       if (is_umount) {
+               write_node_summaries(sbi, start_blk);
+               start_blk += NR_CURSEG_NODE_TYPE;
+       }
+
+       /* writeout checkpoint block */
+       cp_page = grab_meta_page(sbi, start_blk);
+       kaddr = page_address(cp_page);
+       memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
+       set_page_dirty(cp_page);
+       f2fs_put_page(cp_page, 1);
+
+       /* wait for previous submitted node/meta pages writeback */
+       while (get_pages(sbi, F2FS_WRITEBACK))
+               congestion_wait(BLK_RW_ASYNC, HZ / 50);
+
+       filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
+       filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
+
+       /* update user_block_counts */
+       sbi->last_valid_block_count = sbi->total_valid_block_count;
+       sbi->alloc_valid_block_count = 0;
+
+       /* Here, we only have one bio having CP pack */
+       if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))
+               sbi->sb->s_flags |= MS_RDONLY;
+       else
+               sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
+
+       clear_prefree_segments(sbi);
+       F2FS_RESET_SB_DIRT(sbi);
+}
+
+/*
+ * We guarantee that this checkpoint procedure should not fail.
+ */
+void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       unsigned long long ckpt_ver;
+
+       if (!blocked) {
+               mutex_lock(&sbi->cp_mutex);
+               block_operations(sbi);
+       }
+
+       f2fs_submit_bio(sbi, DATA, true);
+       f2fs_submit_bio(sbi, NODE, true);
+       f2fs_submit_bio(sbi, META, true);
+
+       /*
+        * update checkpoint pack index
+        * Increase the version number so that
+        * SIT entries and seg summaries are written at correct place
+        */
+       ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver);
+       ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
+
+       /* write cached NAT/SIT entries to NAT/SIT area */
+       flush_nat_entries(sbi);
+       flush_sit_entries(sbi);
+
+       reset_victim_segmap(sbi);
+
+       /* unlock all the fs_lock[] in do_checkpoint() */
+       do_checkpoint(sbi, is_umount);
+
+       unblock_operations(sbi);
+       mutex_unlock(&sbi->cp_mutex);
+}
+
+void init_orphan_info(struct f2fs_sb_info *sbi)
+{
+       mutex_init(&sbi->orphan_inode_mutex);
+       INIT_LIST_HEAD(&sbi->orphan_inode_list);
+       sbi->n_orphans = 0;
+}
+
+int __init create_checkpoint_caches(void)
+{
+       orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
+                       sizeof(struct orphan_inode_entry), NULL);
+       if (unlikely(!orphan_entry_slab))
+               return -ENOMEM;
+       inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
+                       sizeof(struct dir_inode_entry), NULL);
+       if (unlikely(!inode_entry_slab)) {
+               kmem_cache_destroy(orphan_entry_slab);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void destroy_checkpoint_caches(void)
+{
+       kmem_cache_destroy(orphan_entry_slab);
+       kmem_cache_destroy(inode_entry_slab);
+}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
new file mode 100644 (file)
index 0000000..7bd22a2
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * fs/f2fs/data.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/mpage.h>
+#include <linux/writeback.h>
+#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/prefetch.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+/*
+ * Lock ordering for the change of data block address:
+ * ->data_page
+ *  ->node_page
+ *    update block addresses in the node page
+ */
+static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
+{
+       struct f2fs_node *rn;
+       __le32 *addr_array;
+       struct page *node_page = dn->node_page;
+       unsigned int ofs_in_node = dn->ofs_in_node;
+
+       wait_on_page_writeback(node_page);
+
+       rn = (struct f2fs_node *)page_address(node_page);
+
+       /* Get physical address of data block */
+       addr_array = blkaddr_in_node(rn);
+       addr_array[ofs_in_node] = cpu_to_le32(new_addr);
+       set_page_dirty(node_page);
+}
+
+int reserve_new_block(struct dnode_of_data *dn)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+
+       if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+               return -EPERM;
+       if (!inc_valid_block_count(sbi, dn->inode, 1))
+               return -ENOSPC;
+
+       __set_data_blkaddr(dn, NEW_ADDR);
+       dn->data_blkaddr = NEW_ADDR;
+       sync_inode_page(dn);
+       return 0;
+}
+
+static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
+                                       struct buffer_head *bh_result)
+{
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       pgoff_t start_fofs, end_fofs;
+       block_t start_blkaddr;
+
+       read_lock(&fi->ext.ext_lock);
+       if (fi->ext.len == 0) {
+               read_unlock(&fi->ext.ext_lock);
+               return 0;
+       }
+
+       sbi->total_hit_ext++;
+       start_fofs = fi->ext.fofs;
+       end_fofs = fi->ext.fofs + fi->ext.len - 1;
+       start_blkaddr = fi->ext.blk_addr;
+
+       if (pgofs >= start_fofs && pgofs <= end_fofs) {
+               unsigned int blkbits = inode->i_sb->s_blocksize_bits;
+               size_t count;
+
+               clear_buffer_new(bh_result);
+               map_bh(bh_result, inode->i_sb,
+                               start_blkaddr + pgofs - start_fofs);
+               count = end_fofs - pgofs + 1;
+               if (count < (UINT_MAX >> blkbits))
+                       bh_result->b_size = (count << blkbits);
+               else
+                       bh_result->b_size = UINT_MAX;
+
+               sbi->read_hit_ext++;
+               read_unlock(&fi->ext.ext_lock);
+               return 1;
+       }
+       read_unlock(&fi->ext.ext_lock);
+       return 0;
+}
+
+void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
+{
+       struct f2fs_inode_info *fi = F2FS_I(dn->inode);
+       pgoff_t fofs, start_fofs, end_fofs;
+       block_t start_blkaddr, end_blkaddr;
+
+       BUG_ON(blk_addr == NEW_ADDR);
+       fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
+
+       /* Update the page address in the parent node */
+       __set_data_blkaddr(dn, blk_addr);
+
+       write_lock(&fi->ext.ext_lock);
+
+       start_fofs = fi->ext.fofs;
+       end_fofs = fi->ext.fofs + fi->ext.len - 1;
+       start_blkaddr = fi->ext.blk_addr;
+       end_blkaddr = fi->ext.blk_addr + fi->ext.len - 1;
+
+       /* Drop and initialize the matched extent */
+       if (fi->ext.len == 1 && fofs == start_fofs)
+               fi->ext.len = 0;
+
+       /* Initial extent */
+       if (fi->ext.len == 0) {
+               if (blk_addr != NULL_ADDR) {
+                       fi->ext.fofs = fofs;
+                       fi->ext.blk_addr = blk_addr;
+                       fi->ext.len = 1;
+               }
+               goto end_update;
+       }
+
+       /* Frone merge */
+       if (fofs == start_fofs - 1 && blk_addr == start_blkaddr - 1) {
+               fi->ext.fofs--;
+               fi->ext.blk_addr--;
+               fi->ext.len++;
+               goto end_update;
+       }
+
+       /* Back merge */
+       if (fofs == end_fofs + 1 && blk_addr == end_blkaddr + 1) {
+               fi->ext.len++;
+               goto end_update;
+       }
+
+       /* Split the existing extent */
+       if (fi->ext.len > 1 &&
+               fofs >= start_fofs && fofs <= end_fofs) {
+               if ((end_fofs - fofs) < (fi->ext.len >> 1)) {
+                       fi->ext.len = fofs - start_fofs;
+               } else {
+                       fi->ext.fofs = fofs + 1;
+                       fi->ext.blk_addr = start_blkaddr +
+                                       fofs - start_fofs + 1;
+                       fi->ext.len -= fofs - start_fofs + 1;
+               }
+               goto end_update;
+       }
+       write_unlock(&fi->ext.ext_lock);
+       return;
+
+end_update:
+       write_unlock(&fi->ext.ext_lock);
+       sync_inode_page(dn);
+       return;
+}
+
+struct page *find_data_page(struct inode *inode, pgoff_t index)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct address_space *mapping = inode->i_mapping;
+       struct dnode_of_data dn;
+       struct page *page;
+       int err;
+
+       page = find_get_page(mapping, index);
+       if (page && PageUptodate(page))
+               return page;
+       f2fs_put_page(page, 0);
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+       if (err)
+               return ERR_PTR(err);
+       f2fs_put_dnode(&dn);
+
+       if (dn.data_blkaddr == NULL_ADDR)
+               return ERR_PTR(-ENOENT);
+
+       /* By fallocate(), there is no cached page, but with NEW_ADDR */
+       if (dn.data_blkaddr == NEW_ADDR)
+               return ERR_PTR(-EINVAL);
+
+       page = grab_cache_page(mapping, index);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+       if (err) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(err);
+       }
+       unlock_page(page);
+       return page;
+}
+
+/*
+ * If it tries to access a hole, return an error.
+ * Because, the callers, functions in dir.c and GC, should be able to know
+ * whether this page exists or not.
+ */
+struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct address_space *mapping = inode->i_mapping;
+       struct dnode_of_data dn;
+       struct page *page;
+       int err;
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+       if (err)
+               return ERR_PTR(err);
+       f2fs_put_dnode(&dn);
+
+       if (dn.data_blkaddr == NULL_ADDR)
+               return ERR_PTR(-ENOENT);
+
+       page = grab_cache_page(mapping, index);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       if (PageUptodate(page))
+               return page;
+
+       BUG_ON(dn.data_blkaddr == NEW_ADDR);
+       BUG_ON(dn.data_blkaddr == NULL_ADDR);
+
+       err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+       if (err) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(err);
+       }
+       return page;
+}
+
+/*
+ * Caller ensures that this data page is never allocated.
+ * A new zero-filled data page is allocated in the page cache.
+ */
+struct page *get_new_data_page(struct inode *inode, pgoff_t index,
+                                               bool new_i_size)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct address_space *mapping = inode->i_mapping;
+       struct page *page;
+       struct dnode_of_data dn;
+       int err;
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, index, 0);
+       if (err)
+               return ERR_PTR(err);
+
+       if (dn.data_blkaddr == NULL_ADDR) {
+               if (reserve_new_block(&dn)) {
+                       f2fs_put_dnode(&dn);
+                       return ERR_PTR(-ENOSPC);
+               }
+       }
+       f2fs_put_dnode(&dn);
+
+       page = grab_cache_page(mapping, index);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       if (PageUptodate(page))
+               return page;
+
+       if (dn.data_blkaddr == NEW_ADDR) {
+               zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+       } else {
+               err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+               if (err) {
+                       f2fs_put_page(page, 1);
+                       return ERR_PTR(err);
+               }
+       }
+       SetPageUptodate(page);
+
+       if (new_i_size &&
+               i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
+               i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT));
+               mark_inode_dirty_sync(inode);
+       }
+       return page;
+}
+
+static void read_end_io(struct bio *bio, int err)
+{
+       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+
+       do {
+               struct page *page = bvec->bv_page;
+
+               if (--bvec >= bio->bi_io_vec)
+                       prefetchw(&bvec->bv_page->flags);
+
+               if (uptodate) {
+                       SetPageUptodate(page);
+               } else {
+                       ClearPageUptodate(page);
+                       SetPageError(page);
+               }
+               unlock_page(page);
+       } while (bvec >= bio->bi_io_vec);
+       kfree(bio->bi_private);
+       bio_put(bio);
+}
+
+/*
+ * Fill the locked page with data located in the block address.
+ * Read operation is synchronous, and caller must unlock the page.
+ */
+int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
+                                       block_t blk_addr, int type)
+{
+       struct block_device *bdev = sbi->sb->s_bdev;
+       bool sync = (type == READ_SYNC);
+       struct bio *bio;
+
+       /* This page can be already read by other threads */
+       if (PageUptodate(page)) {
+               if (!sync)
+                       unlock_page(page);
+               return 0;
+       }
+
+       down_read(&sbi->bio_sem);
+
+       /* Allocate a new bio */
+       bio = f2fs_bio_alloc(bdev, 1);
+
+       /* Initialize the bio */
+       bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
+       bio->bi_end_io = read_end_io;
+
+       if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+               kfree(bio->bi_private);
+               bio_put(bio);
+               up_read(&sbi->bio_sem);
+               return -EFAULT;
+       }
+
+       submit_bio(type, bio);
+       up_read(&sbi->bio_sem);
+
+       /* wait for read completion if sync */
+       if (sync) {
+               lock_page(page);
+               if (PageError(page))
+                       return -EIO;
+       }
+       return 0;
+}
+
+/*
+ * This function should be used by the data read flow only where it
+ * does not check the "create" flag that indicates block allocation.
+ * The reason for this special functionality is to exploit VFS readahead
+ * mechanism.
+ */
+static int get_data_block_ro(struct inode *inode, sector_t iblock,
+                       struct buffer_head *bh_result, int create)
+{
+       unsigned int blkbits = inode->i_sb->s_blocksize_bits;
+       unsigned maxblocks = bh_result->b_size >> blkbits;
+       struct dnode_of_data dn;
+       pgoff_t pgofs;
+       int err;
+
+       /* Get the page offset from the block offset(iblock) */
+       pgofs = (pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits));
+
+       if (check_extent_cache(inode, pgofs, bh_result))
+               return 0;
+
+       /* When reading holes, we need its node page */
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
+       if (err)
+               return (err == -ENOENT) ? 0 : err;
+
+       /* It does not support data allocation */
+       BUG_ON(create);
+
+       if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) {
+               int i;
+               unsigned int end_offset;
+
+               end_offset = IS_INODE(dn.node_page) ?
+                               ADDRS_PER_INODE :
+                               ADDRS_PER_BLOCK;
+
+               clear_buffer_new(bh_result);
+
+               /* Give more consecutive addresses for the read ahead */
+               for (i = 0; i < end_offset - dn.ofs_in_node; i++)
+                       if (((datablock_addr(dn.node_page,
+                                                       dn.ofs_in_node + i))
+                               != (dn.data_blkaddr + i)) || maxblocks == i)
+                               break;
+               map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
+               bh_result->b_size = (i << blkbits);
+       }
+       f2fs_put_dnode(&dn);
+       return 0;
+}
+
+static int f2fs_read_data_page(struct file *file, struct page *page)
+{
+       return mpage_readpage(page, get_data_block_ro);
+}
+
+static int f2fs_read_data_pages(struct file *file,
+                       struct address_space *mapping,
+                       struct list_head *pages, unsigned nr_pages)
+{
+       return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
+}
+
+int do_write_data_page(struct page *page)
+{
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       block_t old_blk_addr, new_blk_addr;
+       struct dnode_of_data dn;
+       int err = 0;
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
+       if (err)
+               return err;
+
+       old_blk_addr = dn.data_blkaddr;
+
+       /* This page is already truncated */
+       if (old_blk_addr == NULL_ADDR)
+               goto out_writepage;
+
+       set_page_writeback(page);
+
+       /*
+        * If current allocation needs SSR,
+        * it had better in-place writes for updated data.
+        */
+       if (old_blk_addr != NEW_ADDR && !is_cold_data(page) &&
+                               need_inplace_update(inode)) {
+               rewrite_data_page(F2FS_SB(inode->i_sb), page,
+                                               old_blk_addr);
+       } else {
+               write_data_page(inode, page, &dn,
+                               old_blk_addr, &new_blk_addr);
+               update_extent_cache(new_blk_addr, &dn);
+               F2FS_I(inode)->data_version =
+                       le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
+       }
+out_writepage:
+       f2fs_put_dnode(&dn);
+       return err;
+}
+
+static int f2fs_write_data_page(struct page *page,
+                                       struct writeback_control *wbc)
+{
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       loff_t i_size = i_size_read(inode);
+       const pgoff_t end_index = ((unsigned long long) i_size)
+                                                       >> PAGE_CACHE_SHIFT;
+       unsigned offset;
+       int err = 0;
+
+       if (page->index < end_index)
+               goto out;
+
+       /*
+        * If the offset is out-of-range of file size,
+        * this page does not have to be written to disk.
+        */
+       offset = i_size & (PAGE_CACHE_SIZE - 1);
+       if ((page->index >= end_index + 1) || !offset) {
+               if (S_ISDIR(inode->i_mode)) {
+                       dec_page_count(sbi, F2FS_DIRTY_DENTS);
+                       inode_dec_dirty_dents(inode);
+               }
+               goto unlock_out;
+       }
+
+       zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+out:
+       if (sbi->por_doing)
+               goto redirty_out;
+
+       if (wbc->for_reclaim && !S_ISDIR(inode->i_mode) && !is_cold_data(page))
+               goto redirty_out;
+
+       mutex_lock_op(sbi, DATA_WRITE);
+       if (S_ISDIR(inode->i_mode)) {
+               dec_page_count(sbi, F2FS_DIRTY_DENTS);
+               inode_dec_dirty_dents(inode);
+       }
+       err = do_write_data_page(page);
+       if (err && err != -ENOENT) {
+               wbc->pages_skipped++;
+               set_page_dirty(page);
+       }
+       mutex_unlock_op(sbi, DATA_WRITE);
+
+       if (wbc->for_reclaim)
+               f2fs_submit_bio(sbi, DATA, true);
+
+       if (err == -ENOENT)
+               goto unlock_out;
+
+       clear_cold_data(page);
+       unlock_page(page);
+
+       if (!wbc->for_reclaim && !S_ISDIR(inode->i_mode))
+               f2fs_balance_fs(sbi);
+       return 0;
+
+unlock_out:
+       unlock_page(page);
+       return (err == -ENOENT) ? 0 : err;
+
+redirty_out:
+       wbc->pages_skipped++;
+       set_page_dirty(page);
+       return AOP_WRITEPAGE_ACTIVATE;
+}
+
+#define MAX_DESIRED_PAGES_WP   4096
+
+static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
+                       void *data)
+{
+       struct address_space *mapping = data;
+       int ret = mapping->a_ops->writepage(page, wbc);
+       mapping_set_error(mapping, ret);
+       return ret;
+}
+
+static int f2fs_write_data_pages(struct address_space *mapping,
+                           struct writeback_control *wbc)
+{
+       struct inode *inode = mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       int ret;
+       long excess_nrtw = 0, desired_nrtw;
+
+       if (wbc->nr_to_write < MAX_DESIRED_PAGES_WP) {
+               desired_nrtw = MAX_DESIRED_PAGES_WP;
+               excess_nrtw = desired_nrtw - wbc->nr_to_write;
+               wbc->nr_to_write = desired_nrtw;
+       }
+
+       if (!S_ISDIR(inode->i_mode))
+               mutex_lock(&sbi->writepages);
+       ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
+       if (!S_ISDIR(inode->i_mode))
+               mutex_unlock(&sbi->writepages);
+       f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
+
+       remove_dirty_dir_inode(inode);
+
+       wbc->nr_to_write -= excess_nrtw;
+       return ret;
+}
+
+static int f2fs_write_begin(struct file *file, struct address_space *mapping,
+               loff_t pos, unsigned len, unsigned flags,
+               struct page **pagep, void **fsdata)
+{
+       struct inode *inode = mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct page *page;
+       pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
+       struct dnode_of_data dn;
+       int err = 0;
+
+       /* for nobh_write_end */
+       *fsdata = NULL;
+
+       f2fs_balance_fs(sbi);
+
+       page = grab_cache_page_write_begin(mapping, index, flags);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
+       mutex_lock_op(sbi, DATA_NEW);
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, index, 0);
+       if (err) {
+               mutex_unlock_op(sbi, DATA_NEW);
+               f2fs_put_page(page, 1);
+               return err;
+       }
+
+       if (dn.data_blkaddr == NULL_ADDR) {
+               err = reserve_new_block(&dn);
+               if (err) {
+                       f2fs_put_dnode(&dn);
+                       mutex_unlock_op(sbi, DATA_NEW);
+                       f2fs_put_page(page, 1);
+                       return err;
+               }
+       }
+       f2fs_put_dnode(&dn);
+
+       mutex_unlock_op(sbi, DATA_NEW);
+
+       if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
+               return 0;
+
+       if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
+               unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+               unsigned end = start + len;
+
+               /* Reading beyond i_size is simple: memset to zero */
+               zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
+               return 0;
+       }
+
+       if (dn.data_blkaddr == NEW_ADDR) {
+               zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+       } else {
+               err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+               if (err) {
+                       f2fs_put_page(page, 1);
+                       return err;
+               }
+       }
+       SetPageUptodate(page);
+       clear_cold_data(page);
+       return 0;
+}
+
+static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
+               const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file->f_mapping->host;
+
+       if (rw == WRITE)
+               return 0;
+
+       /* Needs synchronization with the cleaner */
+       return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+                                                 get_data_block_ro);
+}
+
+static void f2fs_invalidate_data_page(struct page *page, unsigned long offset)
+{
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       if (S_ISDIR(inode->i_mode) && PageDirty(page)) {
+               dec_page_count(sbi, F2FS_DIRTY_DENTS);
+               inode_dec_dirty_dents(inode);
+       }
+       ClearPagePrivate(page);
+}
+
+static int f2fs_release_data_page(struct page *page, gfp_t wait)
+{
+       ClearPagePrivate(page);
+       return 0;
+}
+
+static int f2fs_set_data_page_dirty(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct inode *inode = mapping->host;
+
+       SetPageUptodate(page);
+       if (!PageDirty(page)) {
+               __set_page_dirty_nobuffers(page);
+               set_dirty_dir_page(inode, page);
+               return 1;
+       }
+       return 0;
+}
+
+static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
+{
+       return generic_block_bmap(mapping, block, get_data_block_ro);
+}
+
+const struct address_space_operations f2fs_dblock_aops = {
+       .readpage       = f2fs_read_data_page,
+       .readpages      = f2fs_read_data_pages,
+       .writepage      = f2fs_write_data_page,
+       .writepages     = f2fs_write_data_pages,
+       .write_begin    = f2fs_write_begin,
+       .write_end      = nobh_write_end,
+       .set_page_dirty = f2fs_set_data_page_dirty,
+       .invalidatepage = f2fs_invalidate_data_page,
+       .releasepage    = f2fs_release_data_page,
+       .direct_IO      = f2fs_direct_IO,
+       .bmap           = f2fs_bmap,
+};
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
new file mode 100644 (file)
index 0000000..c8c3730
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * f2fs debugging statistics
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ * Copyright (c) 2012 Linux Foundation
+ * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.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.
+ */
+
+#include <linux/fs.h>
+#include <linux/backing-dev.h>
+#include <linux/proc_fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/blkdev.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "gc.h"
+
+static LIST_HEAD(f2fs_stat_list);
+static struct dentry *debugfs_root;
+static DEFINE_MUTEX(f2fs_stat_mutex);
+
+static void update_general_status(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_stat_info *si = sbi->stat_info;
+       int i;
+
+       /* valid check of the segment numbers */
+       si->hit_ext = sbi->read_hit_ext;
+       si->total_ext = sbi->total_hit_ext;
+       si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
+       si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
+       si->ndirty_dirs = sbi->n_dirty_dirs;
+       si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
+       si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
+       si->rsvd_segs = reserved_segments(sbi);
+       si->overp_segs = overprovision_segments(sbi);
+       si->valid_count = valid_user_blocks(sbi);
+       si->valid_node_count = valid_node_count(sbi);
+       si->valid_inode_count = valid_inode_count(sbi);
+       si->utilization = utilization(sbi);
+
+       si->free_segs = free_segments(sbi);
+       si->free_secs = free_sections(sbi);
+       si->prefree_count = prefree_segments(sbi);
+       si->dirty_count = dirty_segments(sbi);
+       si->node_pages = sbi->node_inode->i_mapping->nrpages;
+       si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
+       si->nats = NM_I(sbi)->nat_cnt;
+       si->sits = SIT_I(sbi)->dirty_sentries;
+       si->fnids = NM_I(sbi)->fcnt;
+       si->bg_gc = sbi->bg_gc;
+       si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
+               * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+               / 2;
+       si->util_valid = (int)(written_block_count(sbi) >>
+                                               sbi->log_blocks_per_seg)
+               * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+               / 2;
+       si->util_invalid = 50 - si->util_free - si->util_valid;
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
+               struct curseg_info *curseg = CURSEG_I(sbi, i);
+               si->curseg[i] = curseg->segno;
+               si->cursec[i] = curseg->segno / sbi->segs_per_sec;
+               si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
+       }
+
+       for (i = 0; i < 2; i++) {
+               si->segment_count[i] = sbi->segment_count[i];
+               si->block_count[i] = sbi->block_count[i];
+       }
+}
+
+/*
+ * This function calculates BDF of every segments
+ */
+static void update_sit_info(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_stat_info *si = sbi->stat_info;
+       unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int segno, vblocks;
+       int ndirty = 0;
+
+       bimodal = 0;
+       total_vblocks = 0;
+       blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
+       hblks_per_sec = blks_per_sec / 2;
+       mutex_lock(&sit_i->sentry_lock);
+       for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+               vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+               dist = abs(vblocks - hblks_per_sec);
+               bimodal += dist * dist;
+
+               if (vblocks > 0 && vblocks < blks_per_sec) {
+                       total_vblocks += vblocks;
+                       ndirty++;
+               }
+       }
+       mutex_unlock(&sit_i->sentry_lock);
+       dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+       si->bimodal = bimodal / dist;
+       if (si->dirty_count)
+               si->avg_vblocks = total_vblocks / ndirty;
+       else
+               si->avg_vblocks = 0;
+}
+
+/*
+ * This function calculates memory footprint.
+ */
+static void update_mem_info(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_stat_info *si = sbi->stat_info;
+       unsigned npages;
+
+       if (si->base_mem)
+               goto get_cache;
+
+       si->base_mem = sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
+       si->base_mem += 2 * sizeof(struct f2fs_inode_info);
+       si->base_mem += sizeof(*sbi->ckpt);
+
+       /* build sm */
+       si->base_mem += sizeof(struct f2fs_sm_info);
+
+       /* build sit */
+       si->base_mem += sizeof(struct sit_info);
+       si->base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
+       si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
+       if (sbi->segs_per_sec > 1)
+               si->base_mem += sbi->total_sections *
+                       sizeof(struct sec_entry);
+       si->base_mem += __bitmap_size(sbi, SIT_BITMAP);
+
+       /* build free segmap */
+       si->base_mem += sizeof(struct free_segmap_info);
+       si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       si->base_mem += f2fs_bitmap_size(sbi->total_sections);
+
+       /* build curseg */
+       si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
+       si->base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
+
+       /* build dirty segmap */
+       si->base_mem += sizeof(struct dirty_seglist_info);
+       si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       si->base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+       /* buld nm */
+       si->base_mem += sizeof(struct f2fs_nm_info);
+       si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
+
+       /* build gc */
+       si->base_mem += sizeof(struct f2fs_gc_kthread);
+
+get_cache:
+       /* free nids */
+       si->cache_mem = NM_I(sbi)->fcnt;
+       si->cache_mem += NM_I(sbi)->nat_cnt;
+       npages = sbi->node_inode->i_mapping->nrpages;
+       si->cache_mem += npages << PAGE_CACHE_SHIFT;
+       npages = sbi->meta_inode->i_mapping->nrpages;
+       si->cache_mem += npages << PAGE_CACHE_SHIFT;
+       si->cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+       si->cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+}
+
+static int stat_show(struct seq_file *s, void *v)
+{
+       struct f2fs_stat_info *si, *next;
+       int i = 0;
+       int j;
+
+       mutex_lock(&f2fs_stat_mutex);
+       list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
+
+               update_general_status(si->sbi);
+
+               seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
+               seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
+                          si->sit_area_segs, si->nat_area_segs);
+               seq_printf(s, "[SSA: %d] [MAIN: %d",
+                          si->ssa_area_segs, si->main_area_segs);
+               seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
+                          si->overp_segs, si->rsvd_segs);
+               seq_printf(s, "Utilization: %d%% (%d valid blocks)\n",
+                          si->utilization, si->valid_count);
+               seq_printf(s, "  - Node: %u (Inode: %u, ",
+                          si->valid_node_count, si->valid_inode_count);
+               seq_printf(s, "Other: %u)\n  - Data: %u\n",
+                          si->valid_node_count - si->valid_inode_count,
+                          si->valid_count - si->valid_node_count);
+               seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
+                          si->main_area_segs, si->main_area_sections,
+                          si->main_area_zones);
+               seq_printf(s, "  - COLD  data: %d, %d, %d\n",
+                          si->curseg[CURSEG_COLD_DATA],
+                          si->cursec[CURSEG_COLD_DATA],
+                          si->curzone[CURSEG_COLD_DATA]);
+               seq_printf(s, "  - WARM  data: %d, %d, %d\n",
+                          si->curseg[CURSEG_WARM_DATA],
+                          si->cursec[CURSEG_WARM_DATA],
+                          si->curzone[CURSEG_WARM_DATA]);
+               seq_printf(s, "  - HOT   data: %d, %d, %d\n",
+                          si->curseg[CURSEG_HOT_DATA],
+                          si->cursec[CURSEG_HOT_DATA],
+                          si->curzone[CURSEG_HOT_DATA]);
+               seq_printf(s, "  - Dir   dnode: %d, %d, %d\n",
+                          si->curseg[CURSEG_HOT_NODE],
+                          si->cursec[CURSEG_HOT_NODE],
+                          si->curzone[CURSEG_HOT_NODE]);
+               seq_printf(s, "  - File   dnode: %d, %d, %d\n",
+                          si->curseg[CURSEG_WARM_NODE],
+                          si->cursec[CURSEG_WARM_NODE],
+                          si->curzone[CURSEG_WARM_NODE]);
+               seq_printf(s, "  - Indir nodes: %d, %d, %d\n",
+                          si->curseg[CURSEG_COLD_NODE],
+                          si->cursec[CURSEG_COLD_NODE],
+                          si->curzone[CURSEG_COLD_NODE]);
+               seq_printf(s, "\n  - Valid: %d\n  - Dirty: %d\n",
+                          si->main_area_segs - si->dirty_count -
+                          si->prefree_count - si->free_segs,
+                          si->dirty_count);
+               seq_printf(s, "  - Prefree: %d\n  - Free: %d (%d)\n\n",
+                          si->prefree_count, si->free_segs, si->free_secs);
+               seq_printf(s, "GC calls: %d (BG: %d)\n",
+                          si->call_count, si->bg_gc);
+               seq_printf(s, "  - data segments : %d\n", si->data_segs);
+               seq_printf(s, "  - node segments : %d\n", si->node_segs);
+               seq_printf(s, "Try to move %d blocks\n", si->tot_blks);
+               seq_printf(s, "  - data blocks : %d\n", si->data_blks);
+               seq_printf(s, "  - node blocks : %d\n", si->node_blks);
+               seq_printf(s, "\nExtent Hit Ratio: %d / %d\n",
+                          si->hit_ext, si->total_ext);
+               seq_printf(s, "\nBalancing F2FS Async:\n");
+               seq_printf(s, "  - nodes %4d in %4d\n",
+                          si->ndirty_node, si->node_pages);
+               seq_printf(s, "  - dents %4d in dirs:%4d\n",
+                          si->ndirty_dent, si->ndirty_dirs);
+               seq_printf(s, "  - meta %4d in %4d\n",
+                          si->ndirty_meta, si->meta_pages);
+               seq_printf(s, "  - NATs %5d > %lu\n",
+                          si->nats, NM_WOUT_THRESHOLD);
+               seq_printf(s, "  - SITs: %5d\n  - free_nids: %5d\n",
+                          si->sits, si->fnids);
+               seq_printf(s, "\nDistribution of User Blocks:");
+               seq_printf(s, " [ valid | invalid | free ]\n");
+               seq_printf(s, "  [");
+
+               for (j = 0; j < si->util_valid; j++)
+                       seq_printf(s, "-");
+               seq_printf(s, "|");
+
+               for (j = 0; j < si->util_invalid; j++)
+                       seq_printf(s, "-");
+               seq_printf(s, "|");
+
+               for (j = 0; j < si->util_free; j++)
+                       seq_printf(s, "-");
+               seq_printf(s, "]\n\n");
+               seq_printf(s, "SSR: %u blocks in %u segments\n",
+                          si->block_count[SSR], si->segment_count[SSR]);
+               seq_printf(s, "LFS: %u blocks in %u segments\n",
+                          si->block_count[LFS], si->segment_count[LFS]);
+
+               /* segment usage info */
+               update_sit_info(si->sbi);
+               seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n",
+                          si->bimodal, si->avg_vblocks);
+
+               /* memory footprint */
+               update_mem_info(si->sbi);
+               seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
+                               (si->base_mem + si->cache_mem) >> 10,
+                               si->base_mem >> 10, si->cache_mem >> 10);
+       }
+       mutex_unlock(&f2fs_stat_mutex);
+       return 0;
+}
+
+static int stat_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, stat_show, inode->i_private);
+}
+
+static const struct file_operations stat_fops = {
+       .open = stat_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+int f2fs_build_stats(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+       struct f2fs_stat_info *si;
+
+       sbi->stat_info = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
+       if (!sbi->stat_info)
+               return -ENOMEM;
+
+       si = sbi->stat_info;
+       si->all_area_segs = le32_to_cpu(raw_super->segment_count);
+       si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
+       si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
+       si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
+       si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
+       si->main_area_sections = le32_to_cpu(raw_super->section_count);
+       si->main_area_zones = si->main_area_sections /
+                               le32_to_cpu(raw_super->secs_per_zone);
+       si->sbi = sbi;
+
+       mutex_lock(&f2fs_stat_mutex);
+       list_add_tail(&si->stat_list, &f2fs_stat_list);
+       mutex_unlock(&f2fs_stat_mutex);
+
+       return 0;
+}
+
+void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_stat_info *si = sbi->stat_info;
+
+       mutex_lock(&f2fs_stat_mutex);
+       list_del(&si->stat_list);
+       mutex_unlock(&f2fs_stat_mutex);
+
+       kfree(sbi->stat_info);
+}
+
+void __init f2fs_create_root_stats(void)
+{
+       debugfs_root = debugfs_create_dir("f2fs", NULL);
+       if (debugfs_root)
+               debugfs_create_file("status", S_IRUGO, debugfs_root,
+                                        NULL, &stat_fops);
+}
+
+void f2fs_destroy_root_stats(void)
+{
+       debugfs_remove_recursive(debugfs_root);
+       debugfs_root = NULL;
+}
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
new file mode 100644 (file)
index 0000000..989980e
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * fs/f2fs/dir.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "node.h"
+#include "acl.h"
+
+static unsigned long dir_blocks(struct inode *inode)
+{
+       return ((unsigned long long) (i_size_read(inode) + PAGE_CACHE_SIZE - 1))
+                                                       >> PAGE_CACHE_SHIFT;
+}
+
+static unsigned int dir_buckets(unsigned int level)
+{
+       if (level < MAX_DIR_HASH_DEPTH / 2)
+               return 1 << level;
+       else
+               return 1 << ((MAX_DIR_HASH_DEPTH / 2) - 1);
+}
+
+static unsigned int bucket_blocks(unsigned int level)
+{
+       if (level < MAX_DIR_HASH_DEPTH / 2)
+               return 2;
+       else
+               return 4;
+}
+
+static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
+       [F2FS_FT_UNKNOWN]       = DT_UNKNOWN,
+       [F2FS_FT_REG_FILE]      = DT_REG,
+       [F2FS_FT_DIR]           = DT_DIR,
+       [F2FS_FT_CHRDEV]        = DT_CHR,
+       [F2FS_FT_BLKDEV]        = DT_BLK,
+       [F2FS_FT_FIFO]          = DT_FIFO,
+       [F2FS_FT_SOCK]          = DT_SOCK,
+       [F2FS_FT_SYMLINK]       = DT_LNK,
+};
+
+#define S_SHIFT 12
+static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
+       [S_IFREG >> S_SHIFT]    = F2FS_FT_REG_FILE,
+       [S_IFDIR >> S_SHIFT]    = F2FS_FT_DIR,
+       [S_IFCHR >> S_SHIFT]    = F2FS_FT_CHRDEV,
+       [S_IFBLK >> S_SHIFT]    = F2FS_FT_BLKDEV,
+       [S_IFIFO >> S_SHIFT]    = F2FS_FT_FIFO,
+       [S_IFSOCK >> S_SHIFT]   = F2FS_FT_SOCK,
+       [S_IFLNK >> S_SHIFT]    = F2FS_FT_SYMLINK,
+};
+
+static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
+{
+       mode_t mode = inode->i_mode;
+       de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
+}
+
+static unsigned long dir_block_index(unsigned int level, unsigned int idx)
+{
+       unsigned long i;
+       unsigned long bidx = 0;
+
+       for (i = 0; i < level; i++)
+               bidx += dir_buckets(i) * bucket_blocks(i);
+       bidx += idx * bucket_blocks(level);
+       return bidx;
+}
+
+static bool early_match_name(const char *name, size_t namelen,
+                       f2fs_hash_t namehash, struct f2fs_dir_entry *de)
+{
+       if (le16_to_cpu(de->name_len) != namelen)
+               return false;
+
+       if (de->hash_code != namehash)
+               return false;
+
+       return true;
+}
+
+static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
+                       const char *name, size_t namelen, int *max_slots,
+                       f2fs_hash_t namehash, struct page **res_page)
+{
+       struct f2fs_dir_entry *de;
+       unsigned long bit_pos, end_pos, next_pos;
+       struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
+       int slots;
+
+       bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                                       NR_DENTRY_IN_BLOCK, 0);
+       while (bit_pos < NR_DENTRY_IN_BLOCK) {
+               de = &dentry_blk->dentry[bit_pos];
+               slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+
+               if (early_match_name(name, namelen, namehash, de)) {
+                       if (!memcmp(dentry_blk->filename[bit_pos],
+                                                       name, namelen)) {
+                               *res_page = dentry_page;
+                               goto found;
+                       }
+               }
+               next_pos = bit_pos + slots;
+               bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                               NR_DENTRY_IN_BLOCK, next_pos);
+               if (bit_pos >= NR_DENTRY_IN_BLOCK)
+                       end_pos = NR_DENTRY_IN_BLOCK;
+               else
+                       end_pos = bit_pos;
+               if (*max_slots < end_pos - next_pos)
+                       *max_slots = end_pos - next_pos;
+       }
+
+       de = NULL;
+       kunmap(dentry_page);
+found:
+       return de;
+}
+
+static struct f2fs_dir_entry *find_in_level(struct inode *dir,
+               unsigned int level, const char *name, size_t namelen,
+                       f2fs_hash_t namehash, struct page **res_page)
+{
+       int s = GET_DENTRY_SLOTS(namelen);
+       unsigned int nbucket, nblock;
+       unsigned int bidx, end_block;
+       struct page *dentry_page;
+       struct f2fs_dir_entry *de = NULL;
+       bool room = false;
+       int max_slots = 0;
+
+       BUG_ON(level > MAX_DIR_HASH_DEPTH);
+
+       nbucket = dir_buckets(level);
+       nblock = bucket_blocks(level);
+
+       bidx = dir_block_index(level, le32_to_cpu(namehash) % nbucket);
+       end_block = bidx + nblock;
+
+       for (; bidx < end_block; bidx++) {
+               /* no need to allocate new dentry pages to all the indices */
+               dentry_page = find_data_page(dir, bidx);
+               if (IS_ERR(dentry_page)) {
+                       room = true;
+                       continue;
+               }
+
+               de = find_in_block(dentry_page, name, namelen,
+                                       &max_slots, namehash, res_page);
+               if (de)
+                       break;
+
+               if (max_slots >= s)
+                       room = true;
+               f2fs_put_page(dentry_page, 0);
+       }
+
+       if (!de && room && F2FS_I(dir)->chash != namehash) {
+               F2FS_I(dir)->chash = namehash;
+               F2FS_I(dir)->clevel = level;
+       }
+
+       return de;
+}
+
+/*
+ * Find an entry in the specified directory with the wanted name.
+ * It returns the page where the entry was found (as a parameter - res_page),
+ * and the entry itself. Page is returned mapped and unlocked.
+ * Entry is guaranteed to be valid.
+ */
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
+                       struct qstr *child, struct page **res_page)
+{
+       const char *name = child->name;
+       size_t namelen = child->len;
+       unsigned long npages = dir_blocks(dir);
+       struct f2fs_dir_entry *de = NULL;
+       f2fs_hash_t name_hash;
+       unsigned int max_depth;
+       unsigned int level;
+
+       if (npages == 0)
+               return NULL;
+
+       *res_page = NULL;
+
+       name_hash = f2fs_dentry_hash(name, namelen);
+       max_depth = F2FS_I(dir)->i_current_depth;
+
+       for (level = 0; level < max_depth; level++) {
+               de = find_in_level(dir, level, name,
+                               namelen, name_hash, res_page);
+               if (de)
+                       break;
+       }
+       if (!de && F2FS_I(dir)->chash != name_hash) {
+               F2FS_I(dir)->chash = name_hash;
+               F2FS_I(dir)->clevel = level - 1;
+       }
+       return de;
+}
+
+struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
+{
+       struct page *page = NULL;
+       struct f2fs_dir_entry *de = NULL;
+       struct f2fs_dentry_block *dentry_blk = NULL;
+
+       page = get_lock_data_page(dir, 0);
+       if (IS_ERR(page))
+               return NULL;
+
+       dentry_blk = kmap(page);
+       de = &dentry_blk->dentry[1];
+       *p = page;
+       unlock_page(page);
+       return de;
+}
+
+ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr)
+{
+       ino_t res = 0;
+       struct f2fs_dir_entry *de;
+       struct page *page;
+
+       de = f2fs_find_entry(dir, qstr, &page);
+       if (de) {
+               res = le32_to_cpu(de->ino);
+               kunmap(page);
+               f2fs_put_page(page, 0);
+       }
+
+       return res;
+}
+
+void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
+               struct page *page, struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+
+       mutex_lock_op(sbi, DENTRY_OPS);
+       lock_page(page);
+       wait_on_page_writeback(page);
+       de->ino = cpu_to_le32(inode->i_ino);
+       set_de_type(de, inode);
+       kunmap(page);
+       set_page_dirty(page);
+       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+       mark_inode_dirty(dir);
+
+       /* update parent inode number before releasing dentry page */
+       F2FS_I(inode)->i_pino = dir->i_ino;
+
+       f2fs_put_page(page, 1);
+       mutex_unlock_op(sbi, DENTRY_OPS);
+}
+
+void init_dent_inode(struct dentry *dentry, struct page *ipage)
+{
+       struct f2fs_node *rn;
+
+       if (IS_ERR(ipage))
+               return;
+
+       wait_on_page_writeback(ipage);
+
+       /* copy dentry info. to this inode page */
+       rn = (struct f2fs_node *)page_address(ipage);
+       rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
+       memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
+       set_page_dirty(ipage);
+}
+
+static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
+{
+       struct inode *dir = dentry->d_parent->d_inode;
+
+       if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
+               int err;
+               err = new_inode_page(inode, dentry);
+               if (err)
+                       return err;
+
+               if (S_ISDIR(inode->i_mode)) {
+                       err = f2fs_make_empty(inode, dir);
+                       if (err) {
+                               remove_inode_page(inode);
+                               return err;
+                       }
+               }
+
+               err = f2fs_init_acl(inode, dir);
+               if (err) {
+                       remove_inode_page(inode);
+                       return err;
+               }
+       } else {
+               struct page *ipage;
+               ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
+               if (IS_ERR(ipage))
+                       return PTR_ERR(ipage);
+               set_cold_node(inode, ipage);
+               init_dent_inode(dentry, ipage);
+               f2fs_put_page(ipage, 1);
+       }
+       if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
+               inc_nlink(inode);
+               f2fs_write_inode(inode, NULL);
+       }
+       return 0;
+}
+
+static void update_parent_metadata(struct inode *dir, struct inode *inode,
+                                               unsigned int current_depth)
+{
+       bool need_dir_update = false;
+
+       if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
+               if (S_ISDIR(inode->i_mode)) {
+                       inc_nlink(dir);
+                       need_dir_update = true;
+               }
+               clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
+       }
+       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+       if (F2FS_I(dir)->i_current_depth != current_depth) {
+               F2FS_I(dir)->i_current_depth = current_depth;
+               need_dir_update = true;
+       }
+
+       if (need_dir_update)
+               f2fs_write_inode(dir, NULL);
+       else
+               mark_inode_dirty(dir);
+
+       if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
+               clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+}
+
+static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
+{
+       int bit_start = 0;
+       int zero_start, zero_end;
+next:
+       zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
+                                               NR_DENTRY_IN_BLOCK,
+                                               bit_start);
+       if (zero_start >= NR_DENTRY_IN_BLOCK)
+               return NR_DENTRY_IN_BLOCK;
+
+       zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                                               NR_DENTRY_IN_BLOCK,
+                                               zero_start);
+       if (zero_end - zero_start >= slots)
+               return zero_start;
+
+       bit_start = zero_end + 1;
+
+       if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
+               return NR_DENTRY_IN_BLOCK;
+       goto next;
+}
+
+int f2fs_add_link(struct dentry *dentry, struct inode *inode)
+{
+       unsigned int bit_pos;
+       unsigned int level;
+       unsigned int current_depth;
+       unsigned long bidx, block;
+       f2fs_hash_t dentry_hash;
+       struct f2fs_dir_entry *de;
+       unsigned int nbucket, nblock;
+       struct inode *dir = dentry->d_parent->d_inode;
+       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       const char *name = dentry->d_name.name;
+       size_t namelen = dentry->d_name.len;
+       struct page *dentry_page = NULL;
+       struct f2fs_dentry_block *dentry_blk = NULL;
+       int slots = GET_DENTRY_SLOTS(namelen);
+       int err = 0;
+       int i;
+
+       dentry_hash = f2fs_dentry_hash(name, dentry->d_name.len);
+       level = 0;
+       current_depth = F2FS_I(dir)->i_current_depth;
+       if (F2FS_I(dir)->chash == dentry_hash) {
+               level = F2FS_I(dir)->clevel;
+               F2FS_I(dir)->chash = 0;
+       }
+
+start:
+       if (current_depth == MAX_DIR_HASH_DEPTH)
+               return -ENOSPC;
+
+       /* Increase the depth, if required */
+       if (level == current_depth)
+               ++current_depth;
+
+       nbucket = dir_buckets(level);
+       nblock = bucket_blocks(level);
+
+       bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket));
+
+       for (block = bidx; block <= (bidx + nblock - 1); block++) {
+               mutex_lock_op(sbi, DENTRY_OPS);
+               dentry_page = get_new_data_page(dir, block, true);
+               if (IS_ERR(dentry_page)) {
+                       mutex_unlock_op(sbi, DENTRY_OPS);
+                       return PTR_ERR(dentry_page);
+               }
+
+               dentry_blk = kmap(dentry_page);
+               bit_pos = room_for_filename(dentry_blk, slots);
+               if (bit_pos < NR_DENTRY_IN_BLOCK)
+                       goto add_dentry;
+
+               kunmap(dentry_page);
+               f2fs_put_page(dentry_page, 1);
+               mutex_unlock_op(sbi, DENTRY_OPS);
+       }
+
+       /* Move to next level to find the empty slot for new dentry */
+       ++level;
+       goto start;
+add_dentry:
+       err = init_inode_metadata(inode, dentry);
+       if (err)
+               goto fail;
+
+       wait_on_page_writeback(dentry_page);
+
+       de = &dentry_blk->dentry[bit_pos];
+       de->hash_code = dentry_hash;
+       de->name_len = cpu_to_le16(namelen);
+       memcpy(dentry_blk->filename[bit_pos], name, namelen);
+       de->ino = cpu_to_le32(inode->i_ino);
+       set_de_type(de, inode);
+       for (i = 0; i < slots; i++)
+               test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+       set_page_dirty(dentry_page);
+
+       update_parent_metadata(dir, inode, current_depth);
+
+       /* update parent inode number before releasing dentry page */
+       F2FS_I(inode)->i_pino = dir->i_ino;
+fail:
+       kunmap(dentry_page);
+       f2fs_put_page(dentry_page, 1);
+       mutex_unlock_op(sbi, DENTRY_OPS);
+       return err;
+}
+
+/*
+ * It only removes the dentry from the dentry page,corresponding name
+ * entry in name page does not need to be touched during deletion.
+ */
+void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
+                                               struct inode *inode)
+{
+       struct  f2fs_dentry_block *dentry_blk;
+       unsigned int bit_pos;
+       struct address_space *mapping = page->mapping;
+       struct inode *dir = mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
+       void *kaddr = page_address(page);
+       int i;
+
+       mutex_lock_op(sbi, DENTRY_OPS);
+
+       lock_page(page);
+       wait_on_page_writeback(page);
+
+       dentry_blk = (struct f2fs_dentry_block *)kaddr;
+       bit_pos = dentry - (struct f2fs_dir_entry *)dentry_blk->dentry;
+       for (i = 0; i < slots; i++)
+               test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+
+       /* Let's check and deallocate this dentry page */
+       bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                       NR_DENTRY_IN_BLOCK,
+                       0);
+       kunmap(page); /* kunmap - pair of f2fs_find_entry */
+       set_page_dirty(page);
+
+       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+
+       if (inode && S_ISDIR(inode->i_mode)) {
+               drop_nlink(dir);
+               f2fs_write_inode(dir, NULL);
+       } else {
+               mark_inode_dirty(dir);
+       }
+
+       if (inode) {
+               inode->i_ctime = CURRENT_TIME;
+               drop_nlink(inode);
+               if (S_ISDIR(inode->i_mode)) {
+                       drop_nlink(inode);
+                       i_size_write(inode, 0);
+               }
+               f2fs_write_inode(inode, NULL);
+               if (inode->i_nlink == 0)
+                       add_orphan_inode(sbi, inode->i_ino);
+       }
+
+       if (bit_pos == NR_DENTRY_IN_BLOCK) {
+               truncate_hole(dir, page->index, page->index + 1);
+               clear_page_dirty_for_io(page);
+               ClearPageUptodate(page);
+               dec_page_count(sbi, F2FS_DIRTY_DENTS);
+               inode_dec_dirty_dents(dir);
+       }
+       f2fs_put_page(page, 1);
+
+       mutex_unlock_op(sbi, DENTRY_OPS);
+}
+
+int f2fs_make_empty(struct inode *inode, struct inode *parent)
+{
+       struct page *dentry_page;
+       struct f2fs_dentry_block *dentry_blk;
+       struct f2fs_dir_entry *de;
+       void *kaddr;
+
+       dentry_page = get_new_data_page(inode, 0, true);
+       if (IS_ERR(dentry_page))
+               return PTR_ERR(dentry_page);
+
+       kaddr = kmap_atomic(dentry_page);
+       dentry_blk = (struct f2fs_dentry_block *)kaddr;
+
+       de = &dentry_blk->dentry[0];
+       de->name_len = cpu_to_le16(1);
+       de->hash_code = f2fs_dentry_hash(".", 1);
+       de->ino = cpu_to_le32(inode->i_ino);
+       memcpy(dentry_blk->filename[0], ".", 1);
+       set_de_type(de, inode);
+
+       de = &dentry_blk->dentry[1];
+       de->hash_code = f2fs_dentry_hash("..", 2);
+       de->name_len = cpu_to_le16(2);
+       de->ino = cpu_to_le32(parent->i_ino);
+       memcpy(dentry_blk->filename[1], "..", 2);
+       set_de_type(de, inode);
+
+       test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
+       test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
+       kunmap_atomic(kaddr);
+
+       set_page_dirty(dentry_page);
+       f2fs_put_page(dentry_page, 1);
+       return 0;
+}
+
+bool f2fs_empty_dir(struct inode *dir)
+{
+       unsigned long bidx;
+       struct page *dentry_page;
+       unsigned int bit_pos;
+       struct  f2fs_dentry_block *dentry_blk;
+       unsigned long nblock = dir_blocks(dir);
+
+       for (bidx = 0; bidx < nblock; bidx++) {
+               void *kaddr;
+               dentry_page = get_lock_data_page(dir, bidx);
+               if (IS_ERR(dentry_page)) {
+                       if (PTR_ERR(dentry_page) == -ENOENT)
+                               continue;
+                       else
+                               return false;
+               }
+
+               kaddr = kmap_atomic(dentry_page);
+               dentry_blk = (struct f2fs_dentry_block *)kaddr;
+               if (bidx == 0)
+                       bit_pos = 2;
+               else
+                       bit_pos = 0;
+               bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                                               NR_DENTRY_IN_BLOCK,
+                                               bit_pos);
+               kunmap_atomic(kaddr);
+
+               f2fs_put_page(dentry_page, 1);
+
+               if (bit_pos < NR_DENTRY_IN_BLOCK)
+                       return false;
+       }
+       return true;
+}
+
+static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+       unsigned long pos = file->f_pos;
+       struct inode *inode = file->f_dentry->d_inode;
+       unsigned long npages = dir_blocks(inode);
+       unsigned char *types = NULL;
+       unsigned int bit_pos = 0, start_bit_pos = 0;
+       int over = 0;
+       struct f2fs_dentry_block *dentry_blk = NULL;
+       struct f2fs_dir_entry *de = NULL;
+       struct page *dentry_page = NULL;
+       unsigned int n = 0;
+       unsigned char d_type = DT_UNKNOWN;
+       int slots;
+
+       types = f2fs_filetype_table;
+       bit_pos = (pos % NR_DENTRY_IN_BLOCK);
+       n = (pos / NR_DENTRY_IN_BLOCK);
+
+       for ( ; n < npages; n++) {
+               dentry_page = get_lock_data_page(inode, n);
+               if (IS_ERR(dentry_page))
+                       continue;
+
+               start_bit_pos = bit_pos;
+               dentry_blk = kmap(dentry_page);
+               while (bit_pos < NR_DENTRY_IN_BLOCK) {
+                       d_type = DT_UNKNOWN;
+                       bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+                                                       NR_DENTRY_IN_BLOCK,
+                                                       bit_pos);
+                       if (bit_pos >= NR_DENTRY_IN_BLOCK)
+                               break;
+
+                       de = &dentry_blk->dentry[bit_pos];
+                       if (types && de->file_type < F2FS_FT_MAX)
+                               d_type = types[de->file_type];
+
+                       over = filldir(dirent,
+                                       dentry_blk->filename[bit_pos],
+                                       le16_to_cpu(de->name_len),
+                                       (n * NR_DENTRY_IN_BLOCK) + bit_pos,
+                                       le32_to_cpu(de->ino), d_type);
+                       if (over) {
+                               file->f_pos += bit_pos - start_bit_pos;
+                               goto success;
+                       }
+                       slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+                       bit_pos += slots;
+               }
+               bit_pos = 0;
+               file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK;
+               kunmap(dentry_page);
+               f2fs_put_page(dentry_page, 1);
+               dentry_page = NULL;
+       }
+success:
+       if (dentry_page && !IS_ERR(dentry_page)) {
+               kunmap(dentry_page);
+               f2fs_put_page(dentry_page, 1);
+       }
+
+       return 0;
+}
+
+const struct file_operations f2fs_dir_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .readdir        = f2fs_readdir,
+       .fsync          = f2fs_sync_file,
+       .unlocked_ioctl = f2fs_ioctl,
+};
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
new file mode 100644 (file)
index 0000000..c8e2d75
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+ * fs/f2fs/f2fs.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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 _LINUX_F2FS_H
+#define _LINUX_F2FS_H
+
+#include <linux/types.h>
+#include <linux/page-flags.h>
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/magic.h>
+
+/*
+ * For mount options
+ */
+#define F2FS_MOUNT_BG_GC               0x00000001
+#define F2FS_MOUNT_DISABLE_ROLL_FORWARD        0x00000002
+#define F2FS_MOUNT_DISCARD             0x00000004
+#define F2FS_MOUNT_NOHEAP              0x00000008
+#define F2FS_MOUNT_XATTR_USER          0x00000010
+#define F2FS_MOUNT_POSIX_ACL           0x00000020
+#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY        0x00000040
+
+#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
+#define set_opt(sbi, option)   (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
+#define test_opt(sbi, option)  (sbi->mount_opt.opt & F2FS_MOUNT_##option)
+
+#define ver_after(a, b)        (typecheck(unsigned long long, a) &&            \
+               typecheck(unsigned long long, b) &&                     \
+               ((long long)((a) - (b)) > 0))
+
+typedef u64 block_t;
+typedef u32 nid_t;
+
+struct f2fs_mount_info {
+       unsigned int    opt;
+};
+
+static inline __u32 f2fs_crc32(void *buff, size_t len)
+{
+       return crc32_le(F2FS_SUPER_MAGIC, buff, len);
+}
+
+static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size)
+{
+       return f2fs_crc32(buff, buff_size) == blk_crc;
+}
+
+/*
+ * For checkpoint manager
+ */
+enum {
+       NAT_BITMAP,
+       SIT_BITMAP
+};
+
+/* for the list of orphan inodes */
+struct orphan_inode_entry {
+       struct list_head list;  /* list head */
+       nid_t ino;              /* inode number */
+};
+
+/* for the list of directory inodes */
+struct dir_inode_entry {
+       struct list_head list;  /* list head */
+       struct inode *inode;    /* vfs inode pointer */
+};
+
+/* for the list of fsync inodes, used only during recovery */
+struct fsync_inode_entry {
+       struct list_head list;  /* list head */
+       struct inode *inode;    /* vfs inode pointer */
+       block_t blkaddr;        /* block address locating the last inode */
+};
+
+#define nats_in_cursum(sum)            (le16_to_cpu(sum->n_nats))
+#define sits_in_cursum(sum)            (le16_to_cpu(sum->n_sits))
+
+#define nat_in_journal(sum, i)         (sum->nat_j.entries[i].ne)
+#define nid_in_journal(sum, i)         (sum->nat_j.entries[i].nid)
+#define sit_in_journal(sum, i)         (sum->sit_j.entries[i].se)
+#define segno_in_journal(sum, i)       (sum->sit_j.entries[i].segno)
+
+static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i)
+{
+       int before = nats_in_cursum(rs);
+       rs->n_nats = cpu_to_le16(before + i);
+       return before;
+}
+
+static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
+{
+       int before = sits_in_cursum(rs);
+       rs->n_sits = cpu_to_le16(before + i);
+       return before;
+}
+
+/*
+ * For INODE and NODE manager
+ */
+#define XATTR_NODE_OFFSET      (-1)    /*
+                                        * store xattrs to one node block per
+                                        * file keeping -1 as its node offset to
+                                        * distinguish from index node blocks.
+                                        */
+#define RDONLY_NODE            1       /*
+                                        * specify a read-only mode when getting
+                                        * a node block. 0 is read-write mode.
+                                        * used by get_dnode_of_data().
+                                        */
+#define F2FS_LINK_MAX          32000   /* maximum link count per file */
+
+/* for in-memory extent cache entry */
+struct extent_info {
+       rwlock_t ext_lock;      /* rwlock for consistency */
+       unsigned int fofs;      /* start offset in a file */
+       u32 blk_addr;           /* start block address of the extent */
+       unsigned int len;       /* lenth of the extent */
+};
+
+/*
+ * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
+ */
+#define FADVISE_COLD_BIT       0x01
+
+struct f2fs_inode_info {
+       struct inode vfs_inode;         /* serve a vfs inode */
+       unsigned long i_flags;          /* keep an inode flags for ioctl */
+       unsigned char i_advise;         /* use to give file attribute hints */
+       unsigned int i_current_depth;   /* use only in directory structure */
+       unsigned int i_pino;            /* parent inode number */
+       umode_t i_acl_mode;             /* keep file acl mode temporarily */
+
+       /* Use below internally in f2fs*/
+       unsigned long flags;            /* use to pass per-file flags */
+       unsigned long long data_version;/* lastes version of data for fsync */
+       atomic_t dirty_dents;           /* # of dirty dentry pages */
+       f2fs_hash_t chash;              /* hash value of given file name */
+       unsigned int clevel;            /* maximum level of given file name */
+       nid_t i_xattr_nid;              /* node id that contains xattrs */
+       struct extent_info ext;         /* in-memory extent cache entry */
+};
+
+static inline void get_extent_info(struct extent_info *ext,
+                                       struct f2fs_extent i_ext)
+{
+       write_lock(&ext->ext_lock);
+       ext->fofs = le32_to_cpu(i_ext.fofs);
+       ext->blk_addr = le32_to_cpu(i_ext.blk_addr);
+       ext->len = le32_to_cpu(i_ext.len);
+       write_unlock(&ext->ext_lock);
+}
+
+static inline void set_raw_extent(struct extent_info *ext,
+                                       struct f2fs_extent *i_ext)
+{
+       read_lock(&ext->ext_lock);
+       i_ext->fofs = cpu_to_le32(ext->fofs);
+       i_ext->blk_addr = cpu_to_le32(ext->blk_addr);
+       i_ext->len = cpu_to_le32(ext->len);
+       read_unlock(&ext->ext_lock);
+}
+
+struct f2fs_nm_info {
+       block_t nat_blkaddr;            /* base disk address of NAT */
+       nid_t max_nid;                  /* maximum possible node ids */
+       nid_t init_scan_nid;            /* the first nid to be scanned */
+       nid_t next_scan_nid;            /* the next nid to be scanned */
+
+       /* NAT cache management */
+       struct radix_tree_root nat_root;/* root of the nat entry cache */
+       rwlock_t nat_tree_lock;         /* protect nat_tree_lock */
+       unsigned int nat_cnt;           /* the # of cached nat entries */
+       struct list_head nat_entries;   /* cached nat entry list (clean) */
+       struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
+
+       /* free node ids management */
+       struct list_head free_nid_list; /* a list for free nids */
+       spinlock_t free_nid_list_lock;  /* protect free nid list */
+       unsigned int fcnt;              /* the number of free node id */
+       struct mutex build_lock;        /* lock for build free nids */
+
+       /* for checkpoint */
+       char *nat_bitmap;               /* NAT bitmap pointer */
+       int bitmap_size;                /* bitmap size */
+};
+
+/*
+ * this structure is used as one of function parameters.
+ * all the information are dedicated to a given direct node block determined
+ * by the data offset in a file.
+ */
+struct dnode_of_data {
+       struct inode *inode;            /* vfs inode pointer */
+       struct page *inode_page;        /* its inode page, NULL is possible */
+       struct page *node_page;         /* cached direct node page */
+       nid_t nid;                      /* node id of the direct node block */
+       unsigned int ofs_in_node;       /* data offset in the node page */
+       bool inode_page_locked;         /* inode page is locked or not */
+       block_t data_blkaddr;           /* block address of the node block */
+};
+
+static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
+               struct page *ipage, struct page *npage, nid_t nid)
+{
+       memset(dn, 0, sizeof(*dn));
+       dn->inode = inode;
+       dn->inode_page = ipage;
+       dn->node_page = npage;
+       dn->nid = nid;
+}
+
+/*
+ * For SIT manager
+ *
+ * By default, there are 6 active log areas across the whole main area.
+ * When considering hot and cold data separation to reduce cleaning overhead,
+ * we split 3 for data logs and 3 for node logs as hot, warm, and cold types,
+ * respectively.
+ * In the current design, you should not change the numbers intentionally.
+ * Instead, as a mount option such as active_logs=x, you can use 2, 4, and 6
+ * logs individually according to the underlying devices. (default: 6)
+ * Just in case, on-disk layout covers maximum 16 logs that consist of 8 for
+ * data and 8 for node logs.
+ */
+#define        NR_CURSEG_DATA_TYPE     (3)
+#define NR_CURSEG_NODE_TYPE    (3)
+#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
+
+enum {
+       CURSEG_HOT_DATA = 0,    /* directory entry blocks */
+       CURSEG_WARM_DATA,       /* data blocks */
+       CURSEG_COLD_DATA,       /* multimedia or GCed data blocks */
+       CURSEG_HOT_NODE,        /* direct node blocks of directory files */
+       CURSEG_WARM_NODE,       /* direct node blocks of normal files */
+       CURSEG_COLD_NODE,       /* indirect node blocks */
+       NO_CHECK_TYPE
+};
+
+struct f2fs_sm_info {
+       struct sit_info *sit_info;              /* whole segment information */
+       struct free_segmap_info *free_info;     /* free segment information */
+       struct dirty_seglist_info *dirty_info;  /* dirty segment information */
+       struct curseg_info *curseg_array;       /* active segment information */
+
+       struct list_head wblist_head;   /* list of under-writeback pages */
+       spinlock_t wblist_lock;         /* lock for checkpoint */
+
+       block_t seg0_blkaddr;           /* block address of 0'th segment */
+       block_t main_blkaddr;           /* start block address of main area */
+       block_t ssa_blkaddr;            /* start block address of SSA area */
+
+       unsigned int segment_count;     /* total # of segments */
+       unsigned int main_segments;     /* # of segments in main area */
+       unsigned int reserved_segments; /* # of reserved segments */
+       unsigned int ovp_segments;      /* # of overprovision segments */
+};
+
+/*
+ * For directory operation
+ */
+#define        NODE_DIR1_BLOCK         (ADDRS_PER_INODE + 1)
+#define        NODE_DIR2_BLOCK         (ADDRS_PER_INODE + 2)
+#define        NODE_IND1_BLOCK         (ADDRS_PER_INODE + 3)
+#define        NODE_IND2_BLOCK         (ADDRS_PER_INODE + 4)
+#define        NODE_DIND_BLOCK         (ADDRS_PER_INODE + 5)
+
+/*
+ * For superblock
+ */
+/*
+ * COUNT_TYPE for monitoring
+ *
+ * f2fs monitors the number of several block types such as on-writeback,
+ * dirty dentry blocks, dirty node blocks, and dirty meta blocks.
+ */
+enum count_type {
+       F2FS_WRITEBACK,
+       F2FS_DIRTY_DENTS,
+       F2FS_DIRTY_NODES,
+       F2FS_DIRTY_META,
+       NR_COUNT_TYPE,
+};
+
+/*
+ * FS_LOCK nesting subclasses for the lock validator:
+ *
+ * The locking order between these classes is
+ * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW
+ *    -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
+ */
+enum lock_type {
+       RENAME,         /* for renaming operations */
+       DENTRY_OPS,     /* for directory operations */
+       DATA_WRITE,     /* for data write */
+       DATA_NEW,       /* for data allocation */
+       DATA_TRUNC,     /* for data truncate */
+       NODE_NEW,       /* for node allocation */
+       NODE_TRUNC,     /* for node truncate */
+       NODE_WRITE,     /* for node write */
+       NR_LOCK_TYPE,
+};
+
+/*
+ * The below are the page types of bios used in submti_bio().
+ * The available types are:
+ * DATA                        User data pages. It operates as async mode.
+ * NODE                        Node pages. It operates as async mode.
+ * META                        FS metadata pages such as SIT, NAT, CP.
+ * NR_PAGE_TYPE                The number of page types.
+ * META_FLUSH          Make sure the previous pages are written
+ *                     with waiting the bio's completion
+ * ...                 Only can be used with META.
+ */
+enum page_type {
+       DATA,
+       NODE,
+       META,
+       NR_PAGE_TYPE,
+       META_FLUSH,
+};
+
+struct f2fs_sb_info {
+       struct super_block *sb;                 /* pointer to VFS super block */
+       struct buffer_head *raw_super_buf;      /* buffer head of raw sb */
+       struct f2fs_super_block *raw_super;     /* raw super block pointer */
+       int s_dirty;                            /* dirty flag for checkpoint */
+
+       /* for node-related operations */
+       struct f2fs_nm_info *nm_info;           /* node manager */
+       struct inode *node_inode;               /* cache node blocks */
+
+       /* for segment-related operations */
+       struct f2fs_sm_info *sm_info;           /* segment manager */
+       struct bio *bio[NR_PAGE_TYPE];          /* bios to merge */
+       sector_t last_block_in_bio[NR_PAGE_TYPE];       /* last block number */
+       struct rw_semaphore bio_sem;            /* IO semaphore */
+
+       /* for checkpoint */
+       struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
+       struct inode *meta_inode;               /* cache meta blocks */
+       struct mutex cp_mutex;                  /* for checkpoint procedure */
+       struct mutex fs_lock[NR_LOCK_TYPE];     /* for blocking FS operations */
+       struct mutex write_inode;               /* mutex for write inode */
+       struct mutex writepages;                /* mutex for writepages() */
+       int por_doing;                          /* recovery is doing or not */
+
+       /* for orphan inode management */
+       struct list_head orphan_inode_list;     /* orphan inode list */
+       struct mutex orphan_inode_mutex;        /* for orphan inode list */
+       unsigned int n_orphans;                 /* # of orphan inodes */
+
+       /* for directory inode management */
+       struct list_head dir_inode_list;        /* dir inode list */
+       spinlock_t dir_inode_lock;              /* for dir inode list lock */
+       unsigned int n_dirty_dirs;              /* # of dir inodes */
+
+       /* basic file system units */
+       unsigned int log_sectors_per_block;     /* log2 sectors per block */
+       unsigned int log_blocksize;             /* log2 block size */
+       unsigned int blocksize;                 /* block size */
+       unsigned int root_ino_num;              /* root inode number*/
+       unsigned int node_ino_num;              /* node inode number*/
+       unsigned int meta_ino_num;              /* meta inode number*/
+       unsigned int log_blocks_per_seg;        /* log2 blocks per segment */
+       unsigned int blocks_per_seg;            /* blocks per segment */
+       unsigned int segs_per_sec;              /* segments per section */
+       unsigned int secs_per_zone;             /* sections per zone */
+       unsigned int total_sections;            /* total section count */
+       unsigned int total_node_count;          /* total node block count */
+       unsigned int total_valid_node_count;    /* valid node block count */
+       unsigned int total_valid_inode_count;   /* valid inode count */
+       int active_logs;                        /* # of active logs */
+
+       block_t user_block_count;               /* # of user blocks */
+       block_t total_valid_block_count;        /* # of valid blocks */
+       block_t alloc_valid_block_count;        /* # of allocated blocks */
+       block_t last_valid_block_count;         /* for recovery */
+       u32 s_next_generation;                  /* for NFS support */
+       atomic_t nr_pages[NR_COUNT_TYPE];       /* # of pages, see count_type */
+
+       struct f2fs_mount_info mount_opt;       /* mount options */
+
+       /* for cleaning operations */
+       struct mutex gc_mutex;                  /* mutex for GC */
+       struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
+
+       /*
+        * for stat information.
+        * one is for the LFS mode, and the other is for the SSR mode.
+        */
+       struct f2fs_stat_info *stat_info;       /* FS status information */
+       unsigned int segment_count[2];          /* # of allocated segments */
+       unsigned int block_count[2];            /* # of allocated blocks */
+       unsigned int last_victim[2];            /* last victim segment # */
+       int total_hit_ext, read_hit_ext;        /* extent cache hit ratio */
+       int bg_gc;                              /* background gc calls */
+       spinlock_t stat_lock;                   /* lock for stat operations */
+};
+
+/*
+ * Inline functions
+ */
+static inline struct f2fs_inode_info *F2FS_I(struct inode *inode)
+{
+       return container_of(inode, struct f2fs_inode_info, vfs_inode);
+}
+
+static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
+static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
+{
+       return (struct f2fs_super_block *)(sbi->raw_super);
+}
+
+static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
+{
+       return (struct f2fs_checkpoint *)(sbi->ckpt);
+}
+
+static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
+{
+       return (struct f2fs_nm_info *)(sbi->nm_info);
+}
+
+static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi)
+{
+       return (struct f2fs_sm_info *)(sbi->sm_info);
+}
+
+static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
+{
+       return (struct sit_info *)(SM_I(sbi)->sit_info);
+}
+
+static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi)
+{
+       return (struct free_segmap_info *)(SM_I(sbi)->free_info);
+}
+
+static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
+{
+       return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
+}
+
+static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
+{
+       sbi->s_dirty = 1;
+}
+
+static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi)
+{
+       sbi->s_dirty = 0;
+}
+
+static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+       unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+       return ckpt_flags & f;
+}
+
+static inline void set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+       unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+       ckpt_flags |= f;
+       cp->ckpt_flags = cpu_to_le32(ckpt_flags);
+}
+
+static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+       unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+       ckpt_flags &= (~f);
+       cp->ckpt_flags = cpu_to_le32(ckpt_flags);
+}
+
+static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+{
+       mutex_lock_nested(&sbi->fs_lock[t], t);
+}
+
+static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+{
+       mutex_unlock(&sbi->fs_lock[t]);
+}
+
+/*
+ * Check whether the given nid is within node id range.
+ */
+static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       BUG_ON((nid >= NM_I(sbi)->max_nid));
+}
+
+#define F2FS_DEFAULT_ALLOCATED_BLOCKS  1
+
+/*
+ * Check whether the inode has blocks or not
+ */
+static inline int F2FS_HAS_BLOCKS(struct inode *inode)
+{
+       if (F2FS_I(inode)->i_xattr_nid)
+               return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
+       else
+               return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
+}
+
+static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
+                                struct inode *inode, blkcnt_t count)
+{
+       block_t valid_block_count;
+
+       spin_lock(&sbi->stat_lock);
+       valid_block_count =
+               sbi->total_valid_block_count + (block_t)count;
+       if (valid_block_count > sbi->user_block_count) {
+               spin_unlock(&sbi->stat_lock);
+               return false;
+       }
+       inode->i_blocks += count;
+       sbi->total_valid_block_count = valid_block_count;
+       sbi->alloc_valid_block_count += (block_t)count;
+       spin_unlock(&sbi->stat_lock);
+       return true;
+}
+
+static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
+                                               struct inode *inode,
+                                               blkcnt_t count)
+{
+       spin_lock(&sbi->stat_lock);
+       BUG_ON(sbi->total_valid_block_count < (block_t) count);
+       BUG_ON(inode->i_blocks < count);
+       inode->i_blocks -= count;
+       sbi->total_valid_block_count -= (block_t)count;
+       spin_unlock(&sbi->stat_lock);
+       return 0;
+}
+
+static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
+{
+       atomic_inc(&sbi->nr_pages[count_type]);
+       F2FS_SET_SB_DIRT(sbi);
+}
+
+static inline void inode_inc_dirty_dents(struct inode *inode)
+{
+       atomic_inc(&F2FS_I(inode)->dirty_dents);
+}
+
+static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
+{
+       atomic_dec(&sbi->nr_pages[count_type]);
+}
+
+static inline void inode_dec_dirty_dents(struct inode *inode)
+{
+       atomic_dec(&F2FS_I(inode)->dirty_dents);
+}
+
+static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
+{
+       return atomic_read(&sbi->nr_pages[count_type]);
+}
+
+static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
+{
+       block_t ret;
+       spin_lock(&sbi->stat_lock);
+       ret = sbi->total_valid_block_count;
+       spin_unlock(&sbi->stat_lock);
+       return ret;
+}
+
+static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+
+       /* return NAT or SIT bitmap */
+       if (flag == NAT_BITMAP)
+               return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
+       else if (flag == SIT_BITMAP)
+               return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
+
+       return 0;
+}
+
+static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       int offset = (flag == NAT_BITMAP) ?
+                       le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
+       return &ckpt->sit_nat_version_bitmap + offset;
+}
+
+static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
+{
+       block_t start_addr;
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);
+
+       start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
+
+       /*
+        * odd numbered checkpoint should at cp segment 0
+        * and even segent must be at cp segment 1
+        */
+       if (!(ckpt_version & 1))
+               start_addr += sbi->blocks_per_seg;
+
+       return start_addr;
+}
+
+static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
+{
+       return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
+                                               struct inode *inode,
+                                               unsigned int count)
+{
+       block_t valid_block_count;
+       unsigned int valid_node_count;
+
+       spin_lock(&sbi->stat_lock);
+
+       valid_block_count = sbi->total_valid_block_count + (block_t)count;
+       sbi->alloc_valid_block_count += (block_t)count;
+       valid_node_count = sbi->total_valid_node_count + count;
+
+       if (valid_block_count > sbi->user_block_count) {
+               spin_unlock(&sbi->stat_lock);
+               return false;
+       }
+
+       if (valid_node_count > sbi->total_node_count) {
+               spin_unlock(&sbi->stat_lock);
+               return false;
+       }
+
+       if (inode)
+               inode->i_blocks += count;
+       sbi->total_valid_node_count = valid_node_count;
+       sbi->total_valid_block_count = valid_block_count;
+       spin_unlock(&sbi->stat_lock);
+
+       return true;
+}
+
+static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
+                                               struct inode *inode,
+                                               unsigned int count)
+{
+       spin_lock(&sbi->stat_lock);
+
+       BUG_ON(sbi->total_valid_block_count < count);
+       BUG_ON(sbi->total_valid_node_count < count);
+       BUG_ON(inode->i_blocks < count);
+
+       inode->i_blocks -= count;
+       sbi->total_valid_node_count -= count;
+       sbi->total_valid_block_count -= (block_t)count;
+
+       spin_unlock(&sbi->stat_lock);
+}
+
+static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
+{
+       unsigned int ret;
+       spin_lock(&sbi->stat_lock);
+       ret = sbi->total_valid_node_count;
+       spin_unlock(&sbi->stat_lock);
+       return ret;
+}
+
+static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
+{
+       spin_lock(&sbi->stat_lock);
+       BUG_ON(sbi->total_valid_inode_count == sbi->total_node_count);
+       sbi->total_valid_inode_count++;
+       spin_unlock(&sbi->stat_lock);
+}
+
+static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
+{
+       spin_lock(&sbi->stat_lock);
+       BUG_ON(!sbi->total_valid_inode_count);
+       sbi->total_valid_inode_count--;
+       spin_unlock(&sbi->stat_lock);
+       return 0;
+}
+
+static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
+{
+       unsigned int ret;
+       spin_lock(&sbi->stat_lock);
+       ret = sbi->total_valid_inode_count;
+       spin_unlock(&sbi->stat_lock);
+       return ret;
+}
+
+static inline void f2fs_put_page(struct page *page, int unlock)
+{
+       if (!page || IS_ERR(page))
+               return;
+
+       if (unlock) {
+               BUG_ON(!PageLocked(page));
+               unlock_page(page);
+       }
+       page_cache_release(page);
+}
+
+static inline void f2fs_put_dnode(struct dnode_of_data *dn)
+{
+       if (dn->node_page)
+               f2fs_put_page(dn->node_page, 1);
+       if (dn->inode_page && dn->node_page != dn->inode_page)
+               f2fs_put_page(dn->inode_page, 0);
+       dn->node_page = NULL;
+       dn->inode_page = NULL;
+}
+
+static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
+                                       size_t size, void (*ctor)(void *))
+{
+       return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor);
+}
+
+#define RAW_IS_INODE(p)        ((p)->footer.nid == (p)->footer.ino)
+
+static inline bool IS_INODE(struct page *page)
+{
+       struct f2fs_node *p = (struct f2fs_node *)page_address(page);
+       return RAW_IS_INODE(p);
+}
+
+static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
+{
+       return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
+}
+
+static inline block_t datablock_addr(struct page *node_page,
+               unsigned int offset)
+{
+       struct f2fs_node *raw_node;
+       __le32 *addr_array;
+       raw_node = (struct f2fs_node *)page_address(node_page);
+       addr_array = blkaddr_in_node(raw_node);
+       return le32_to_cpu(addr_array[offset]);
+}
+
+static inline int f2fs_test_bit(unsigned int nr, char *addr)
+{
+       int mask;
+
+       addr += (nr >> 3);
+       mask = 1 << (7 - (nr & 0x07));
+       return mask & *addr;
+}
+
+static inline int f2fs_set_bit(unsigned int nr, char *addr)
+{
+       int mask;
+       int ret;
+
+       addr += (nr >> 3);
+       mask = 1 << (7 - (nr & 0x07));
+       ret = mask & *addr;
+       *addr |= mask;
+       return ret;
+}
+
+static inline int f2fs_clear_bit(unsigned int nr, char *addr)
+{
+       int mask;
+       int ret;
+
+       addr += (nr >> 3);
+       mask = 1 << (7 - (nr & 0x07));
+       ret = mask & *addr;
+       *addr &= ~mask;
+       return ret;
+}
+
+/* used for f2fs_inode_info->flags */
+enum {
+       FI_NEW_INODE,           /* indicate newly allocated inode */
+       FI_NEED_CP,             /* need to do checkpoint during fsync */
+       FI_INC_LINK,            /* need to increment i_nlink */
+       FI_ACL_MODE,            /* indicate acl mode */
+       FI_NO_ALLOC,            /* should not allocate any blocks */
+};
+
+static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+       set_bit(flag, &fi->flags);
+}
+
+static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
+{
+       return test_bit(flag, &fi->flags);
+}
+
+static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+       clear_bit(flag, &fi->flags);
+}
+
+static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
+{
+       fi->i_acl_mode = mode;
+       set_inode_flag(fi, FI_ACL_MODE);
+}
+
+static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+       if (is_inode_flag_set(fi, FI_ACL_MODE)) {
+               clear_inode_flag(fi, FI_ACL_MODE);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * file.c
+ */
+int f2fs_sync_file(struct file *, loff_t, loff_t, int);
+void truncate_data_blocks(struct dnode_of_data *);
+void f2fs_truncate(struct inode *);
+int f2fs_setattr(struct dentry *, struct iattr *);
+int truncate_hole(struct inode *, pgoff_t, pgoff_t);
+long f2fs_ioctl(struct file *, unsigned int, unsigned long);
+
+/*
+ * inode.c
+ */
+void f2fs_set_inode_flags(struct inode *);
+struct inode *f2fs_iget_nowait(struct super_block *, unsigned long);
+struct inode *f2fs_iget(struct super_block *, unsigned long);
+void update_inode(struct inode *, struct page *);
+int f2fs_write_inode(struct inode *, struct writeback_control *);
+void f2fs_evict_inode(struct inode *);
+
+/*
+ * namei.c
+ */
+struct dentry *f2fs_get_parent(struct dentry *child);
+
+/*
+ * dir.c
+ */
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
+                                                       struct page **);
+struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
+ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
+void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
+                               struct page *, struct inode *);
+void init_dent_inode(struct dentry *, struct page *);
+int f2fs_add_link(struct dentry *, struct inode *);
+void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
+int f2fs_make_empty(struct inode *, struct inode *);
+bool f2fs_empty_dir(struct inode *);
+
+/*
+ * super.c
+ */
+int f2fs_sync_fs(struct super_block *, int);
+extern __printf(3, 4)
+void f2fs_msg(struct super_block *, const char *, const char *, ...);
+
+/*
+ * hash.c
+ */
+f2fs_hash_t f2fs_dentry_hash(const char *, size_t);
+
+/*
+ * node.c
+ */
+struct dnode_of_data;
+struct node_info;
+
+int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
+void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
+int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
+int truncate_inode_blocks(struct inode *, pgoff_t);
+int remove_inode_page(struct inode *);
+int new_inode_page(struct inode *, struct dentry *);
+struct page *new_node_page(struct dnode_of_data *, unsigned int);
+void ra_node_page(struct f2fs_sb_info *, nid_t);
+struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
+struct page *get_node_page_ra(struct page *, int);
+void sync_inode_page(struct dnode_of_data *);
+int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
+bool alloc_nid(struct f2fs_sb_info *, nid_t *);
+void alloc_nid_done(struct f2fs_sb_info *, nid_t);
+void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
+void recover_node_page(struct f2fs_sb_info *, struct page *,
+               struct f2fs_summary *, struct node_info *, block_t);
+int recover_inode_page(struct f2fs_sb_info *, struct page *);
+int restore_node_summary(struct f2fs_sb_info *, unsigned int,
+                               struct f2fs_summary_block *);
+void flush_nat_entries(struct f2fs_sb_info *);
+int build_node_manager(struct f2fs_sb_info *);
+void destroy_node_manager(struct f2fs_sb_info *);
+int __init create_node_manager_caches(void);
+void destroy_node_manager_caches(void);
+
+/*
+ * segment.c
+ */
+void f2fs_balance_fs(struct f2fs_sb_info *);
+void invalidate_blocks(struct f2fs_sb_info *, block_t);
+void locate_dirty_segment(struct f2fs_sb_info *, unsigned int);
+void clear_prefree_segments(struct f2fs_sb_info *);
+int npages_for_summary_flush(struct f2fs_sb_info *);
+void allocate_new_segments(struct f2fs_sb_info *);
+struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
+struct bio *f2fs_bio_alloc(struct block_device *, int);
+void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
+int write_meta_page(struct f2fs_sb_info *, struct page *,
+                                       struct writeback_control *);
+void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
+                                       block_t, block_t *);
+void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
+                                       block_t, block_t *);
+void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
+void recover_data_page(struct f2fs_sb_info *, struct page *,
+                               struct f2fs_summary *, block_t, block_t);
+void rewrite_node_page(struct f2fs_sb_info *, struct page *,
+                               struct f2fs_summary *, block_t, block_t);
+void write_data_summaries(struct f2fs_sb_info *, block_t);
+void write_node_summaries(struct f2fs_sb_info *, block_t);
+int lookup_journal_in_cursum(struct f2fs_summary_block *,
+                                       int, unsigned int, int);
+void flush_sit_entries(struct f2fs_sb_info *);
+int build_segment_manager(struct f2fs_sb_info *);
+void reset_victim_segmap(struct f2fs_sb_info *);
+void destroy_segment_manager(struct f2fs_sb_info *);
+
+/*
+ * checkpoint.c
+ */
+struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
+struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
+long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
+int check_orphan_space(struct f2fs_sb_info *);
+void add_orphan_inode(struct f2fs_sb_info *, nid_t);
+void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
+int recover_orphan_inodes(struct f2fs_sb_info *);
+int get_valid_checkpoint(struct f2fs_sb_info *);
+void set_dirty_dir_page(struct inode *, struct page *);
+void remove_dirty_dir_inode(struct inode *);
+void sync_dirty_dir_inodes(struct f2fs_sb_info *);
+void block_operations(struct f2fs_sb_info *);
+void write_checkpoint(struct f2fs_sb_info *, bool, bool);
+void init_orphan_info(struct f2fs_sb_info *);
+int __init create_checkpoint_caches(void);
+void destroy_checkpoint_caches(void);
+
+/*
+ * data.c
+ */
+int reserve_new_block(struct dnode_of_data *);
+void update_extent_cache(block_t, struct dnode_of_data *);
+struct page *find_data_page(struct inode *, pgoff_t);
+struct page *get_lock_data_page(struct inode *, pgoff_t);
+struct page *get_new_data_page(struct inode *, pgoff_t, bool);
+int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
+int do_write_data_page(struct page *);
+
+/*
+ * gc.c
+ */
+int start_gc_thread(struct f2fs_sb_info *);
+void stop_gc_thread(struct f2fs_sb_info *);
+block_t start_bidx_of_node(unsigned int);
+int f2fs_gc(struct f2fs_sb_info *);
+void build_gc_manager(struct f2fs_sb_info *);
+int __init create_gc_caches(void);
+void destroy_gc_caches(void);
+
+/*
+ * recovery.c
+ */
+void recover_fsync_data(struct f2fs_sb_info *);
+bool space_for_roll_forward(struct f2fs_sb_info *);
+
+/*
+ * debug.c
+ */
+#ifdef CONFIG_F2FS_STAT_FS
+struct f2fs_stat_info {
+       struct list_head stat_list;
+       struct f2fs_sb_info *sbi;
+       struct mutex stat_lock;
+       int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs;
+       int main_area_segs, main_area_sections, main_area_zones;
+       int hit_ext, total_ext;
+       int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
+       int nats, sits, fnids;
+       int total_count, utilization;
+       int bg_gc;
+       unsigned int valid_count, valid_node_count, valid_inode_count;
+       unsigned int bimodal, avg_vblocks;
+       int util_free, util_valid, util_invalid;
+       int rsvd_segs, overp_segs;
+       int dirty_count, node_pages, meta_pages;
+       int prefree_count, call_count;
+       int tot_segs, node_segs, data_segs, free_segs, free_secs;
+       int tot_blks, data_blks, node_blks;
+       int curseg[NR_CURSEG_TYPE];
+       int cursec[NR_CURSEG_TYPE];
+       int curzone[NR_CURSEG_TYPE];
+
+       unsigned int segment_count[2];
+       unsigned int block_count[2];
+       unsigned base_mem, cache_mem;
+};
+
+#define stat_inc_call_count(si)        ((si)->call_count++)
+
+#define stat_inc_seg_count(sbi, type)                                  \
+       do {                                                            \
+               struct f2fs_stat_info *si = sbi->stat_info;             \
+               (si)->tot_segs++;                                       \
+               if (type == SUM_TYPE_DATA)                              \
+                       si->data_segs++;                                \
+               else                                                    \
+                       si->node_segs++;                                \
+       } while (0)
+
+#define stat_inc_tot_blk_count(si, blks)                               \
+       (si->tot_blks += (blks))
+
+#define stat_inc_data_blk_count(sbi, blks)                             \
+       do {                                                            \
+               struct f2fs_stat_info *si = sbi->stat_info;             \
+               stat_inc_tot_blk_count(si, blks);                       \
+               si->data_blks += (blks);                                \
+       } while (0)
+
+#define stat_inc_node_blk_count(sbi, blks)                             \
+       do {                                                            \
+               struct f2fs_stat_info *si = sbi->stat_info;             \
+               stat_inc_tot_blk_count(si, blks);                       \
+               si->node_blks += (blks);                                \
+       } while (0)
+
+int f2fs_build_stats(struct f2fs_sb_info *);
+void f2fs_destroy_stats(struct f2fs_sb_info *);
+void __init f2fs_create_root_stats(void);
+void f2fs_destroy_root_stats(void);
+#else
+#define stat_inc_call_count(si)
+#define stat_inc_seg_count(si, type)
+#define stat_inc_tot_blk_count(si, blks)
+#define stat_inc_data_blk_count(si, blks)
+#define stat_inc_node_blk_count(sbi, blks)
+
+static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
+static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
+static inline void __init f2fs_create_root_stats(void) { }
+static inline void f2fs_destroy_root_stats(void) { }
+#endif
+
+extern const struct file_operations f2fs_dir_operations;
+extern const struct file_operations f2fs_file_operations;
+extern const struct inode_operations f2fs_file_inode_operations;
+extern const struct address_space_operations f2fs_dblock_aops;
+extern const struct address_space_operations f2fs_node_aops;
+extern const struct address_space_operations f2fs_meta_aops;
+extern const struct inode_operations f2fs_dir_inode_operations;
+extern const struct inode_operations f2fs_symlink_inode_operations;
+extern const struct inode_operations f2fs_special_inode_operations;
+#endif
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
new file mode 100644 (file)
index 0000000..3191b52
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * fs/f2fs/file.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/stat.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+#include <linux/falloc.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/mount.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "xattr.h"
+#include "acl.h"
+
+static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
+                                               struct vm_fault *vmf)
+{
+       struct page *page = vmf->page;
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       block_t old_blk_addr;
+       struct dnode_of_data dn;
+       int err;
+
+       f2fs_balance_fs(sbi);
+
+       sb_start_pagefault(inode->i_sb);
+
+       mutex_lock_op(sbi, DATA_NEW);
+
+       /* block allocation */
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, page->index, 0);
+       if (err) {
+               mutex_unlock_op(sbi, DATA_NEW);
+               goto out;
+       }
+
+       old_blk_addr = dn.data_blkaddr;
+
+       if (old_blk_addr == NULL_ADDR) {
+               err = reserve_new_block(&dn);
+               if (err) {
+                       f2fs_put_dnode(&dn);
+                       mutex_unlock_op(sbi, DATA_NEW);
+                       goto out;
+               }
+       }
+       f2fs_put_dnode(&dn);
+
+       mutex_unlock_op(sbi, DATA_NEW);
+
+       lock_page(page);
+       if (page->mapping != inode->i_mapping ||
+                       page_offset(page) >= i_size_read(inode) ||
+                       !PageUptodate(page)) {
+               unlock_page(page);
+               err = -EFAULT;
+               goto out;
+       }
+
+       /*
+        * check to see if the page is mapped already (no holes)
+        */
+       if (PageMappedToDisk(page))
+               goto out;
+
+       /* fill the page */
+       wait_on_page_writeback(page);
+
+       /* page is wholly or partially inside EOF */
+       if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) {
+               unsigned offset;
+               offset = i_size_read(inode) & ~PAGE_CACHE_MASK;
+               zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+       }
+       set_page_dirty(page);
+       SetPageUptodate(page);
+
+       file_update_time(vma->vm_file);
+out:
+       sb_end_pagefault(inode->i_sb);
+       return block_page_mkwrite_return(err);
+}
+
+static const struct vm_operations_struct f2fs_file_vm_ops = {
+       .fault          = filemap_fault,
+       .page_mkwrite   = f2fs_vm_page_mkwrite,
+       .remap_pages    = generic_file_remap_pages,
+};
+
+static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
+{
+       struct dentry *dentry;
+       nid_t pino;
+
+       inode = igrab(inode);
+       dentry = d_find_any_alias(inode);
+       if (!dentry) {
+               iput(inode);
+               return 0;
+       }
+       pino = dentry->d_parent->d_inode->i_ino;
+       dput(dentry);
+       iput(inode);
+       return !is_checkpointed_node(sbi, pino);
+}
+
+int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+{
+       struct inode *inode = file->f_mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       unsigned long long cur_version;
+       int ret = 0;
+       bool need_cp = false;
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = LONG_MAX,
+               .for_reclaim = 0,
+       };
+
+       if (inode->i_sb->s_flags & MS_RDONLY)
+               return 0;
+
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+
+       /* guarantee free sections for fsync */
+       f2fs_balance_fs(sbi);
+
+       mutex_lock(&inode->i_mutex);
+
+       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+               goto out;
+
+       mutex_lock(&sbi->cp_mutex);
+       cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
+       mutex_unlock(&sbi->cp_mutex);
+
+       if (F2FS_I(inode)->data_version != cur_version &&
+                                       !(inode->i_state & I_DIRTY))
+               goto out;
+       F2FS_I(inode)->data_version--;
+
+       if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
+               need_cp = true;
+       if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP))
+               need_cp = true;
+       if (!space_for_roll_forward(sbi))
+               need_cp = true;
+       if (need_to_sync_dir(sbi, inode))
+               need_cp = true;
+
+       if (need_cp) {
+               /* all the dirty node pages should be flushed for POR */
+               ret = f2fs_sync_fs(inode->i_sb, 1);
+               clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
+       } else {
+               /* if there is no written node page, write its inode page */
+               while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {
+                       ret = f2fs_write_inode(inode, NULL);
+                       if (ret)
+                               goto out;
+               }
+               filemap_fdatawait_range(sbi->node_inode->i_mapping,
+                                                       0, LONG_MAX);
+       }
+out:
+       mutex_unlock(&inode->i_mutex);
+       return ret;
+}
+
+static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       file_accessed(file);
+       vma->vm_ops = &f2fs_file_vm_ops;
+       return 0;
+}
+
+static int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
+{
+       int nr_free = 0, ofs = dn->ofs_in_node;
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct f2fs_node *raw_node;
+       __le32 *addr;
+
+       raw_node = page_address(dn->node_page);
+       addr = blkaddr_in_node(raw_node) + ofs;
+
+       for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
+               block_t blkaddr = le32_to_cpu(*addr);
+               if (blkaddr == NULL_ADDR)
+                       continue;
+
+               update_extent_cache(NULL_ADDR, dn);
+               invalidate_blocks(sbi, blkaddr);
+               dec_valid_block_count(sbi, dn->inode, 1);
+               nr_free++;
+       }
+       if (nr_free) {
+               set_page_dirty(dn->node_page);
+               sync_inode_page(dn);
+       }
+       dn->ofs_in_node = ofs;
+       return nr_free;
+}
+
+void truncate_data_blocks(struct dnode_of_data *dn)
+{
+       truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
+}
+
+static void truncate_partial_data_page(struct inode *inode, u64 from)
+{
+       unsigned offset = from & (PAGE_CACHE_SIZE - 1);
+       struct page *page;
+
+       if (!offset)
+               return;
+
+       page = find_data_page(inode, from >> PAGE_CACHE_SHIFT);
+       if (IS_ERR(page))
+               return;
+
+       lock_page(page);
+       wait_on_page_writeback(page);
+       zero_user(page, offset, PAGE_CACHE_SIZE - offset);
+       set_page_dirty(page);
+       f2fs_put_page(page, 1);
+}
+
+static int truncate_blocks(struct inode *inode, u64 from)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       unsigned int blocksize = inode->i_sb->s_blocksize;
+       struct dnode_of_data dn;
+       pgoff_t free_from;
+       int count = 0;
+       int err;
+
+       free_from = (pgoff_t)
+                       ((from + blocksize - 1) >> (sbi->log_blocksize));
+
+       mutex_lock_op(sbi, DATA_TRUNC);
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
+       if (err) {
+               if (err == -ENOENT)
+                       goto free_next;
+               mutex_unlock_op(sbi, DATA_TRUNC);
+               return err;
+       }
+
+       if (IS_INODE(dn.node_page))
+               count = ADDRS_PER_INODE;
+       else
+               count = ADDRS_PER_BLOCK;
+
+       count -= dn.ofs_in_node;
+       BUG_ON(count < 0);
+       if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
+               truncate_data_blocks_range(&dn, count);
+               free_from += count;
+       }
+
+       f2fs_put_dnode(&dn);
+free_next:
+       err = truncate_inode_blocks(inode, free_from);
+       mutex_unlock_op(sbi, DATA_TRUNC);
+
+       /* lastly zero out the first data page */
+       truncate_partial_data_page(inode, from);
+
+       return err;
+}
+
+void f2fs_truncate(struct inode *inode)
+{
+       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+                               S_ISLNK(inode->i_mode)))
+               return;
+
+       if (!truncate_blocks(inode, i_size_read(inode))) {
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+       }
+
+       f2fs_balance_fs(F2FS_SB(inode->i_sb));
+}
+
+static int f2fs_getattr(struct vfsmount *mnt,
+                        struct dentry *dentry, struct kstat *stat)
+{
+       struct inode *inode = dentry->d_inode;
+       generic_fillattr(inode, stat);
+       stat->blocks <<= 3;
+       return 0;
+}
+
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+static void __setattr_copy(struct inode *inode, const struct iattr *attr)
+{
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       unsigned int ia_valid = attr->ia_valid;
+
+       if (ia_valid & ATTR_UID)
+               inode->i_uid = attr->ia_uid;
+       if (ia_valid & ATTR_GID)
+               inode->i_gid = attr->ia_gid;
+       if (ia_valid & ATTR_ATIME)
+               inode->i_atime = timespec_trunc(attr->ia_atime,
+                                               inode->i_sb->s_time_gran);
+       if (ia_valid & ATTR_MTIME)
+               inode->i_mtime = timespec_trunc(attr->ia_mtime,
+                                               inode->i_sb->s_time_gran);
+       if (ia_valid & ATTR_CTIME)
+               inode->i_ctime = timespec_trunc(attr->ia_ctime,
+                                               inode->i_sb->s_time_gran);
+       if (ia_valid & ATTR_MODE) {
+               umode_t mode = attr->ia_mode;
+
+               if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+                       mode &= ~S_ISGID;
+               set_acl_inode(fi, mode);
+       }
+}
+#else
+#define __setattr_copy setattr_copy
+#endif
+
+int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       struct inode *inode = dentry->d_inode;
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       int err;
+
+       err = inode_change_ok(inode, attr);
+       if (err)
+               return err;
+
+       if ((attr->ia_valid & ATTR_SIZE) &&
+                       attr->ia_size != i_size_read(inode)) {
+               truncate_setsize(inode, attr->ia_size);
+               f2fs_truncate(inode);
+       }
+
+       __setattr_copy(inode, attr);
+
+       if (attr->ia_valid & ATTR_MODE) {
+               err = f2fs_acl_chmod(inode);
+               if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
+                       inode->i_mode = fi->i_acl_mode;
+                       clear_inode_flag(fi, FI_ACL_MODE);
+               }
+       }
+
+       mark_inode_dirty(inode);
+       return err;
+}
+
+const struct inode_operations f2fs_file_inode_operations = {
+       .getattr        = f2fs_getattr,
+       .setattr        = f2fs_setattr,
+       .get_acl        = f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = f2fs_listxattr,
+       .removexattr    = generic_removexattr,
+#endif
+};
+
+static void fill_zero(struct inode *inode, pgoff_t index,
+                                       loff_t start, loff_t len)
+{
+       struct page *page;
+
+       if (!len)
+               return;
+
+       page = get_new_data_page(inode, index, false);
+
+       if (!IS_ERR(page)) {
+               wait_on_page_writeback(page);
+               zero_user(page, start, len);
+               set_page_dirty(page);
+               f2fs_put_page(page, 1);
+       }
+}
+
+int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
+{
+       pgoff_t index;
+       int err;
+
+       for (index = pg_start; index < pg_end; index++) {
+               struct dnode_of_data dn;
+               struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+               f2fs_balance_fs(sbi);
+
+               mutex_lock_op(sbi, DATA_TRUNC);
+               set_new_dnode(&dn, inode, NULL, NULL, 0);
+               err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+               if (err) {
+                       mutex_unlock_op(sbi, DATA_TRUNC);
+                       if (err == -ENOENT)
+                               continue;
+                       return err;
+               }
+
+               if (dn.data_blkaddr != NULL_ADDR)
+                       truncate_data_blocks_range(&dn, 1);
+               f2fs_put_dnode(&dn);
+               mutex_unlock_op(sbi, DATA_TRUNC);
+       }
+       return 0;
+}
+
+static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
+{
+       pgoff_t pg_start, pg_end;
+       loff_t off_start, off_end;
+       int ret = 0;
+
+       pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
+       pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
+
+       off_start = offset & (PAGE_CACHE_SIZE - 1);
+       off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
+
+       if (pg_start == pg_end) {
+               fill_zero(inode, pg_start, off_start,
+                                               off_end - off_start);
+       } else {
+               if (off_start)
+                       fill_zero(inode, pg_start++, off_start,
+                                       PAGE_CACHE_SIZE - off_start);
+               if (off_end)
+                       fill_zero(inode, pg_end, 0, off_end);
+
+               if (pg_start < pg_end) {
+                       struct address_space *mapping = inode->i_mapping;
+                       loff_t blk_start, blk_end;
+
+                       blk_start = pg_start << PAGE_CACHE_SHIFT;
+                       blk_end = pg_end << PAGE_CACHE_SHIFT;
+                       truncate_inode_pages_range(mapping, blk_start,
+                                       blk_end - 1);
+                       ret = truncate_hole(inode, pg_start, pg_end);
+               }
+       }
+
+       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+               i_size_read(inode) <= (offset + len)) {
+               i_size_write(inode, offset);
+               mark_inode_dirty(inode);
+       }
+
+       return ret;
+}
+
+static int expand_inode_data(struct inode *inode, loff_t offset,
+                                       loff_t len, int mode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       pgoff_t index, pg_start, pg_end;
+       loff_t new_size = i_size_read(inode);
+       loff_t off_start, off_end;
+       int ret = 0;
+
+       ret = inode_newsize_ok(inode, (len + offset));
+       if (ret)
+               return ret;
+
+       pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
+       pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
+
+       off_start = offset & (PAGE_CACHE_SIZE - 1);
+       off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
+
+       for (index = pg_start; index <= pg_end; index++) {
+               struct dnode_of_data dn;
+
+               mutex_lock_op(sbi, DATA_NEW);
+
+               set_new_dnode(&dn, inode, NULL, NULL, 0);
+               ret = get_dnode_of_data(&dn, index, 0);
+               if (ret) {
+                       mutex_unlock_op(sbi, DATA_NEW);
+                       break;
+               }
+
+               if (dn.data_blkaddr == NULL_ADDR) {
+                       ret = reserve_new_block(&dn);
+                       if (ret) {
+                               f2fs_put_dnode(&dn);
+                               mutex_unlock_op(sbi, DATA_NEW);
+                               break;
+                       }
+               }
+               f2fs_put_dnode(&dn);
+
+               mutex_unlock_op(sbi, DATA_NEW);
+
+               if (pg_start == pg_end)
+                       new_size = offset + len;
+               else if (index == pg_start && off_start)
+                       new_size = (index + 1) << PAGE_CACHE_SHIFT;
+               else if (index == pg_end)
+                       new_size = (index << PAGE_CACHE_SHIFT) + off_end;
+               else
+                       new_size += PAGE_CACHE_SIZE;
+       }
+
+       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+               i_size_read(inode) < new_size) {
+               i_size_write(inode, new_size);
+               mark_inode_dirty(inode);
+       }
+
+       return ret;
+}
+
+static long f2fs_fallocate(struct file *file, int mode,
+                               loff_t offset, loff_t len)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       long ret;
+
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+               return -EOPNOTSUPP;
+
+       if (mode & FALLOC_FL_PUNCH_HOLE)
+               ret = punch_hole(inode, offset, len, mode);
+       else
+               ret = expand_inode_data(inode, offset, len, mode);
+
+       if (!ret) {
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+       }
+       return ret;
+}
+
+#define F2FS_REG_FLMASK                (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
+#define F2FS_OTHER_FLMASK      (FS_NODUMP_FL | FS_NOATIME_FL)
+
+static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
+{
+       if (S_ISDIR(mode))
+               return flags;
+       else if (S_ISREG(mode))
+               return flags & F2FS_REG_FLMASK;
+       else
+               return flags & F2FS_OTHER_FLMASK;
+}
+
+long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       unsigned int flags;
+       int ret;
+
+       switch (cmd) {
+       case FS_IOC_GETFLAGS:
+               flags = fi->i_flags & FS_FL_USER_VISIBLE;
+               return put_user(flags, (int __user *) arg);
+       case FS_IOC_SETFLAGS:
+       {
+               unsigned int oldflags;
+
+               ret = mnt_want_write(filp->f_path.mnt);
+               if (ret)
+                       return ret;
+
+               if (!inode_owner_or_capable(inode)) {
+                       ret = -EACCES;
+                       goto out;
+               }
+
+               if (get_user(flags, (int __user *) arg)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               flags = f2fs_mask_flags(inode->i_mode, flags);
+
+               mutex_lock(&inode->i_mutex);
+
+               oldflags = fi->i_flags;
+
+               if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
+                       if (!capable(CAP_LINUX_IMMUTABLE)) {
+                               mutex_unlock(&inode->i_mutex);
+                               ret = -EPERM;
+                               goto out;
+                       }
+               }
+
+               flags = flags & FS_FL_USER_MODIFIABLE;
+               flags |= oldflags & ~FS_FL_USER_MODIFIABLE;
+               fi->i_flags = flags;
+               mutex_unlock(&inode->i_mutex);
+
+               f2fs_set_inode_flags(inode);
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+out:
+               mnt_drop_write(filp->f_path.mnt);
+               return ret;
+       }
+       default:
+               return -ENOTTY;
+       }
+}
+
+const struct file_operations f2fs_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = generic_file_aio_read,
+       .aio_write      = generic_file_aio_write,
+       .open           = generic_file_open,
+       .mmap           = f2fs_file_mmap,
+       .fsync          = f2fs_sync_file,
+       .fallocate      = f2fs_fallocate,
+       .unlocked_ioctl = f2fs_ioctl,
+       .splice_read    = generic_file_splice_read,
+       .splice_write   = generic_file_splice_write,
+};
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
new file mode 100644 (file)
index 0000000..c386910
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * fs/f2fs/gc.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/module.h>
+#include <linux/backing-dev.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/f2fs_fs.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/blkdev.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "gc.h"
+
+static struct kmem_cache *winode_slab;
+
+static int gc_thread_func(void *data)
+{
+       struct f2fs_sb_info *sbi = data;
+       wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
+       long wait_ms;
+
+       wait_ms = GC_THREAD_MIN_SLEEP_TIME;
+
+       do {
+               if (try_to_freeze())
+                       continue;
+               else
+                       wait_event_interruptible_timeout(*wq,
+                                               kthread_should_stop(),
+                                               msecs_to_jiffies(wait_ms));
+               if (kthread_should_stop())
+                       break;
+
+               f2fs_balance_fs(sbi);
+
+               if (!test_opt(sbi, BG_GC))
+                       continue;
+
+               /*
+                * [GC triggering condition]
+                * 0. GC is not conducted currently.
+                * 1. There are enough dirty segments.
+                * 2. IO subsystem is idle by checking the # of writeback pages.
+                * 3. IO subsystem is idle by checking the # of requests in
+                *    bdev's request list.
+                *
+                * Note) We have to avoid triggering GCs too much frequently.
+                * Because it is possible that some segments can be
+                * invalidated soon after by user update or deletion.
+                * So, I'd like to wait some time to collect dirty segments.
+                */
+               if (!mutex_trylock(&sbi->gc_mutex))
+                       continue;
+
+               if (!is_idle(sbi)) {
+                       wait_ms = increase_sleep_time(wait_ms);
+                       mutex_unlock(&sbi->gc_mutex);
+                       continue;
+               }
+
+               if (has_enough_invalid_blocks(sbi))
+                       wait_ms = decrease_sleep_time(wait_ms);
+               else
+                       wait_ms = increase_sleep_time(wait_ms);
+
+               sbi->bg_gc++;
+
+               if (f2fs_gc(sbi) == GC_NONE)
+                       wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
+               else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
+                       wait_ms = GC_THREAD_MAX_SLEEP_TIME;
+
+       } while (!kthread_should_stop());
+       return 0;
+}
+
+int start_gc_thread(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_gc_kthread *gc_th;
+
+       gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
+       if (!gc_th)
+               return -ENOMEM;
+
+       sbi->gc_thread = gc_th;
+       init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
+       sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
+                               GC_THREAD_NAME);
+       if (IS_ERR(gc_th->f2fs_gc_task)) {
+               kfree(gc_th);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void stop_gc_thread(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
+       if (!gc_th)
+               return;
+       kthread_stop(gc_th->f2fs_gc_task);
+       kfree(gc_th);
+       sbi->gc_thread = NULL;
+}
+
+static int select_gc_type(int gc_type)
+{
+       return (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
+}
+
+static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
+                       int type, struct victim_sel_policy *p)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+       if (p->alloc_mode) {
+               p->gc_mode = GC_GREEDY;
+               p->dirty_segmap = dirty_i->dirty_segmap[type];
+               p->ofs_unit = 1;
+       } else {
+               p->gc_mode = select_gc_type(gc_type);
+               p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
+               p->ofs_unit = sbi->segs_per_sec;
+       }
+       p->offset = sbi->last_victim[p->gc_mode];
+}
+
+static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
+                               struct victim_sel_policy *p)
+{
+       if (p->gc_mode == GC_GREEDY)
+               return (1 << sbi->log_blocks_per_seg) * p->ofs_unit;
+       else if (p->gc_mode == GC_CB)
+               return UINT_MAX;
+       else /* No other gc_mode */
+               return 0;
+}
+
+static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned int segno;
+
+       /*
+        * If the gc_type is FG_GC, we can select victim segments
+        * selected by background GC before.
+        * Those segments guarantee they have small valid blocks.
+        */
+       segno = find_next_bit(dirty_i->victim_segmap[BG_GC],
+                                               TOTAL_SEGS(sbi), 0);
+       if (segno < TOTAL_SEGS(sbi)) {
+               clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
+               return segno;
+       }
+       return NULL_SEGNO;
+}
+
+static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int secno = GET_SECNO(sbi, segno);
+       unsigned int start = secno * sbi->segs_per_sec;
+       unsigned long long mtime = 0;
+       unsigned int vblocks;
+       unsigned char age = 0;
+       unsigned char u;
+       unsigned int i;
+
+       for (i = 0; i < sbi->segs_per_sec; i++)
+               mtime += get_seg_entry(sbi, start + i)->mtime;
+       vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+
+       mtime = div_u64(mtime, sbi->segs_per_sec);
+       vblocks = div_u64(vblocks, sbi->segs_per_sec);
+
+       u = (vblocks * 100) >> sbi->log_blocks_per_seg;
+
+       /* Handle if the system time is changed by user */
+       if (mtime < sit_i->min_mtime)
+               sit_i->min_mtime = mtime;
+       if (mtime > sit_i->max_mtime)
+               sit_i->max_mtime = mtime;
+       if (sit_i->max_mtime != sit_i->min_mtime)
+               age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime),
+                               sit_i->max_mtime - sit_i->min_mtime);
+
+       return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
+}
+
+static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
+                                       struct victim_sel_policy *p)
+{
+       if (p->alloc_mode == SSR)
+               return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
+
+       /* alloc_mode == LFS */
+       if (p->gc_mode == GC_GREEDY)
+               return get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+       else
+               return get_cb_cost(sbi, segno);
+}
+
+/*
+ * This function is called from two pathes.
+ * One is garbage collection and the other is SSR segment selection.
+ * When it is called during GC, it just gets a victim segment
+ * and it does not remove it from dirty seglist.
+ * When it is called from SSR segment selection, it finds a segment
+ * which has minimum valid blocks and removes it from dirty seglist.
+ */
+static int get_victim_by_default(struct f2fs_sb_info *sbi,
+               unsigned int *result, int gc_type, int type, char alloc_mode)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       struct victim_sel_policy p;
+       unsigned int segno;
+       int nsearched = 0;
+
+       p.alloc_mode = alloc_mode;
+       select_policy(sbi, gc_type, type, &p);
+
+       p.min_segno = NULL_SEGNO;
+       p.min_cost = get_max_cost(sbi, &p);
+
+       mutex_lock(&dirty_i->seglist_lock);
+
+       if (p.alloc_mode == LFS && gc_type == FG_GC) {
+               p.min_segno = check_bg_victims(sbi);
+               if (p.min_segno != NULL_SEGNO)
+                       goto got_it;
+       }
+
+       while (1) {
+               unsigned long cost;
+
+               segno = find_next_bit(p.dirty_segmap,
+                                               TOTAL_SEGS(sbi), p.offset);
+               if (segno >= TOTAL_SEGS(sbi)) {
+                       if (sbi->last_victim[p.gc_mode]) {
+                               sbi->last_victim[p.gc_mode] = 0;
+                               p.offset = 0;
+                               continue;
+                       }
+                       break;
+               }
+               p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
+
+               if (test_bit(segno, dirty_i->victim_segmap[FG_GC]))
+                       continue;
+               if (gc_type == BG_GC &&
+                               test_bit(segno, dirty_i->victim_segmap[BG_GC]))
+                       continue;
+               if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
+                       continue;
+
+               cost = get_gc_cost(sbi, segno, &p);
+
+               if (p.min_cost > cost) {
+                       p.min_segno = segno;
+                       p.min_cost = cost;
+               }
+
+               if (cost == get_max_cost(sbi, &p))
+                       continue;
+
+               if (nsearched++ >= MAX_VICTIM_SEARCH) {
+                       sbi->last_victim[p.gc_mode] = segno;
+                       break;
+               }
+       }
+got_it:
+       if (p.min_segno != NULL_SEGNO) {
+               *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
+               if (p.alloc_mode == LFS) {
+                       int i;
+                       for (i = 0; i < p.ofs_unit; i++)
+                               set_bit(*result + i,
+                                       dirty_i->victim_segmap[gc_type]);
+               }
+       }
+       mutex_unlock(&dirty_i->seglist_lock);
+
+       return (p.min_segno == NULL_SEGNO) ? 0 : 1;
+}
+
+static const struct victim_selection default_v_ops = {
+       .get_victim = get_victim_by_default,
+};
+
+static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist)
+{
+       struct list_head *this;
+       struct inode_entry *ie;
+
+       list_for_each(this, ilist) {
+               ie = list_entry(this, struct inode_entry, list);
+               if (ie->inode->i_ino == ino)
+                       return ie->inode;
+       }
+       return NULL;
+}
+
+static void add_gc_inode(struct inode *inode, struct list_head *ilist)
+{
+       struct list_head *this;
+       struct inode_entry *new_ie, *ie;
+
+       list_for_each(this, ilist) {
+               ie = list_entry(this, struct inode_entry, list);
+               if (ie->inode == inode) {
+                       iput(inode);
+                       return;
+               }
+       }
+repeat:
+       new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS);
+       if (!new_ie) {
+               cond_resched();
+               goto repeat;
+       }
+       new_ie->inode = inode;
+       list_add_tail(&new_ie->list, ilist);
+}
+
+static void put_gc_inode(struct list_head *ilist)
+{
+       struct inode_entry *ie, *next_ie;
+       list_for_each_entry_safe(ie, next_ie, ilist, list) {
+               iput(ie->inode);
+               list_del(&ie->list);
+               kmem_cache_free(winode_slab, ie);
+       }
+}
+
+static int check_valid_map(struct f2fs_sb_info *sbi,
+                               unsigned int segno, int offset)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct seg_entry *sentry;
+       int ret;
+
+       mutex_lock(&sit_i->sentry_lock);
+       sentry = get_seg_entry(sbi, segno);
+       ret = f2fs_test_bit(offset, sentry->cur_valid_map);
+       mutex_unlock(&sit_i->sentry_lock);
+       return ret ? GC_OK : GC_NEXT;
+}
+
+/*
+ * This function compares node address got in summary with that in NAT.
+ * On validity, copy that node with cold status, otherwise (invalid node)
+ * ignore that.
+ */
+static int gc_node_segment(struct f2fs_sb_info *sbi,
+               struct f2fs_summary *sum, unsigned int segno, int gc_type)
+{
+       bool initial = true;
+       struct f2fs_summary *entry;
+       int off;
+
+next_step:
+       entry = sum;
+       for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
+               nid_t nid = le32_to_cpu(entry->nid);
+               struct page *node_page;
+               int err;
+
+               /*
+                * It makes sure that free segments are able to write
+                * all the dirty node pages before CP after this CP.
+                * So let's check the space of dirty node pages.
+                */
+               if (should_do_checkpoint(sbi)) {
+                       mutex_lock(&sbi->cp_mutex);
+                       block_operations(sbi);
+                       return GC_BLOCKED;
+               }
+
+               err = check_valid_map(sbi, segno, off);
+               if (err == GC_NEXT)
+                       continue;
+
+               if (initial) {
+                       ra_node_page(sbi, nid);
+                       continue;
+               }
+               node_page = get_node_page(sbi, nid);
+               if (IS_ERR(node_page))
+                       continue;
+
+               /* set page dirty and write it */
+               if (!PageWriteback(node_page))
+                       set_page_dirty(node_page);
+               f2fs_put_page(node_page, 1);
+               stat_inc_node_blk_count(sbi, 1);
+       }
+       if (initial) {
+               initial = false;
+               goto next_step;
+       }
+
+       if (gc_type == FG_GC) {
+               struct writeback_control wbc = {
+                       .sync_mode = WB_SYNC_ALL,
+                       .nr_to_write = LONG_MAX,
+                       .for_reclaim = 0,
+               };
+               sync_node_pages(sbi, 0, &wbc);
+       }
+       return GC_DONE;
+}
+
+/*
+ * Calculate start block index indicating the given node offset.
+ * Be careful, caller should give this node offset only indicating direct node
+ * blocks. If any node offsets, which point the other types of node blocks such
+ * as indirect or double indirect node blocks, are given, it must be a caller's
+ * bug.
+ */
+block_t start_bidx_of_node(unsigned int node_ofs)
+{
+       unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+       unsigned int bidx;
+
+       if (node_ofs == 0)
+               return 0;
+
+       if (node_ofs <= 2) {
+               bidx = node_ofs - 1;
+       } else if (node_ofs <= indirect_blks) {
+               int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+               bidx = node_ofs - 2 - dec;
+       } else {
+               int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+               bidx = node_ofs - 5 - dec;
+       }
+       return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;
+}
+
+static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+               struct node_info *dni, block_t blkaddr, unsigned int *nofs)
+{
+       struct page *node_page;
+       nid_t nid;
+       unsigned int ofs_in_node;
+       block_t source_blkaddr;
+
+       nid = le32_to_cpu(sum->nid);
+       ofs_in_node = le16_to_cpu(sum->ofs_in_node);
+
+       node_page = get_node_page(sbi, nid);
+       if (IS_ERR(node_page))
+               return GC_NEXT;
+
+       get_node_info(sbi, nid, dni);
+
+       if (sum->version != dni->version) {
+               f2fs_put_page(node_page, 1);
+               return GC_NEXT;
+       }
+
+       *nofs = ofs_of_node(node_page);
+       source_blkaddr = datablock_addr(node_page, ofs_in_node);
+       f2fs_put_page(node_page, 1);
+
+       if (source_blkaddr != blkaddr)
+               return GC_NEXT;
+       return GC_OK;
+}
+
+static void move_data_page(struct inode *inode, struct page *page, int gc_type)
+{
+       if (page->mapping != inode->i_mapping)
+               goto out;
+
+       if (inode != page->mapping->host)
+               goto out;
+
+       if (PageWriteback(page))
+               goto out;
+
+       if (gc_type == BG_GC) {
+               set_page_dirty(page);
+               set_cold_data(page);
+       } else {
+               struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+               mutex_lock_op(sbi, DATA_WRITE);
+               if (clear_page_dirty_for_io(page) &&
+                       S_ISDIR(inode->i_mode)) {
+                       dec_page_count(sbi, F2FS_DIRTY_DENTS);
+                       inode_dec_dirty_dents(inode);
+               }
+               set_cold_data(page);
+               do_write_data_page(page);
+               mutex_unlock_op(sbi, DATA_WRITE);
+               clear_cold_data(page);
+       }
+out:
+       f2fs_put_page(page, 1);
+}
+
+/*
+ * This function tries to get parent node of victim data block, and identifies
+ * data block validity. If the block is valid, copy that with cold status and
+ * modify parent node.
+ * If the parent node is not valid or the data block address is different,
+ * the victim data block is ignored.
+ */
+static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+               struct list_head *ilist, unsigned int segno, int gc_type)
+{
+       struct super_block *sb = sbi->sb;
+       struct f2fs_summary *entry;
+       block_t start_addr;
+       int err, off;
+       int phase = 0;
+
+       start_addr = START_BLOCK(sbi, segno);
+
+next_step:
+       entry = sum;
+       for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
+               struct page *data_page;
+               struct inode *inode;
+               struct node_info dni; /* dnode info for the data */
+               unsigned int ofs_in_node, nofs;
+               block_t start_bidx;
+
+               /*
+                * It makes sure that free segments are able to write
+                * all the dirty node pages before CP after this CP.
+                * So let's check the space of dirty node pages.
+                */
+               if (should_do_checkpoint(sbi)) {
+                       mutex_lock(&sbi->cp_mutex);
+                       block_operations(sbi);
+                       err = GC_BLOCKED;
+                       goto stop;
+               }
+
+               err = check_valid_map(sbi, segno, off);
+               if (err == GC_NEXT)
+                       continue;
+
+               if (phase == 0) {
+                       ra_node_page(sbi, le32_to_cpu(entry->nid));
+                       continue;
+               }
+
+               /* Get an inode by ino with checking validity */
+               err = check_dnode(sbi, entry, &dni, start_addr + off, &nofs);
+               if (err == GC_NEXT)
+                       continue;
+
+               if (phase == 1) {
+                       ra_node_page(sbi, dni.ino);
+                       continue;
+               }
+
+               start_bidx = start_bidx_of_node(nofs);
+               ofs_in_node = le16_to_cpu(entry->ofs_in_node);
+
+               if (phase == 2) {
+                       inode = f2fs_iget_nowait(sb, dni.ino);
+                       if (IS_ERR(inode))
+                               continue;
+
+                       data_page = find_data_page(inode,
+                                       start_bidx + ofs_in_node);
+                       if (IS_ERR(data_page))
+                               goto next_iput;
+
+                       f2fs_put_page(data_page, 0);
+                       add_gc_inode(inode, ilist);
+               } else {
+                       inode = find_gc_inode(dni.ino, ilist);
+                       if (inode) {
+                               data_page = get_lock_data_page(inode,
+                                               start_bidx + ofs_in_node);
+                               if (IS_ERR(data_page))
+                                       continue;
+                               move_data_page(inode, data_page, gc_type);
+                               stat_inc_data_blk_count(sbi, 1);
+                       }
+               }
+               continue;
+next_iput:
+               iput(inode);
+       }
+       if (++phase < 4)
+               goto next_step;
+       err = GC_DONE;
+stop:
+       if (gc_type == FG_GC)
+               f2fs_submit_bio(sbi, DATA, true);
+       return err;
+}
+
+static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
+                                               int gc_type, int type)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       int ret;
+       mutex_lock(&sit_i->sentry_lock);
+       ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type, type, LFS);
+       mutex_unlock(&sit_i->sentry_lock);
+       return ret;
+}
+
+static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
+                               struct list_head *ilist, int gc_type)
+{
+       struct page *sum_page;
+       struct f2fs_summary_block *sum;
+       int ret = GC_DONE;
+
+       /* read segment summary of victim */
+       sum_page = get_sum_page(sbi, segno);
+       if (IS_ERR(sum_page))
+               return GC_ERROR;
+
+       /*
+        * CP needs to lock sum_page. In this time, we don't need
+        * to lock this page, because this summary page is not gone anywhere.
+        * Also, this page is not gonna be updated before GC is done.
+        */
+       unlock_page(sum_page);
+       sum = page_address(sum_page);
+
+       switch (GET_SUM_TYPE((&sum->footer))) {
+       case SUM_TYPE_NODE:
+               ret = gc_node_segment(sbi, sum->entries, segno, gc_type);
+               break;
+       case SUM_TYPE_DATA:
+               ret = gc_data_segment(sbi, sum->entries, ilist, segno, gc_type);
+               break;
+       }
+       stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
+       stat_inc_call_count(sbi->stat_info);
+
+       f2fs_put_page(sum_page, 0);
+       return ret;
+}
+
+int f2fs_gc(struct f2fs_sb_info *sbi)
+{
+       struct list_head ilist;
+       unsigned int segno, i;
+       int gc_type = BG_GC;
+       int gc_status = GC_NONE;
+
+       INIT_LIST_HEAD(&ilist);
+gc_more:
+       if (!(sbi->sb->s_flags & MS_ACTIVE))
+               goto stop;
+
+       if (has_not_enough_free_secs(sbi))
+               gc_type = FG_GC;
+
+       if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
+               goto stop;
+
+       for (i = 0; i < sbi->segs_per_sec; i++) {
+               /*
+                * do_garbage_collect will give us three gc_status:
+                * GC_ERROR, GC_DONE, and GC_BLOCKED.
+                * If GC is finished uncleanly, we have to return
+                * the victim to dirty segment list.
+                */
+               gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type);
+               if (gc_status != GC_DONE)
+                       break;
+       }
+       if (has_not_enough_free_secs(sbi)) {
+               write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
+               if (has_not_enough_free_secs(sbi))
+                       goto gc_more;
+       }
+stop:
+       mutex_unlock(&sbi->gc_mutex);
+
+       put_gc_inode(&ilist);
+       return gc_status;
+}
+
+void build_gc_manager(struct f2fs_sb_info *sbi)
+{
+       DIRTY_I(sbi)->v_ops = &default_v_ops;
+}
+
+int __init create_gc_caches(void)
+{
+       winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
+                       sizeof(struct inode_entry), NULL);
+       if (!winode_slab)
+               return -ENOMEM;
+       return 0;
+}
+
+void destroy_gc_caches(void)
+{
+       kmem_cache_destroy(winode_slab);
+}
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
new file mode 100644 (file)
index 0000000..b026d93
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * fs/f2fs/gc.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+#define GC_THREAD_NAME "f2fs_gc_task"
+#define GC_THREAD_MIN_WB_PAGES         1       /*
+                                                * a threshold to determine
+                                                * whether IO subsystem is idle
+                                                * or not
+                                                */
+#define GC_THREAD_MIN_SLEEP_TIME       10000 /* milliseconds */
+#define GC_THREAD_MAX_SLEEP_TIME       30000
+#define GC_THREAD_NOGC_SLEEP_TIME      10000
+#define LIMIT_INVALID_BLOCK    40 /* percentage over total user space */
+#define LIMIT_FREE_BLOCK       40 /* percentage over invalid + free space */
+
+/* Search max. number of dirty segments to select a victim segment */
+#define MAX_VICTIM_SEARCH      20
+
+enum {
+       GC_NONE = 0,
+       GC_ERROR,
+       GC_OK,
+       GC_NEXT,
+       GC_BLOCKED,
+       GC_DONE,
+};
+
+struct f2fs_gc_kthread {
+       struct task_struct *f2fs_gc_task;
+       wait_queue_head_t gc_wait_queue_head;
+};
+
+struct inode_entry {
+       struct list_head list;
+       struct inode *inode;
+};
+
+/*
+ * inline functions
+ */
+static inline block_t free_user_blocks(struct f2fs_sb_info *sbi)
+{
+       if (free_segments(sbi) < overprovision_segments(sbi))
+               return 0;
+       else
+               return (free_segments(sbi) - overprovision_segments(sbi))
+                       << sbi->log_blocks_per_seg;
+}
+
+static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi)
+{
+       return (long)(sbi->user_block_count * LIMIT_INVALID_BLOCK) / 100;
+}
+
+static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
+{
+       block_t reclaimable_user_blocks = sbi->user_block_count -
+               written_block_count(sbi);
+       return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
+}
+
+static inline long increase_sleep_time(long wait)
+{
+       wait += GC_THREAD_MIN_SLEEP_TIME;
+       if (wait > GC_THREAD_MAX_SLEEP_TIME)
+               wait = GC_THREAD_MAX_SLEEP_TIME;
+       return wait;
+}
+
+static inline long decrease_sleep_time(long wait)
+{
+       wait -= GC_THREAD_MIN_SLEEP_TIME;
+       if (wait <= GC_THREAD_MIN_SLEEP_TIME)
+               wait = GC_THREAD_MIN_SLEEP_TIME;
+       return wait;
+}
+
+static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
+{
+       block_t invalid_user_blocks = sbi->user_block_count -
+                                       written_block_count(sbi);
+       /*
+        * Background GC is triggered with the following condition.
+        * 1. There are a number of invalid blocks.
+        * 2. There is not enough free space.
+        */
+       if (invalid_user_blocks > limit_invalid_user_blocks(sbi) &&
+                       free_user_blocks(sbi) < limit_free_user_blocks(sbi))
+               return true;
+       return false;
+}
+
+static inline int is_idle(struct f2fs_sb_info *sbi)
+{
+       struct block_device *bdev = sbi->sb->s_bdev;
+       struct request_queue *q = bdev_get_queue(bdev);
+       struct request_list *rl = &q->root_rl;
+       return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
+}
+
+static inline bool should_do_checkpoint(struct f2fs_sb_info *sbi)
+{
+       unsigned int pages_per_sec = sbi->segs_per_sec *
+                                       (1 << sbi->log_blocks_per_seg);
+       int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
+                       >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+       int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
+                       >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+       return free_sections(sbi) <= (node_secs + 2 * dent_secs + 2);
+}
diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
new file mode 100644 (file)
index 0000000..6eb8d26
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * fs/f2fs/hash.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext3/hash.c
+ *
+ * Copyright (C) 2002 by Theodore Ts'o
+ *
+ * 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/types.h>
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/cryptohash.h>
+#include <linux/pagemap.h>
+
+#include "f2fs.h"
+
+/*
+ * Hashing code copied from ext3
+ */
+#define DELTA 0x9E3779B9
+
+static void TEA_transform(unsigned int buf[4], unsigned int const in[])
+{
+       __u32 sum = 0;
+       __u32 b0 = buf[0], b1 = buf[1];
+       __u32 a = in[0], b = in[1], c = in[2], d = in[3];
+       int n = 16;
+
+       do {
+               sum += DELTA;
+               b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+               b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+       } while (--n);
+
+       buf[0] += b0;
+       buf[1] += b1;
+}
+
+static void str2hashbuf(const char *msg, size_t len, unsigned int *buf, int num)
+{
+       unsigned pad, val;
+       int i;
+
+       pad = (__u32)len | ((__u32)len << 8);
+       pad |= pad << 16;
+
+       val = pad;
+       if (len > num * 4)
+               len = num * 4;
+       for (i = 0; i < len; i++) {
+               if ((i % 4) == 0)
+                       val = pad;
+               val = msg[i] + (val << 8);
+               if ((i % 4) == 3) {
+                       *buf++ = val;
+                       val = pad;
+                       num--;
+               }
+       }
+       if (--num >= 0)
+               *buf++ = val;
+       while (--num >= 0)
+               *buf++ = pad;
+}
+
+f2fs_hash_t f2fs_dentry_hash(const char *name, size_t len)
+{
+       __u32 hash;
+       f2fs_hash_t f2fs_hash;
+       const char *p;
+       __u32 in[8], buf[4];
+
+       if ((len <= 2) && (name[0] == '.') &&
+               (name[1] == '.' || name[1] == '\0'))
+               return 0;
+
+       /* Initialize the default seed for the hash checksum functions */
+       buf[0] = 0x67452301;
+       buf[1] = 0xefcdab89;
+       buf[2] = 0x98badcfe;
+       buf[3] = 0x10325476;
+
+       p = name;
+       while (1) {
+               str2hashbuf(p, len, in, 4);
+               TEA_transform(buf, in);
+               p += 16;
+               if (len <= 16)
+                       break;
+               len -= 16;
+       }
+       hash = buf[0];
+       f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
+       return f2fs_hash;
+}
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
new file mode 100644 (file)
index 0000000..7942417
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * fs/f2fs/inode.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+
+#include "f2fs.h"
+#include "node.h"
+
+struct f2fs_iget_args {
+       u64 ino;
+       int on_free;
+};
+
+void f2fs_set_inode_flags(struct inode *inode)
+{
+       unsigned int flags = F2FS_I(inode)->i_flags;
+
+       inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE |
+                       S_NOATIME | S_DIRSYNC);
+
+       if (flags & FS_SYNC_FL)
+               inode->i_flags |= S_SYNC;
+       if (flags & FS_APPEND_FL)
+               inode->i_flags |= S_APPEND;
+       if (flags & FS_IMMUTABLE_FL)
+               inode->i_flags |= S_IMMUTABLE;
+       if (flags & FS_NOATIME_FL)
+               inode->i_flags |= S_NOATIME;
+       if (flags & FS_DIRSYNC_FL)
+               inode->i_flags |= S_DIRSYNC;
+}
+
+static int f2fs_iget_test(struct inode *inode, void *data)
+{
+       struct f2fs_iget_args *args = data;
+
+       if (inode->i_ino != args->ino)
+               return 0;
+       if (inode->i_state & (I_FREEING | I_WILL_FREE)) {
+               args->on_free = 1;
+               return 0;
+       }
+       return 1;
+}
+
+struct inode *f2fs_iget_nowait(struct super_block *sb, unsigned long ino)
+{
+       struct f2fs_iget_args args = {
+               .ino = ino,
+               .on_free = 0
+       };
+       struct inode *inode = ilookup5(sb, ino, f2fs_iget_test, &args);
+
+       if (inode)
+               return inode;
+       if (!args.on_free)
+               return f2fs_iget(sb, ino);
+       return ERR_PTR(-ENOENT);
+}
+
+static int do_read_inode(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       struct page *node_page;
+       struct f2fs_node *rn;
+       struct f2fs_inode *ri;
+
+       /* Check if ino is within scope */
+       check_nid_range(sbi, inode->i_ino);
+
+       node_page = get_node_page(sbi, inode->i_ino);
+       if (IS_ERR(node_page))
+               return PTR_ERR(node_page);
+
+       rn = page_address(node_page);
+       ri = &(rn->i);
+
+       inode->i_mode = le16_to_cpu(ri->i_mode);
+       i_uid_write(inode, le32_to_cpu(ri->i_uid));
+       i_gid_write(inode, le32_to_cpu(ri->i_gid));
+       set_nlink(inode, le32_to_cpu(ri->i_links));
+       inode->i_size = le64_to_cpu(ri->i_size);
+       inode->i_blocks = le64_to_cpu(ri->i_blocks);
+
+       inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
+       inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
+       inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
+       inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec);
+       inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
+       inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
+       inode->i_generation = le32_to_cpu(ri->i_generation);
+
+       fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+       fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
+       fi->i_flags = le32_to_cpu(ri->i_flags);
+       fi->flags = 0;
+       fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
+       fi->i_advise = ri->i_advise;
+       fi->i_pino = le32_to_cpu(ri->i_pino);
+       get_extent_info(&fi->ext, ri->i_ext);
+       f2fs_put_page(node_page, 1);
+       return 0;
+}
+
+struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode;
+       int ret;
+
+       inode = iget_locked(sb, ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+       if (!(inode->i_state & I_NEW))
+               return inode;
+       if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
+               goto make_now;
+
+       ret = do_read_inode(inode);
+       if (ret)
+               goto bad_inode;
+
+       if (!sbi->por_doing && inode->i_nlink == 0) {
+               ret = -ENOENT;
+               goto bad_inode;
+       }
+
+make_now:
+       if (ino == F2FS_NODE_INO(sbi)) {
+               inode->i_mapping->a_ops = &f2fs_node_aops;
+               mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+       } else if (ino == F2FS_META_INO(sbi)) {
+               inode->i_mapping->a_ops = &f2fs_meta_aops;
+               mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+       } else if (S_ISREG(inode->i_mode)) {
+               inode->i_op = &f2fs_file_inode_operations;
+               inode->i_fop = &f2fs_file_operations;
+               inode->i_mapping->a_ops = &f2fs_dblock_aops;
+       } else if (S_ISDIR(inode->i_mode)) {
+               inode->i_op = &f2fs_dir_inode_operations;
+               inode->i_fop = &f2fs_dir_operations;
+               inode->i_mapping->a_ops = &f2fs_dblock_aops;
+               mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
+                               __GFP_ZERO);
+       } else if (S_ISLNK(inode->i_mode)) {
+               inode->i_op = &f2fs_symlink_inode_operations;
+               inode->i_mapping->a_ops = &f2fs_dblock_aops;
+       } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+                       S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+               inode->i_op = &f2fs_special_inode_operations;
+               init_special_inode(inode, inode->i_mode, inode->i_rdev);
+       } else {
+               ret = -EIO;
+               goto bad_inode;
+       }
+       unlock_new_inode(inode);
+
+       return inode;
+
+bad_inode:
+       iget_failed(inode);
+       return ERR_PTR(ret);
+}
+
+void update_inode(struct inode *inode, struct page *node_page)
+{
+       struct f2fs_node *rn;
+       struct f2fs_inode *ri;
+
+       wait_on_page_writeback(node_page);
+
+       rn = page_address(node_page);
+       ri = &(rn->i);
+
+       ri->i_mode = cpu_to_le16(inode->i_mode);
+       ri->i_advise = F2FS_I(inode)->i_advise;
+       ri->i_uid = cpu_to_le32(i_uid_read(inode));
+       ri->i_gid = cpu_to_le32(i_gid_read(inode));
+       ri->i_links = cpu_to_le32(inode->i_nlink);
+       ri->i_size = cpu_to_le64(i_size_read(inode));
+       ri->i_blocks = cpu_to_le64(inode->i_blocks);
+       set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext);
+
+       ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
+       ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+       ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
+       ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
+       ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+       ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+       ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
+       ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
+       ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
+       ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
+       ri->i_generation = cpu_to_le32(inode->i_generation);
+       set_cold_node(inode, node_page);
+       set_page_dirty(node_page);
+}
+
+int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct page *node_page;
+       bool need_lock = false;
+
+       if (inode->i_ino == F2FS_NODE_INO(sbi) ||
+                       inode->i_ino == F2FS_META_INO(sbi))
+               return 0;
+
+       if (wbc)
+               f2fs_balance_fs(sbi);
+
+       node_page = get_node_page(sbi, inode->i_ino);
+       if (IS_ERR(node_page))
+               return PTR_ERR(node_page);
+
+       if (!PageDirty(node_page)) {
+               need_lock = true;
+               f2fs_put_page(node_page, 1);
+               mutex_lock(&sbi->write_inode);
+               node_page = get_node_page(sbi, inode->i_ino);
+               if (IS_ERR(node_page)) {
+                       mutex_unlock(&sbi->write_inode);
+                       return PTR_ERR(node_page);
+               }
+       }
+       update_inode(inode, node_page);
+       f2fs_put_page(node_page, 1);
+       if (need_lock)
+               mutex_unlock(&sbi->write_inode);
+       return 0;
+}
+
+/*
+ * Called at the last iput() if i_nlink is zero
+ */
+void f2fs_evict_inode(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+       truncate_inode_pages(&inode->i_data, 0);
+
+       if (inode->i_ino == F2FS_NODE_INO(sbi) ||
+                       inode->i_ino == F2FS_META_INO(sbi))
+               goto no_delete;
+
+       BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
+       remove_dirty_dir_inode(inode);
+
+       if (inode->i_nlink || is_bad_inode(inode))
+               goto no_delete;
+
+       set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
+       i_size_write(inode, 0);
+
+       if (F2FS_HAS_BLOCKS(inode))
+               f2fs_truncate(inode);
+
+       remove_inode_page(inode);
+no_delete:
+       clear_inode(inode);
+}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
new file mode 100644 (file)
index 0000000..1a49b88
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * fs/f2fs/namei.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/ctype.h>
+
+#include "f2fs.h"
+#include "xattr.h"
+#include "acl.h"
+
+static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
+{
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       nid_t ino;
+       struct inode *inode;
+       bool nid_free = false;
+       int err;
+
+       inode = new_inode(sb);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_lock_op(sbi, NODE_NEW);
+       if (!alloc_nid(sbi, &ino)) {
+               mutex_unlock_op(sbi, NODE_NEW);
+               err = -ENOSPC;
+               goto fail;
+       }
+       mutex_unlock_op(sbi, NODE_NEW);
+
+       inode->i_uid = current_fsuid();
+
+       if (dir->i_mode & S_ISGID) {
+               inode->i_gid = dir->i_gid;
+               if (S_ISDIR(mode))
+                       mode |= S_ISGID;
+       } else {
+               inode->i_gid = current_fsgid();
+       }
+
+       inode->i_ino = ino;
+       inode->i_mode = mode;
+       inode->i_blocks = 0;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+       inode->i_generation = sbi->s_next_generation++;
+
+       err = insert_inode_locked(inode);
+       if (err) {
+               err = -EINVAL;
+               nid_free = true;
+               goto out;
+       }
+
+       mark_inode_dirty(inode);
+       return inode;
+
+out:
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+fail:
+       iput(inode);
+       if (nid_free)
+               alloc_nid_failed(sbi, ino);
+       return ERR_PTR(err);
+}
+
+static int is_multimedia_file(const unsigned char *s, const char *sub)
+{
+       size_t slen = strlen(s);
+       size_t sublen = strlen(sub);
+       int ret;
+
+       if (sublen > slen)
+               return 1;
+
+       ret = memcmp(s + slen - sublen, sub, sublen);
+       if (ret) {      /* compare upper case */
+               int i;
+               char upper_sub[8];
+               for (i = 0; i < sublen && i < sizeof(upper_sub); i++)
+                       upper_sub[i] = toupper(sub[i]);
+               return memcmp(s + slen - sublen, upper_sub, sublen);
+       }
+
+       return ret;
+}
+
+/*
+ * Set multimedia files as cold files for hot/cold data separation
+ */
+static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
+               const unsigned char *name)
+{
+       int i;
+       __u8 (*extlist)[8] = sbi->raw_super->extension_list;
+
+       int count = le32_to_cpu(sbi->raw_super->extension_count);
+       for (i = 0; i < count; i++) {
+               if (!is_multimedia_file(name, extlist[i])) {
+                       F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
+                       break;
+               }
+       }
+}
+
+static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+                                               bool excl)
+{
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode;
+       nid_t ino = 0;
+       int err;
+
+       f2fs_balance_fs(sbi);
+
+       inode = f2fs_new_inode(dir, mode);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
+               set_cold_file(sbi, inode, dentry->d_name.name);
+
+       inode->i_op = &f2fs_file_inode_operations;
+       inode->i_fop = &f2fs_file_operations;
+       inode->i_mapping->a_ops = &f2fs_dblock_aops;
+       ino = inode->i_ino;
+
+       err = f2fs_add_link(dentry, inode);
+       if (err)
+               goto out;
+
+       alloc_nid_done(sbi, ino);
+
+       if (!sbi->por_doing)
+               d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
+       return 0;
+out:
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       alloc_nid_failed(sbi, ino);
+       return err;
+}
+
+static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
+               struct dentry *dentry)
+{
+       struct inode *inode = old_dentry->d_inode;
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       int err;
+
+       f2fs_balance_fs(sbi);
+
+       inode->i_ctime = CURRENT_TIME;
+       atomic_inc(&inode->i_count);
+
+       set_inode_flag(F2FS_I(inode), FI_INC_LINK);
+       err = f2fs_add_link(dentry, inode);
+       if (err)
+               goto out;
+
+       d_instantiate(dentry, inode);
+       return 0;
+out:
+       clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+       iput(inode);
+       return err;
+}
+
+struct dentry *f2fs_get_parent(struct dentry *child)
+{
+       struct qstr dotdot = QSTR_INIT("..", 2);
+       unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot);
+       if (!ino)
+               return ERR_PTR(-ENOENT);
+       return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
+}
+
+static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
+               unsigned int flags)
+{
+       struct inode *inode = NULL;
+       struct f2fs_dir_entry *de;
+       struct page *page;
+
+       if (dentry->d_name.len > F2FS_MAX_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       de = f2fs_find_entry(dir, &dentry->d_name, &page);
+       if (de) {
+               nid_t ino = le32_to_cpu(de->ino);
+               kunmap(page);
+               f2fs_put_page(page, 0);
+
+               inode = f2fs_iget(dir->i_sb, ino);
+               if (IS_ERR(inode))
+                       return ERR_CAST(inode);
+       }
+
+       return d_splice_alias(inode, dentry);
+}
+
+static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
+{
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode = dentry->d_inode;
+       struct f2fs_dir_entry *de;
+       struct page *page;
+       int err = -ENOENT;
+
+       f2fs_balance_fs(sbi);
+
+       de = f2fs_find_entry(dir, &dentry->d_name, &page);
+       if (!de)
+               goto fail;
+
+       err = check_orphan_space(sbi);
+       if (err) {
+               kunmap(page);
+               f2fs_put_page(page, 0);
+               goto fail;
+       }
+
+       f2fs_delete_entry(de, page, inode);
+
+       /* In order to evict this inode,  we set it dirty */
+       mark_inode_dirty(inode);
+fail:
+       return err;
+}
+
+static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
+                                       const char *symname)
+{
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode;
+       size_t symlen = strlen(symname) + 1;
+       int err;
+
+       f2fs_balance_fs(sbi);
+
+       inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       inode->i_op = &f2fs_symlink_inode_operations;
+       inode->i_mapping->a_ops = &f2fs_dblock_aops;
+
+       err = f2fs_add_link(dentry, inode);
+       if (err)
+               goto out;
+
+       err = page_symlink(inode, symname, symlen);
+       alloc_nid_done(sbi, inode->i_ino);
+
+       d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
+       return err;
+out:
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       alloc_nid_failed(sbi, inode->i_ino);
+       return err;
+}
+
+static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       struct inode *inode;
+       int err;
+
+       f2fs_balance_fs(sbi);
+
+       inode = f2fs_new_inode(dir, S_IFDIR | mode);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       inode->i_op = &f2fs_dir_inode_operations;
+       inode->i_fop = &f2fs_dir_operations;
+       inode->i_mapping->a_ops = &f2fs_dblock_aops;
+       mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+
+       set_inode_flag(F2FS_I(inode), FI_INC_LINK);
+       err = f2fs_add_link(dentry, inode);
+       if (err)
+               goto out_fail;
+
+       alloc_nid_done(sbi, inode->i_ino);
+
+       d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
+
+       return 0;
+
+out_fail:
+       clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       alloc_nid_failed(sbi, inode->i_ino);
+       return err;
+}
+
+static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       if (f2fs_empty_dir(inode))
+               return f2fs_unlink(dir, dentry);
+       return -ENOTEMPTY;
+}
+
+static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
+                               umode_t mode, dev_t rdev)
+{
+       struct super_block *sb = dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode;
+       int err = 0;
+
+       if (!new_valid_dev(rdev))
+               return -EINVAL;
+
+       f2fs_balance_fs(sbi);
+
+       inode = f2fs_new_inode(dir, mode);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       init_special_inode(inode, inode->i_mode, rdev);
+       inode->i_op = &f2fs_special_inode_operations;
+
+       err = f2fs_add_link(dentry, inode);
+       if (err)
+               goto out;
+
+       alloc_nid_done(sbi, inode->i_ino);
+       d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
+       return 0;
+out:
+       clear_nlink(inode);
+       unlock_new_inode(inode);
+       iput(inode);
+       alloc_nid_failed(sbi, inode->i_ino);
+       return err;
+}
+
+static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
+                       struct inode *new_dir, struct dentry *new_dentry)
+{
+       struct super_block *sb = old_dir->i_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *old_inode = old_dentry->d_inode;
+       struct inode *new_inode = new_dentry->d_inode;
+       struct page *old_dir_page;
+       struct page *old_page;
+       struct f2fs_dir_entry *old_dir_entry = NULL;
+       struct f2fs_dir_entry *old_entry;
+       struct f2fs_dir_entry *new_entry;
+       int err = -ENOENT;
+
+       f2fs_balance_fs(sbi);
+
+       old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
+       if (!old_entry)
+               goto out;
+
+       if (S_ISDIR(old_inode->i_mode)) {
+               err = -EIO;
+               old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page);
+               if (!old_dir_entry)
+                       goto out_old;
+       }
+
+       mutex_lock_op(sbi, RENAME);
+
+       if (new_inode) {
+               struct page *new_page;
+
+               err = -ENOTEMPTY;
+               if (old_dir_entry && !f2fs_empty_dir(new_inode))
+                       goto out_dir;
+
+               err = -ENOENT;
+               new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,
+                                               &new_page);
+               if (!new_entry)
+                       goto out_dir;
+
+               f2fs_set_link(new_dir, new_entry, new_page, old_inode);
+
+               new_inode->i_ctime = CURRENT_TIME;
+               if (old_dir_entry)
+                       drop_nlink(new_inode);
+               drop_nlink(new_inode);
+               if (!new_inode->i_nlink)
+                       add_orphan_inode(sbi, new_inode->i_ino);
+               f2fs_write_inode(new_inode, NULL);
+       } else {
+               err = f2fs_add_link(new_dentry, old_inode);
+               if (err)
+                       goto out_dir;
+
+               if (old_dir_entry) {
+                       inc_nlink(new_dir);
+                       f2fs_write_inode(new_dir, NULL);
+               }
+       }
+
+       old_inode->i_ctime = CURRENT_TIME;
+       set_inode_flag(F2FS_I(old_inode), FI_NEED_CP);
+       mark_inode_dirty(old_inode);
+
+       f2fs_delete_entry(old_entry, old_page, NULL);
+
+       if (old_dir_entry) {
+               if (old_dir != new_dir) {
+                       f2fs_set_link(old_inode, old_dir_entry,
+                                               old_dir_page, new_dir);
+               } else {
+                       kunmap(old_dir_page);
+                       f2fs_put_page(old_dir_page, 0);
+               }
+               drop_nlink(old_dir);
+               f2fs_write_inode(old_dir, NULL);
+       }
+
+       mutex_unlock_op(sbi, RENAME);
+       return 0;
+
+out_dir:
+       if (old_dir_entry) {
+               kunmap(old_dir_page);
+               f2fs_put_page(old_dir_page, 0);
+       }
+       mutex_unlock_op(sbi, RENAME);
+out_old:
+       kunmap(old_page);
+       f2fs_put_page(old_page, 0);
+out:
+       return err;
+}
+
+const struct inode_operations f2fs_dir_inode_operations = {
+       .create         = f2fs_create,
+       .lookup         = f2fs_lookup,
+       .link           = f2fs_link,
+       .unlink         = f2fs_unlink,
+       .symlink        = f2fs_symlink,
+       .mkdir          = f2fs_mkdir,
+       .rmdir          = f2fs_rmdir,
+       .mknod          = f2fs_mknod,
+       .rename         = f2fs_rename,
+       .setattr        = f2fs_setattr,
+       .get_acl        = f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = f2fs_listxattr,
+       .removexattr    = generic_removexattr,
+#endif
+};
+
+const struct inode_operations f2fs_symlink_inode_operations = {
+       .readlink       = generic_readlink,
+       .follow_link    = page_follow_link_light,
+       .put_link       = page_put_link,
+       .setattr        = f2fs_setattr,
+#ifdef CONFIG_F2FS_FS_XATTR
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = f2fs_listxattr,
+       .removexattr    = generic_removexattr,
+#endif
+};
+
+const struct inode_operations f2fs_special_inode_operations = {
+       .setattr        = f2fs_setattr,
+       .get_acl        = f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = f2fs_listxattr,
+       .removexattr    = generic_removexattr,
+#endif
+};
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
new file mode 100644 (file)
index 0000000..9bda63c
--- /dev/null
@@ -0,0 +1,1760 @@
+/*
+ * fs/f2fs/node.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/mpage.h>
+#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/pagevec.h>
+#include <linux/swap.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *nat_entry_slab;
+static struct kmem_cache *free_nid_slab;
+
+static void clear_node_page_dirty(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+       unsigned int long flags;
+
+       if (PageDirty(page)) {
+               spin_lock_irqsave(&mapping->tree_lock, flags);
+               radix_tree_tag_clear(&mapping->page_tree,
+                               page_index(page),
+                               PAGECACHE_TAG_DIRTY);
+               spin_unlock_irqrestore(&mapping->tree_lock, flags);
+
+               clear_page_dirty_for_io(page);
+               dec_page_count(sbi, F2FS_DIRTY_NODES);
+       }
+       ClearPageUptodate(page);
+}
+
+static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       pgoff_t index = current_nat_addr(sbi, nid);
+       return get_meta_page(sbi, index);
+}
+
+static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       struct page *src_page;
+       struct page *dst_page;
+       pgoff_t src_off;
+       pgoff_t dst_off;
+       void *src_addr;
+       void *dst_addr;
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+       src_off = current_nat_addr(sbi, nid);
+       dst_off = next_nat_addr(sbi, src_off);
+
+       /* get current nat block page with lock */
+       src_page = get_meta_page(sbi, src_off);
+
+       /* Dirty src_page means that it is already the new target NAT page. */
+       if (PageDirty(src_page))
+               return src_page;
+
+       dst_page = grab_meta_page(sbi, dst_off);
+
+       src_addr = page_address(src_page);
+       dst_addr = page_address(dst_page);
+       memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
+       set_page_dirty(dst_page);
+       f2fs_put_page(src_page, 1);
+
+       set_to_next_nat(nm_i, nid);
+
+       return dst_page;
+}
+
+/*
+ * Readahead NAT pages
+ */
+static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
+{
+       struct address_space *mapping = sbi->meta_inode->i_mapping;
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct page *page;
+       pgoff_t index;
+       int i;
+
+       for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
+               if (nid >= nm_i->max_nid)
+                       nid = 0;
+               index = current_nat_addr(sbi, nid);
+
+               page = grab_cache_page(mapping, index);
+               if (!page)
+                       continue;
+               if (f2fs_readpage(sbi, page, index, READ)) {
+                       f2fs_put_page(page, 1);
+                       continue;
+               }
+               page_cache_release(page);
+       }
+}
+
+static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
+{
+       return radix_tree_lookup(&nm_i->nat_root, n);
+}
+
+static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
+               nid_t start, unsigned int nr, struct nat_entry **ep)
+{
+       return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
+}
+
+static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
+{
+       list_del(&e->list);
+       radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
+       nm_i->nat_cnt--;
+       kmem_cache_free(nat_entry_slab, e);
+}
+
+int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct nat_entry *e;
+       int is_cp = 1;
+
+       read_lock(&nm_i->nat_tree_lock);
+       e = __lookup_nat_cache(nm_i, nid);
+       if (e && !e->checkpointed)
+               is_cp = 0;
+       read_unlock(&nm_i->nat_tree_lock);
+       return is_cp;
+}
+
+static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+       struct nat_entry *new;
+
+       new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC);
+       if (!new)
+               return NULL;
+       if (radix_tree_insert(&nm_i->nat_root, nid, new)) {
+               kmem_cache_free(nat_entry_slab, new);
+               return NULL;
+       }
+       memset(new, 0, sizeof(struct nat_entry));
+       nat_set_nid(new, nid);
+       list_add_tail(&new->list, &nm_i->nat_entries);
+       nm_i->nat_cnt++;
+       return new;
+}
+
+static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid,
+                                               struct f2fs_nat_entry *ne)
+{
+       struct nat_entry *e;
+retry:
+       write_lock(&nm_i->nat_tree_lock);
+       e = __lookup_nat_cache(nm_i, nid);
+       if (!e) {
+               e = grab_nat_entry(nm_i, nid);
+               if (!e) {
+                       write_unlock(&nm_i->nat_tree_lock);
+                       goto retry;
+               }
+               nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
+               nat_set_ino(e, le32_to_cpu(ne->ino));
+               nat_set_version(e, ne->version);
+               e->checkpointed = true;
+       }
+       write_unlock(&nm_i->nat_tree_lock);
+}
+
+static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
+                       block_t new_blkaddr)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct nat_entry *e;
+retry:
+       write_lock(&nm_i->nat_tree_lock);
+       e = __lookup_nat_cache(nm_i, ni->nid);
+       if (!e) {
+               e = grab_nat_entry(nm_i, ni->nid);
+               if (!e) {
+                       write_unlock(&nm_i->nat_tree_lock);
+                       goto retry;
+               }
+               e->ni = *ni;
+               e->checkpointed = true;
+               BUG_ON(ni->blk_addr == NEW_ADDR);
+       } else if (new_blkaddr == NEW_ADDR) {
+               /*
+                * when nid is reallocated,
+                * previous nat entry can be remained in nat cache.
+                * So, reinitialize it with new information.
+                */
+               e->ni = *ni;
+               BUG_ON(ni->blk_addr != NULL_ADDR);
+       }
+
+       if (new_blkaddr == NEW_ADDR)
+               e->checkpointed = false;
+
+       /* sanity check */
+       BUG_ON(nat_get_blkaddr(e) != ni->blk_addr);
+       BUG_ON(nat_get_blkaddr(e) == NULL_ADDR &&
+                       new_blkaddr == NULL_ADDR);
+       BUG_ON(nat_get_blkaddr(e) == NEW_ADDR &&
+                       new_blkaddr == NEW_ADDR);
+       BUG_ON(nat_get_blkaddr(e) != NEW_ADDR &&
+                       nat_get_blkaddr(e) != NULL_ADDR &&
+                       new_blkaddr == NEW_ADDR);
+
+       /* increament version no as node is removed */
+       if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
+               unsigned char version = nat_get_version(e);
+               nat_set_version(e, inc_node_version(version));
+       }
+
+       /* change address */
+       nat_set_blkaddr(e, new_blkaddr);
+       __set_nat_cache_dirty(nm_i, e);
+       write_unlock(&nm_i->nat_tree_lock);
+}
+
+static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+       if (nm_i->nat_cnt < 2 * NM_WOUT_THRESHOLD)
+               return 0;
+
+       write_lock(&nm_i->nat_tree_lock);
+       while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
+               struct nat_entry *ne;
+               ne = list_first_entry(&nm_i->nat_entries,
+                                       struct nat_entry, list);
+               __del_from_nat_cache(nm_i, ne);
+               nr_shrink--;
+       }
+       write_unlock(&nm_i->nat_tree_lock);
+       return nr_shrink;
+}
+
+/*
+ * This function returns always success
+ */
+void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       nid_t start_nid = START_NID(nid);
+       struct f2fs_nat_block *nat_blk;
+       struct page *page = NULL;
+       struct f2fs_nat_entry ne;
+       struct nat_entry *e;
+       int i;
+
+       memset(&ne, 0, sizeof(struct f2fs_nat_entry));
+       ni->nid = nid;
+
+       /* Check nat cache */
+       read_lock(&nm_i->nat_tree_lock);
+       e = __lookup_nat_cache(nm_i, nid);
+       if (e) {
+               ni->ino = nat_get_ino(e);
+               ni->blk_addr = nat_get_blkaddr(e);
+               ni->version = nat_get_version(e);
+       }
+       read_unlock(&nm_i->nat_tree_lock);
+       if (e)
+               return;
+
+       /* Check current segment summary */
+       mutex_lock(&curseg->curseg_mutex);
+       i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
+       if (i >= 0) {
+               ne = nat_in_journal(sum, i);
+               node_info_from_raw_nat(ni, &ne);
+       }
+       mutex_unlock(&curseg->curseg_mutex);
+       if (i >= 0)
+               goto cache;
+
+       /* Fill node_info from nat page */
+       page = get_current_nat_page(sbi, start_nid);
+       nat_blk = (struct f2fs_nat_block *)page_address(page);
+       ne = nat_blk->entries[nid - start_nid];
+       node_info_from_raw_nat(ni, &ne);
+       f2fs_put_page(page, 1);
+cache:
+       /* cache nat entry */
+       cache_nat_entry(NM_I(sbi), nid, &ne);
+}
+
+/*
+ * The maximum depth is four.
+ * Offset[0] will have raw inode offset.
+ */
+static int get_node_path(long block, int offset[4], unsigned int noffset[4])
+{
+       const long direct_index = ADDRS_PER_INODE;
+       const long direct_blks = ADDRS_PER_BLOCK;
+       const long dptrs_per_blk = NIDS_PER_BLOCK;
+       const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+       const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+       int n = 0;
+       int level = 0;
+
+       noffset[0] = 0;
+
+       if (block < direct_index) {
+               offset[n++] = block;
+               level = 0;
+               goto got;
+       }
+       block -= direct_index;
+       if (block < direct_blks) {
+               offset[n++] = NODE_DIR1_BLOCK;
+               noffset[n] = 1;
+               offset[n++] = block;
+               level = 1;
+               goto got;
+       }
+       block -= direct_blks;
+       if (block < direct_blks) {
+               offset[n++] = NODE_DIR2_BLOCK;
+               noffset[n] = 2;
+               offset[n++] = block;
+               level = 1;
+               goto got;
+       }
+       block -= direct_blks;
+       if (block < indirect_blks) {
+               offset[n++] = NODE_IND1_BLOCK;
+               noffset[n] = 3;
+               offset[n++] = block / direct_blks;
+               noffset[n] = 4 + offset[n - 1];
+               offset[n++] = block % direct_blks;
+               level = 2;
+               goto got;
+       }
+       block -= indirect_blks;
+       if (block < indirect_blks) {
+               offset[n++] = NODE_IND2_BLOCK;
+               noffset[n] = 4 + dptrs_per_blk;
+               offset[n++] = block / direct_blks;
+               noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
+               offset[n++] = block % direct_blks;
+               level = 2;
+               goto got;
+       }
+       block -= indirect_blks;
+       if (block < dindirect_blks) {
+               offset[n++] = NODE_DIND_BLOCK;
+               noffset[n] = 5 + (dptrs_per_blk * 2);
+               offset[n++] = block / indirect_blks;
+               noffset[n] = 6 + (dptrs_per_blk * 2) +
+                             offset[n - 1] * (dptrs_per_blk + 1);
+               offset[n++] = (block / direct_blks) % dptrs_per_blk;
+               noffset[n] = 7 + (dptrs_per_blk * 2) +
+                             offset[n - 2] * (dptrs_per_blk + 1) +
+                             offset[n - 1];
+               offset[n++] = block % direct_blks;
+               level = 3;
+               goto got;
+       } else {
+               BUG();
+       }
+got:
+       return level;
+}
+
+/*
+ * Caller should call f2fs_put_dnode(dn).
+ */
+int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct page *npage[4];
+       struct page *parent;
+       int offset[4];
+       unsigned int noffset[4];
+       nid_t nids[4];
+       int level, i;
+       int err = 0;
+
+       level = get_node_path(index, offset, noffset);
+
+       nids[0] = dn->inode->i_ino;
+       npage[0] = get_node_page(sbi, nids[0]);
+       if (IS_ERR(npage[0]))
+               return PTR_ERR(npage[0]);
+
+       parent = npage[0];
+       nids[1] = get_nid(parent, offset[0], true);
+       dn->inode_page = npage[0];
+       dn->inode_page_locked = true;
+
+       /* get indirect or direct nodes */
+       for (i = 1; i <= level; i++) {
+               bool done = false;
+
+               if (!nids[i] && !ro) {
+                       mutex_lock_op(sbi, NODE_NEW);
+
+                       /* alloc new node */
+                       if (!alloc_nid(sbi, &(nids[i]))) {
+                               mutex_unlock_op(sbi, NODE_NEW);
+                               err = -ENOSPC;
+                               goto release_pages;
+                       }
+
+                       dn->nid = nids[i];
+                       npage[i] = new_node_page(dn, noffset[i]);
+                       if (IS_ERR(npage[i])) {
+                               alloc_nid_failed(sbi, nids[i]);
+                               mutex_unlock_op(sbi, NODE_NEW);
+                               err = PTR_ERR(npage[i]);
+                               goto release_pages;
+                       }
+
+                       set_nid(parent, offset[i - 1], nids[i], i == 1);
+                       alloc_nid_done(sbi, nids[i]);
+                       mutex_unlock_op(sbi, NODE_NEW);
+                       done = true;
+               } else if (ro && i == level && level > 1) {
+                       npage[i] = get_node_page_ra(parent, offset[i - 1]);
+                       if (IS_ERR(npage[i])) {
+                               err = PTR_ERR(npage[i]);
+                               goto release_pages;
+                       }
+                       done = true;
+               }
+               if (i == 1) {
+                       dn->inode_page_locked = false;
+                       unlock_page(parent);
+               } else {
+                       f2fs_put_page(parent, 1);
+               }
+
+               if (!done) {
+                       npage[i] = get_node_page(sbi, nids[i]);
+                       if (IS_ERR(npage[i])) {
+                               err = PTR_ERR(npage[i]);
+                               f2fs_put_page(npage[0], 0);
+                               goto release_out;
+                       }
+               }
+               if (i < level) {
+                       parent = npage[i];
+                       nids[i + 1] = get_nid(parent, offset[i], false);
+               }
+       }
+       dn->nid = nids[level];
+       dn->ofs_in_node = offset[level];
+       dn->node_page = npage[level];
+       dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
+       return 0;
+
+release_pages:
+       f2fs_put_page(parent, 1);
+       if (i > 1)
+               f2fs_put_page(npage[0], 0);
+release_out:
+       dn->inode_page = NULL;
+       dn->node_page = NULL;
+       return err;
+}
+
+static void truncate_node(struct dnode_of_data *dn)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct node_info ni;
+
+       get_node_info(sbi, dn->nid, &ni);
+       if (dn->inode->i_blocks == 0) {
+               BUG_ON(ni.blk_addr != NULL_ADDR);
+               goto invalidate;
+       }
+       BUG_ON(ni.blk_addr == NULL_ADDR);
+
+       /* Deallocate node address */
+       invalidate_blocks(sbi, ni.blk_addr);
+       dec_valid_node_count(sbi, dn->inode, 1);
+       set_node_addr(sbi, &ni, NULL_ADDR);
+
+       if (dn->nid == dn->inode->i_ino) {
+               remove_orphan_inode(sbi, dn->nid);
+               dec_valid_inode_count(sbi);
+       } else {
+               sync_inode_page(dn);
+       }
+invalidate:
+       clear_node_page_dirty(dn->node_page);
+       F2FS_SET_SB_DIRT(sbi);
+
+       f2fs_put_page(dn->node_page, 1);
+       dn->node_page = NULL;
+}
+
+static int truncate_dnode(struct dnode_of_data *dn)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct page *page;
+
+       if (dn->nid == 0)
+               return 1;
+
+       /* get direct node */
+       page = get_node_page(sbi, dn->nid);
+       if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
+               return 1;
+       else if (IS_ERR(page))
+               return PTR_ERR(page);
+
+       /* Make dnode_of_data for parameter */
+       dn->node_page = page;
+       dn->ofs_in_node = 0;
+       truncate_data_blocks(dn);
+       truncate_node(dn);
+       return 1;
+}
+
+static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
+                                               int ofs, int depth)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct dnode_of_data rdn = *dn;
+       struct page *page;
+       struct f2fs_node *rn;
+       nid_t child_nid;
+       unsigned int child_nofs;
+       int freed = 0;
+       int i, ret;
+
+       if (dn->nid == 0)
+               return NIDS_PER_BLOCK + 1;
+
+       page = get_node_page(sbi, dn->nid);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+
+       rn = (struct f2fs_node *)page_address(page);
+       if (depth < 3) {
+               for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
+                       child_nid = le32_to_cpu(rn->in.nid[i]);
+                       if (child_nid == 0)
+                               continue;
+                       rdn.nid = child_nid;
+                       ret = truncate_dnode(&rdn);
+                       if (ret < 0)
+                               goto out_err;
+                       set_nid(page, i, 0, false);
+               }
+       } else {
+               child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
+               for (i = ofs; i < NIDS_PER_BLOCK; i++) {
+                       child_nid = le32_to_cpu(rn->in.nid[i]);
+                       if (child_nid == 0) {
+                               child_nofs += NIDS_PER_BLOCK + 1;
+                               continue;
+                       }
+                       rdn.nid = child_nid;
+                       ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
+                       if (ret == (NIDS_PER_BLOCK + 1)) {
+                               set_nid(page, i, 0, false);
+                               child_nofs += ret;
+                       } else if (ret < 0 && ret != -ENOENT) {
+                               goto out_err;
+                       }
+               }
+               freed = child_nofs;
+       }
+
+       if (!ofs) {
+               /* remove current indirect node */
+               dn->node_page = page;
+               truncate_node(dn);
+               freed++;
+       } else {
+               f2fs_put_page(page, 1);
+       }
+       return freed;
+
+out_err:
+       f2fs_put_page(page, 1);
+       return ret;
+}
+
+static int truncate_partial_nodes(struct dnode_of_data *dn,
+                       struct f2fs_inode *ri, int *offset, int depth)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct page *pages[2];
+       nid_t nid[3];
+       nid_t child_nid;
+       int err = 0;
+       int i;
+       int idx = depth - 2;
+
+       nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
+       if (!nid[0])
+               return 0;
+
+       /* get indirect nodes in the path */
+       for (i = 0; i < depth - 1; i++) {
+               /* refernece count'll be increased */
+               pages[i] = get_node_page(sbi, nid[i]);
+               if (IS_ERR(pages[i])) {
+                       depth = i + 1;
+                       err = PTR_ERR(pages[i]);
+                       goto fail;
+               }
+               nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
+       }
+
+       /* free direct nodes linked to a partial indirect node */
+       for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) {
+               child_nid = get_nid(pages[idx], i, false);
+               if (!child_nid)
+                       continue;
+               dn->nid = child_nid;
+               err = truncate_dnode(dn);
+               if (err < 0)
+                       goto fail;
+               set_nid(pages[idx], i, 0, false);
+       }
+
+       if (offset[depth - 1] == 0) {
+               dn->node_page = pages[idx];
+               dn->nid = nid[idx];
+               truncate_node(dn);
+       } else {
+               f2fs_put_page(pages[idx], 1);
+       }
+       offset[idx]++;
+       offset[depth - 1] = 0;
+fail:
+       for (i = depth - 3; i >= 0; i--)
+               f2fs_put_page(pages[i], 1);
+       return err;
+}
+
+/*
+ * All the block addresses of data and nodes should be nullified.
+ */
+int truncate_inode_blocks(struct inode *inode, pgoff_t from)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       int err = 0, cont = 1;
+       int level, offset[4], noffset[4];
+       unsigned int nofs;
+       struct f2fs_node *rn;
+       struct dnode_of_data dn;
+       struct page *page;
+
+       level = get_node_path(from, offset, noffset);
+
+       page = get_node_page(sbi, inode->i_ino);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+
+       set_new_dnode(&dn, inode, page, NULL, 0);
+       unlock_page(page);
+
+       rn = page_address(page);
+       switch (level) {
+       case 0:
+       case 1:
+               nofs = noffset[1];
+               break;
+       case 2:
+               nofs = noffset[1];
+               if (!offset[level - 1])
+                       goto skip_partial;
+               err = truncate_partial_nodes(&dn, &rn->i, offset, level);
+               if (err < 0 && err != -ENOENT)
+                       goto fail;
+               nofs += 1 + NIDS_PER_BLOCK;
+               break;
+       case 3:
+               nofs = 5 + 2 * NIDS_PER_BLOCK;
+               if (!offset[level - 1])
+                       goto skip_partial;
+               err = truncate_partial_nodes(&dn, &rn->i, offset, level);
+               if (err < 0 && err != -ENOENT)
+                       goto fail;
+               break;
+       default:
+               BUG();
+       }
+
+skip_partial:
+       while (cont) {
+               dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
+               switch (offset[0]) {
+               case NODE_DIR1_BLOCK:
+               case NODE_DIR2_BLOCK:
+                       err = truncate_dnode(&dn);
+                       break;
+
+               case NODE_IND1_BLOCK:
+               case NODE_IND2_BLOCK:
+                       err = truncate_nodes(&dn, nofs, offset[1], 2);
+                       break;
+
+               case NODE_DIND_BLOCK:
+                       err = truncate_nodes(&dn, nofs, offset[1], 3);
+                       cont = 0;
+                       break;
+
+               default:
+                       BUG();
+               }
+               if (err < 0 && err != -ENOENT)
+                       goto fail;
+               if (offset[1] == 0 &&
+                               rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) {
+                       lock_page(page);
+                       wait_on_page_writeback(page);
+                       rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
+                       set_page_dirty(page);
+                       unlock_page(page);
+               }
+               offset[1] = 0;
+               offset[0]++;
+               nofs += err;
+       }
+fail:
+       f2fs_put_page(page, 0);
+       return err > 0 ? 0 : err;
+}
+
+int remove_inode_page(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct page *page;
+       nid_t ino = inode->i_ino;
+       struct dnode_of_data dn;
+
+       mutex_lock_op(sbi, NODE_TRUNC);
+       page = get_node_page(sbi, ino);
+       if (IS_ERR(page)) {
+               mutex_unlock_op(sbi, NODE_TRUNC);
+               return PTR_ERR(page);
+       }
+
+       if (F2FS_I(inode)->i_xattr_nid) {
+               nid_t nid = F2FS_I(inode)->i_xattr_nid;
+               struct page *npage = get_node_page(sbi, nid);
+
+               if (IS_ERR(npage)) {
+                       mutex_unlock_op(sbi, NODE_TRUNC);
+                       return PTR_ERR(npage);
+               }
+
+               F2FS_I(inode)->i_xattr_nid = 0;
+               set_new_dnode(&dn, inode, page, npage, nid);
+               dn.inode_page_locked = 1;
+               truncate_node(&dn);
+       }
+
+       /* 0 is possible, after f2fs_new_inode() is failed */
+       BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1);
+       set_new_dnode(&dn, inode, page, page, ino);
+       truncate_node(&dn);
+
+       mutex_unlock_op(sbi, NODE_TRUNC);
+       return 0;
+}
+
+int new_inode_page(struct inode *inode, struct dentry *dentry)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct page *page;
+       struct dnode_of_data dn;
+
+       /* allocate inode page for new inode */
+       set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
+       mutex_lock_op(sbi, NODE_NEW);
+       page = new_node_page(&dn, 0);
+       init_dent_inode(dentry, page);
+       mutex_unlock_op(sbi, NODE_NEW);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+       f2fs_put_page(page, 1);
+       return 0;
+}
+
+struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+       struct node_info old_ni, new_ni;
+       struct page *page;
+       int err;
+
+       if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+               return ERR_PTR(-EPERM);
+
+       page = grab_cache_page(mapping, dn->nid);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       get_node_info(sbi, dn->nid, &old_ni);
+
+       SetPageUptodate(page);
+       fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
+
+       /* Reinitialize old_ni with new node page */
+       BUG_ON(old_ni.blk_addr != NULL_ADDR);
+       new_ni = old_ni;
+       new_ni.ino = dn->inode->i_ino;
+
+       if (!inc_valid_node_count(sbi, dn->inode, 1)) {
+               err = -ENOSPC;
+               goto fail;
+       }
+       set_node_addr(sbi, &new_ni, NEW_ADDR);
+       set_cold_node(dn->inode, page);
+
+       dn->node_page = page;
+       sync_inode_page(dn);
+       set_page_dirty(page);
+       if (ofs == 0)
+               inc_valid_inode_count(sbi);
+
+       return page;
+
+fail:
+       clear_node_page_dirty(page);
+       f2fs_put_page(page, 1);
+       return ERR_PTR(err);
+}
+
+static int read_node_page(struct page *page, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+       struct node_info ni;
+
+       get_node_info(sbi, page->index, &ni);
+
+       if (ni.blk_addr == NULL_ADDR)
+               return -ENOENT;
+       return f2fs_readpage(sbi, page, ni.blk_addr, type);
+}
+
+/*
+ * Readahead a node page
+ */
+void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+       struct page *apage;
+
+       apage = find_get_page(mapping, nid);
+       if (apage && PageUptodate(apage))
+               goto release_out;
+       f2fs_put_page(apage, 0);
+
+       apage = grab_cache_page(mapping, nid);
+       if (!apage)
+               return;
+
+       if (read_node_page(apage, READA))
+               goto unlock_out;
+
+       page_cache_release(apage);
+       return;
+
+unlock_out:
+       unlock_page(apage);
+release_out:
+       page_cache_release(apage);
+}
+
+struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
+{
+       int err;
+       struct page *page;
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+
+       page = grab_cache_page(mapping, nid);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       err = read_node_page(page, READ_SYNC);
+       if (err) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(err);
+       }
+
+       BUG_ON(nid != nid_of_node(page));
+       mark_page_accessed(page);
+       return page;
+}
+
+/*
+ * Return a locked page for the desired node page.
+ * And, readahead MAX_RA_NODE number of node pages.
+ */
+struct page *get_node_page_ra(struct page *parent, int start)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+       int i, end;
+       int err = 0;
+       nid_t nid;
+       struct page *page;
+
+       /* First, try getting the desired direct node. */
+       nid = get_nid(parent, start, false);
+       if (!nid)
+               return ERR_PTR(-ENOENT);
+
+       page = find_get_page(mapping, nid);
+       if (page && PageUptodate(page))
+               goto page_hit;
+       f2fs_put_page(page, 0);
+
+repeat:
+       page = grab_cache_page(mapping, nid);
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       err = read_node_page(page, READA);
+       if (err) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(err);
+       }
+
+       /* Then, try readahead for siblings of the desired node */
+       end = start + MAX_RA_NODE;
+       end = min(end, NIDS_PER_BLOCK);
+       for (i = start + 1; i < end; i++) {
+               nid = get_nid(parent, i, false);
+               if (!nid)
+                       continue;
+               ra_node_page(sbi, nid);
+       }
+
+page_hit:
+       lock_page(page);
+       if (PageError(page)) {
+               f2fs_put_page(page, 1);
+               return ERR_PTR(-EIO);
+       }
+
+       /* Has the page been truncated? */
+       if (page->mapping != mapping) {
+               f2fs_put_page(page, 1);
+               goto repeat;
+       }
+       return page;
+}
+
+void sync_inode_page(struct dnode_of_data *dn)
+{
+       if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
+               update_inode(dn->inode, dn->node_page);
+       } else if (dn->inode_page) {
+               if (!dn->inode_page_locked)
+                       lock_page(dn->inode_page);
+               update_inode(dn->inode, dn->inode_page);
+               if (!dn->inode_page_locked)
+                       unlock_page(dn->inode_page);
+       } else {
+               f2fs_write_inode(dn->inode, NULL);
+       }
+}
+
+int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
+                                       struct writeback_control *wbc)
+{
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+       pgoff_t index, end;
+       struct pagevec pvec;
+       int step = ino ? 2 : 0;
+       int nwritten = 0, wrote = 0;
+
+       pagevec_init(&pvec, 0);
+
+next_step:
+       index = 0;
+       end = LONG_MAX;
+
+       while (index <= end) {
+               int i, nr_pages;
+               nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+                               PAGECACHE_TAG_DIRTY,
+                               min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+               if (nr_pages == 0)
+                       break;
+
+               for (i = 0; i < nr_pages; i++) {
+                       struct page *page = pvec.pages[i];
+
+                       /*
+                        * flushing sequence with step:
+                        * 0. indirect nodes
+                        * 1. dentry dnodes
+                        * 2. file dnodes
+                        */
+                       if (step == 0 && IS_DNODE(page))
+                               continue;
+                       if (step == 1 && (!IS_DNODE(page) ||
+                                               is_cold_node(page)))
+                               continue;
+                       if (step == 2 && (!IS_DNODE(page) ||
+                                               !is_cold_node(page)))
+                               continue;
+
+                       /*
+                        * If an fsync mode,
+                        * we should not skip writing node pages.
+                        */
+                       if (ino && ino_of_node(page) == ino)
+                               lock_page(page);
+                       else if (!trylock_page(page))
+                               continue;
+
+                       if (unlikely(page->mapping != mapping)) {
+continue_unlock:
+                               unlock_page(page);
+                               continue;
+                       }
+                       if (ino && ino_of_node(page) != ino)
+                               goto continue_unlock;
+
+                       if (!PageDirty(page)) {
+                               /* someone wrote it for us */
+                               goto continue_unlock;
+                       }
+
+                       if (!clear_page_dirty_for_io(page))
+                               goto continue_unlock;
+
+                       /* called by fsync() */
+                       if (ino && IS_DNODE(page)) {
+                               int mark = !is_checkpointed_node(sbi, ino);
+                               set_fsync_mark(page, 1);
+                               if (IS_INODE(page))
+                                       set_dentry_mark(page, mark);
+                               nwritten++;
+                       } else {
+                               set_fsync_mark(page, 0);
+                               set_dentry_mark(page, 0);
+                       }
+                       mapping->a_ops->writepage(page, wbc);
+                       wrote++;
+
+                       if (--wbc->nr_to_write == 0)
+                               break;
+               }
+               pagevec_release(&pvec);
+               cond_resched();
+
+               if (wbc->nr_to_write == 0) {
+                       step = 2;
+                       break;
+               }
+       }
+
+       if (step < 2) {
+               step++;
+               goto next_step;
+       }
+
+       if (wrote)
+               f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL);
+
+       return nwritten;
+}
+
+static int f2fs_write_node_page(struct page *page,
+                               struct writeback_control *wbc)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+       nid_t nid;
+       block_t new_addr;
+       struct node_info ni;
+
+       if (wbc->for_reclaim) {
+               dec_page_count(sbi, F2FS_DIRTY_NODES);
+               wbc->pages_skipped++;
+               set_page_dirty(page);
+               return AOP_WRITEPAGE_ACTIVATE;
+       }
+
+       wait_on_page_writeback(page);
+
+       mutex_lock_op(sbi, NODE_WRITE);
+
+       /* get old block addr of this node page */
+       nid = nid_of_node(page);
+       BUG_ON(page->index != nid);
+
+       get_node_info(sbi, nid, &ni);
+
+       /* This page is already truncated */
+       if (ni.blk_addr == NULL_ADDR)
+               return 0;
+
+       set_page_writeback(page);
+
+       /* insert node offset */
+       write_node_page(sbi, page, nid, ni.blk_addr, &new_addr);
+       set_node_addr(sbi, &ni, new_addr);
+       dec_page_count(sbi, F2FS_DIRTY_NODES);
+
+       mutex_unlock_op(sbi, NODE_WRITE);
+       unlock_page(page);
+       return 0;
+}
+
+/*
+ * It is very important to gather dirty pages and write at once, so that we can
+ * submit a big bio without interfering other data writes.
+ * Be default, 512 pages (2MB), a segment size, is quite reasonable.
+ */
+#define COLLECT_DIRTY_NODES    512
+static int f2fs_write_node_pages(struct address_space *mapping,
+                           struct writeback_control *wbc)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+       struct block_device *bdev = sbi->sb->s_bdev;
+       long nr_to_write = wbc->nr_to_write;
+
+       /* First check balancing cached NAT entries */
+       if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
+               write_checkpoint(sbi, false, false);
+               return 0;
+       }
+
+       /* collect a number of dirty node pages and write together */
+       if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
+               return 0;
+
+       /* if mounting is failed, skip writing node pages */
+       wbc->nr_to_write = bio_get_nr_vecs(bdev);
+       sync_node_pages(sbi, 0, wbc);
+       wbc->nr_to_write = nr_to_write -
+               (bio_get_nr_vecs(bdev) - wbc->nr_to_write);
+       return 0;
+}
+
+static int f2fs_set_node_page_dirty(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+
+       SetPageUptodate(page);
+       if (!PageDirty(page)) {
+               __set_page_dirty_nobuffers(page);
+               inc_page_count(sbi, F2FS_DIRTY_NODES);
+               SetPagePrivate(page);
+               return 1;
+       }
+       return 0;
+}
+
+static void f2fs_invalidate_node_page(struct page *page, unsigned long offset)
+{
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       if (PageDirty(page))
+               dec_page_count(sbi, F2FS_DIRTY_NODES);
+       ClearPagePrivate(page);
+}
+
+static int f2fs_release_node_page(struct page *page, gfp_t wait)
+{
+       ClearPagePrivate(page);
+       return 0;
+}
+
+/*
+ * Structure of the f2fs node operations
+ */
+const struct address_space_operations f2fs_node_aops = {
+       .writepage      = f2fs_write_node_page,
+       .writepages     = f2fs_write_node_pages,
+       .set_page_dirty = f2fs_set_node_page_dirty,
+       .invalidatepage = f2fs_invalidate_node_page,
+       .releasepage    = f2fs_release_node_page,
+};
+
+static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
+{
+       struct list_head *this;
+       struct free_nid *i = NULL;
+       list_for_each(this, head) {
+               i = list_entry(this, struct free_nid, list);
+               if (i->nid == n)
+                       break;
+               i = NULL;
+       }
+       return i;
+}
+
+static void __del_from_free_nid_list(struct free_nid *i)
+{
+       list_del(&i->list);
+       kmem_cache_free(free_nid_slab, i);
+}
+
+static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+       struct free_nid *i;
+
+       if (nm_i->fcnt > 2 * MAX_FREE_NIDS)
+               return 0;
+retry:
+       i = kmem_cache_alloc(free_nid_slab, GFP_NOFS);
+       if (!i) {
+               cond_resched();
+               goto retry;
+       }
+       i->nid = nid;
+       i->state = NID_NEW;
+
+       spin_lock(&nm_i->free_nid_list_lock);
+       if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
+               spin_unlock(&nm_i->free_nid_list_lock);
+               kmem_cache_free(free_nid_slab, i);
+               return 0;
+       }
+       list_add_tail(&i->list, &nm_i->free_nid_list);
+       nm_i->fcnt++;
+       spin_unlock(&nm_i->free_nid_list_lock);
+       return 1;
+}
+
+static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+       struct free_nid *i;
+       spin_lock(&nm_i->free_nid_list_lock);
+       i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+       if (i && i->state == NID_NEW) {
+               __del_from_free_nid_list(i);
+               nm_i->fcnt--;
+       }
+       spin_unlock(&nm_i->free_nid_list_lock);
+}
+
+static int scan_nat_page(struct f2fs_nm_info *nm_i,
+                       struct page *nat_page, nid_t start_nid)
+{
+       struct f2fs_nat_block *nat_blk = page_address(nat_page);
+       block_t blk_addr;
+       int fcnt = 0;
+       int i;
+
+       /* 0 nid should not be used */
+       if (start_nid == 0)
+               ++start_nid;
+
+       i = start_nid % NAT_ENTRY_PER_BLOCK;
+
+       for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
+               blk_addr  = le32_to_cpu(nat_blk->entries[i].block_addr);
+               BUG_ON(blk_addr == NEW_ADDR);
+               if (blk_addr == NULL_ADDR)
+                       fcnt += add_free_nid(nm_i, start_nid);
+       }
+       return fcnt;
+}
+
+static void build_free_nids(struct f2fs_sb_info *sbi)
+{
+       struct free_nid *fnid, *next_fnid;
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       nid_t nid = 0;
+       bool is_cycled = false;
+       int fcnt = 0;
+       int i;
+
+       nid = nm_i->next_scan_nid;
+       nm_i->init_scan_nid = nid;
+
+       ra_nat_pages(sbi, nid);
+
+       while (1) {
+               struct page *page = get_current_nat_page(sbi, nid);
+
+               fcnt += scan_nat_page(nm_i, page, nid);
+               f2fs_put_page(page, 1);
+
+               nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
+
+               if (nid >= nm_i->max_nid) {
+                       nid = 0;
+                       is_cycled = true;
+               }
+               if (fcnt > MAX_FREE_NIDS)
+                       break;
+               if (is_cycled && nm_i->init_scan_nid <= nid)
+                       break;
+       }
+
+       nm_i->next_scan_nid = nid;
+
+       /* find free nids from current sum_pages */
+       mutex_lock(&curseg->curseg_mutex);
+       for (i = 0; i < nats_in_cursum(sum); i++) {
+               block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr);
+               nid = le32_to_cpu(nid_in_journal(sum, i));
+               if (addr == NULL_ADDR)
+                       add_free_nid(nm_i, nid);
+               else
+                       remove_free_nid(nm_i, nid);
+       }
+       mutex_unlock(&curseg->curseg_mutex);
+
+       /* remove the free nids from current allocated nids */
+       list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) {
+               struct nat_entry *ne;
+
+               read_lock(&nm_i->nat_tree_lock);
+               ne = __lookup_nat_cache(nm_i, fnid->nid);
+               if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
+                       remove_free_nid(nm_i, fnid->nid);
+               read_unlock(&nm_i->nat_tree_lock);
+       }
+}
+
+/*
+ * If this function returns success, caller can obtain a new nid
+ * from second parameter of this function.
+ * The returned nid could be used ino as well as nid when inode is created.
+ */
+bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct free_nid *i = NULL;
+       struct list_head *this;
+retry:
+       mutex_lock(&nm_i->build_lock);
+       if (!nm_i->fcnt) {
+               /* scan NAT in order to build free nid list */
+               build_free_nids(sbi);
+               if (!nm_i->fcnt) {
+                       mutex_unlock(&nm_i->build_lock);
+                       return false;
+               }
+       }
+       mutex_unlock(&nm_i->build_lock);
+
+       /*
+        * We check fcnt again since previous check is racy as
+        * we didn't hold free_nid_list_lock. So other thread
+        * could consume all of free nids.
+        */
+       spin_lock(&nm_i->free_nid_list_lock);
+       if (!nm_i->fcnt) {
+               spin_unlock(&nm_i->free_nid_list_lock);
+               goto retry;
+       }
+
+       BUG_ON(list_empty(&nm_i->free_nid_list));
+       list_for_each(this, &nm_i->free_nid_list) {
+               i = list_entry(this, struct free_nid, list);
+               if (i->state == NID_NEW)
+                       break;
+       }
+
+       BUG_ON(i->state != NID_NEW);
+       *nid = i->nid;
+       i->state = NID_ALLOC;
+       nm_i->fcnt--;
+       spin_unlock(&nm_i->free_nid_list_lock);
+       return true;
+}
+
+/*
+ * alloc_nid() should be called prior to this function.
+ */
+void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct free_nid *i;
+
+       spin_lock(&nm_i->free_nid_list_lock);
+       i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+       if (i) {
+               BUG_ON(i->state != NID_ALLOC);
+               __del_from_free_nid_list(i);
+       }
+       spin_unlock(&nm_i->free_nid_list_lock);
+}
+
+/*
+ * alloc_nid() should be called prior to this function.
+ */
+void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
+{
+       alloc_nid_done(sbi, nid);
+       add_free_nid(NM_I(sbi), nid);
+}
+
+void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
+               struct f2fs_summary *sum, struct node_info *ni,
+               block_t new_blkaddr)
+{
+       rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
+       set_node_addr(sbi, ni, new_blkaddr);
+       clear_node_page_dirty(page);
+}
+
+int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
+{
+       struct address_space *mapping = sbi->node_inode->i_mapping;
+       struct f2fs_node *src, *dst;
+       nid_t ino = ino_of_node(page);
+       struct node_info old_ni, new_ni;
+       struct page *ipage;
+
+       ipage = grab_cache_page(mapping, ino);
+       if (!ipage)
+               return -ENOMEM;
+
+       /* Should not use this inode  from free nid list */
+       remove_free_nid(NM_I(sbi), ino);
+
+       get_node_info(sbi, ino, &old_ni);
+       SetPageUptodate(ipage);
+       fill_node_footer(ipage, ino, ino, 0, true);
+
+       src = (struct f2fs_node *)page_address(page);
+       dst = (struct f2fs_node *)page_address(ipage);
+
+       memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i);
+       dst->i.i_size = 0;
+       dst->i.i_blocks = cpu_to_le64(1);
+       dst->i.i_links = cpu_to_le32(1);
+       dst->i.i_xattr_nid = 0;
+
+       new_ni = old_ni;
+       new_ni.ino = ino;
+
+       set_node_addr(sbi, &new_ni, NEW_ADDR);
+       inc_valid_inode_count(sbi);
+
+       f2fs_put_page(ipage, 1);
+       return 0;
+}
+
+int restore_node_summary(struct f2fs_sb_info *sbi,
+                       unsigned int segno, struct f2fs_summary_block *sum)
+{
+       struct f2fs_node *rn;
+       struct f2fs_summary *sum_entry;
+       struct page *page;
+       block_t addr;
+       int i, last_offset;
+
+       /* alloc temporal page for read node */
+       page = alloc_page(GFP_NOFS | __GFP_ZERO);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+       lock_page(page);
+
+       /* scan the node segment */
+       last_offset = sbi->blocks_per_seg;
+       addr = START_BLOCK(sbi, segno);
+       sum_entry = &sum->entries[0];
+
+       for (i = 0; i < last_offset; i++, sum_entry++) {
+               if (f2fs_readpage(sbi, page, addr, READ_SYNC))
+                       goto out;
+
+               rn = (struct f2fs_node *)page_address(page);
+               sum_entry->nid = rn->footer.nid;
+               sum_entry->version = 0;
+               sum_entry->ofs_in_node = 0;
+               addr++;
+
+               /*
+                * In order to read next node page,
+                * we must clear PageUptodate flag.
+                */
+               ClearPageUptodate(page);
+       }
+out:
+       unlock_page(page);
+       __free_pages(page, 0);
+       return 0;
+}
+
+static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       int i;
+
+       mutex_lock(&curseg->curseg_mutex);
+
+       if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) {
+               mutex_unlock(&curseg->curseg_mutex);
+               return false;
+       }
+
+       for (i = 0; i < nats_in_cursum(sum); i++) {
+               struct nat_entry *ne;
+               struct f2fs_nat_entry raw_ne;
+               nid_t nid = le32_to_cpu(nid_in_journal(sum, i));
+
+               raw_ne = nat_in_journal(sum, i);
+retry:
+               write_lock(&nm_i->nat_tree_lock);
+               ne = __lookup_nat_cache(nm_i, nid);
+               if (ne) {
+                       __set_nat_cache_dirty(nm_i, ne);
+                       write_unlock(&nm_i->nat_tree_lock);
+                       continue;
+               }
+               ne = grab_nat_entry(nm_i, nid);
+               if (!ne) {
+                       write_unlock(&nm_i->nat_tree_lock);
+                       goto retry;
+               }
+               nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr));
+               nat_set_ino(ne, le32_to_cpu(raw_ne.ino));
+               nat_set_version(ne, raw_ne.version);
+               __set_nat_cache_dirty(nm_i, ne);
+               write_unlock(&nm_i->nat_tree_lock);
+       }
+       update_nats_in_cursum(sum, -i);
+       mutex_unlock(&curseg->curseg_mutex);
+       return true;
+}
+
+/*
+ * This function is called during the checkpointing process.
+ */
+void flush_nat_entries(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       struct list_head *cur, *n;
+       struct page *page = NULL;
+       struct f2fs_nat_block *nat_blk = NULL;
+       nid_t start_nid = 0, end_nid = 0;
+       bool flushed;
+
+       flushed = flush_nats_in_journal(sbi);
+
+       if (!flushed)
+               mutex_lock(&curseg->curseg_mutex);
+
+       /* 1) flush dirty nat caches */
+       list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) {
+               struct nat_entry *ne;
+               nid_t nid;
+               struct f2fs_nat_entry raw_ne;
+               int offset = -1;
+               block_t new_blkaddr;
+
+               ne = list_entry(cur, struct nat_entry, list);
+               nid = nat_get_nid(ne);
+
+               if (nat_get_blkaddr(ne) == NEW_ADDR)
+                       continue;
+               if (flushed)
+                       goto to_nat_page;
+
+               /* if there is room for nat enries in curseg->sumpage */
+               offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);
+               if (offset >= 0) {
+                       raw_ne = nat_in_journal(sum, offset);
+                       goto flush_now;
+               }
+to_nat_page:
+               if (!page || (start_nid > nid || nid > end_nid)) {
+                       if (page) {
+                               f2fs_put_page(page, 1);
+                               page = NULL;
+                       }
+                       start_nid = START_NID(nid);
+                       end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1;
+
+                       /*
+                        * get nat block with dirty flag, increased reference
+                        * count, mapped and lock
+                        */
+                       page = get_next_nat_page(sbi, start_nid);
+                       nat_blk = page_address(page);
+               }
+
+               BUG_ON(!nat_blk);
+               raw_ne = nat_blk->entries[nid - start_nid];
+flush_now:
+               new_blkaddr = nat_get_blkaddr(ne);
+
+               raw_ne.ino = cpu_to_le32(nat_get_ino(ne));
+               raw_ne.block_addr = cpu_to_le32(new_blkaddr);
+               raw_ne.version = nat_get_version(ne);
+
+               if (offset < 0) {
+                       nat_blk->entries[nid - start_nid] = raw_ne;
+               } else {
+                       nat_in_journal(sum, offset) = raw_ne;
+                       nid_in_journal(sum, offset) = cpu_to_le32(nid);
+               }
+
+               if (nat_get_blkaddr(ne) == NULL_ADDR) {
+                       write_lock(&nm_i->nat_tree_lock);
+                       __del_from_nat_cache(nm_i, ne);
+                       write_unlock(&nm_i->nat_tree_lock);
+
+                       /* We can reuse this freed nid at this point */
+                       add_free_nid(NM_I(sbi), nid);
+               } else {
+                       write_lock(&nm_i->nat_tree_lock);
+                       __clear_nat_cache_dirty(nm_i, ne);
+                       ne->checkpointed = true;
+                       write_unlock(&nm_i->nat_tree_lock);
+               }
+       }
+       if (!flushed)
+               mutex_unlock(&curseg->curseg_mutex);
+       f2fs_put_page(page, 1);
+
+       /* 2) shrink nat caches if necessary */
+       try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD);
+}
+
+static int init_node_manager(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       unsigned char *version_bitmap;
+       unsigned int nat_segs, nat_blocks;
+
+       nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
+
+       /* segment_count_nat includes pair segment so divide to 2. */
+       nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
+       nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
+       nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
+       nm_i->fcnt = 0;
+       nm_i->nat_cnt = 0;
+
+       INIT_LIST_HEAD(&nm_i->free_nid_list);
+       INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
+       INIT_LIST_HEAD(&nm_i->nat_entries);
+       INIT_LIST_HEAD(&nm_i->dirty_nat_entries);
+
+       mutex_init(&nm_i->build_lock);
+       spin_lock_init(&nm_i->free_nid_list_lock);
+       rwlock_init(&nm_i->nat_tree_lock);
+
+       nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
+       nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+       nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+
+       nm_i->nat_bitmap = kzalloc(nm_i->bitmap_size, GFP_KERNEL);
+       if (!nm_i->nat_bitmap)
+               return -ENOMEM;
+       version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
+       if (!version_bitmap)
+               return -EFAULT;
+
+       /* copy version bitmap */
+       memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
+       return 0;
+}
+
+int build_node_manager(struct f2fs_sb_info *sbi)
+{
+       int err;
+
+       sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL);
+       if (!sbi->nm_info)
+               return -ENOMEM;
+
+       err = init_node_manager(sbi);
+       if (err)
+               return err;
+
+       build_free_nids(sbi);
+       return 0;
+}
+
+void destroy_node_manager(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct free_nid *i, *next_i;
+       struct nat_entry *natvec[NATVEC_SIZE];
+       nid_t nid = 0;
+       unsigned int found;
+
+       if (!nm_i)
+               return;
+
+       /* destroy free nid list */
+       spin_lock(&nm_i->free_nid_list_lock);
+       list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
+               BUG_ON(i->state == NID_ALLOC);
+               __del_from_free_nid_list(i);
+               nm_i->fcnt--;
+       }
+       BUG_ON(nm_i->fcnt);
+       spin_unlock(&nm_i->free_nid_list_lock);
+
+       /* destroy nat cache */
+       write_lock(&nm_i->nat_tree_lock);
+       while ((found = __gang_lookup_nat_cache(nm_i,
+                                       nid, NATVEC_SIZE, natvec))) {
+               unsigned idx;
+               for (idx = 0; idx < found; idx++) {
+                       struct nat_entry *e = natvec[idx];
+                       nid = nat_get_nid(e) + 1;
+                       __del_from_nat_cache(nm_i, e);
+               }
+       }
+       BUG_ON(nm_i->nat_cnt);
+       write_unlock(&nm_i->nat_tree_lock);
+
+       kfree(nm_i->nat_bitmap);
+       sbi->nm_info = NULL;
+       kfree(nm_i);
+}
+
+int __init create_node_manager_caches(void)
+{
+       nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
+                       sizeof(struct nat_entry), NULL);
+       if (!nat_entry_slab)
+               return -ENOMEM;
+
+       free_nid_slab = f2fs_kmem_cache_create("free_nid",
+                       sizeof(struct free_nid), NULL);
+       if (!free_nid_slab) {
+               kmem_cache_destroy(nat_entry_slab);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void destroy_node_manager_caches(void)
+{
+       kmem_cache_destroy(free_nid_slab);
+       kmem_cache_destroy(nat_entry_slab);
+}
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
new file mode 100644 (file)
index 0000000..afdb130
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * fs/f2fs/node.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+/* start node id of a node block dedicated to the given node id */
+#define        START_NID(nid) ((nid / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
+
+/* node block offset on the NAT area dedicated to the given start node id */
+#define        NAT_BLOCK_OFFSET(start_nid) (start_nid / NAT_ENTRY_PER_BLOCK)
+
+/* # of pages to perform readahead before building free nids */
+#define FREE_NID_PAGES 4
+
+/* maximum # of free node ids to produce during build_free_nids */
+#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
+
+/* maximum readahead size for node during getting data blocks */
+#define MAX_RA_NODE            128
+
+/* maximum cached nat entries to manage memory footprint */
+#define NM_WOUT_THRESHOLD      (64 * NAT_ENTRY_PER_BLOCK)
+
+/* vector size for gang look-up from nat cache that consists of radix tree */
+#define NATVEC_SIZE    64
+
+/*
+ * For node information
+ */
+struct node_info {
+       nid_t nid;              /* node id */
+       nid_t ino;              /* inode number of the node's owner */
+       block_t blk_addr;       /* block address of the node */
+       unsigned char version;  /* version of the node */
+};
+
+struct nat_entry {
+       struct list_head list;  /* for clean or dirty nat list */
+       bool checkpointed;      /* whether it is checkpointed or not */
+       struct node_info ni;    /* in-memory node information */
+};
+
+#define nat_get_nid(nat)               (nat->ni.nid)
+#define nat_set_nid(nat, n)            (nat->ni.nid = n)
+#define nat_get_blkaddr(nat)           (nat->ni.blk_addr)
+#define nat_set_blkaddr(nat, b)                (nat->ni.blk_addr = b)
+#define nat_get_ino(nat)               (nat->ni.ino)
+#define nat_set_ino(nat, i)            (nat->ni.ino = i)
+#define nat_get_version(nat)           (nat->ni.version)
+#define nat_set_version(nat, v)                (nat->ni.version = v)
+
+#define __set_nat_cache_dirty(nm_i, ne)                                        \
+       list_move_tail(&ne->list, &nm_i->dirty_nat_entries);
+#define __clear_nat_cache_dirty(nm_i, ne)                              \
+       list_move_tail(&ne->list, &nm_i->nat_entries);
+#define inc_node_version(version)      (++version)
+
+static inline void node_info_from_raw_nat(struct node_info *ni,
+                                               struct f2fs_nat_entry *raw_ne)
+{
+       ni->ino = le32_to_cpu(raw_ne->ino);
+       ni->blk_addr = le32_to_cpu(raw_ne->block_addr);
+       ni->version = raw_ne->version;
+}
+
+/*
+ * For free nid mangement
+ */
+enum nid_state {
+       NID_NEW,        /* newly added to free nid list */
+       NID_ALLOC       /* it is allocated */
+};
+
+struct free_nid {
+       struct list_head list;  /* for free node id list */
+       nid_t nid;              /* node id */
+       int state;              /* in use or not: NID_NEW or NID_ALLOC */
+};
+
+static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       struct free_nid *fnid;
+
+       if (nm_i->fcnt <= 0)
+               return -1;
+       spin_lock(&nm_i->free_nid_list_lock);
+       fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list);
+       *nid = fnid->nid;
+       spin_unlock(&nm_i->free_nid_list_lock);
+       return 0;
+}
+
+/*
+ * inline functions
+ */
+static inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size);
+}
+
+static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       pgoff_t block_off;
+       pgoff_t block_addr;
+       int seg_off;
+
+       block_off = NAT_BLOCK_OFFSET(start);
+       seg_off = block_off >> sbi->log_blocks_per_seg;
+
+       block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+               (seg_off << sbi->log_blocks_per_seg << 1) +
+               (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+       if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+               block_addr += sbi->blocks_per_seg;
+
+       return block_addr;
+}
+
+static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
+                                               pgoff_t block_addr)
+{
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+       block_addr -= nm_i->nat_blkaddr;
+       if ((block_addr >> sbi->log_blocks_per_seg) % 2)
+               block_addr -= sbi->blocks_per_seg;
+       else
+               block_addr += sbi->blocks_per_seg;
+
+       return block_addr + nm_i->nat_blkaddr;
+}
+
+static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
+{
+       unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
+
+       if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+               f2fs_clear_bit(block_off, nm_i->nat_bitmap);
+       else
+               f2fs_set_bit(block_off, nm_i->nat_bitmap);
+}
+
+static inline void fill_node_footer(struct page *page, nid_t nid,
+                               nid_t ino, unsigned int ofs, bool reset)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       if (reset)
+               memset(rn, 0, sizeof(*rn));
+       rn->footer.nid = cpu_to_le32(nid);
+       rn->footer.ino = cpu_to_le32(ino);
+       rn->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
+}
+
+static inline void copy_node_footer(struct page *dst, struct page *src)
+{
+       void *src_addr = page_address(src);
+       void *dst_addr = page_address(dst);
+       struct f2fs_node *src_rn = (struct f2fs_node *)src_addr;
+       struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr;
+       memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
+}
+
+static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       rn->footer.cp_ver = ckpt->checkpoint_ver;
+       rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
+}
+
+static inline nid_t ino_of_node(struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       return le32_to_cpu(rn->footer.ino);
+}
+
+static inline nid_t nid_of_node(struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       return le32_to_cpu(rn->footer.nid);
+}
+
+static inline unsigned int ofs_of_node(struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned flag = le32_to_cpu(rn->footer.flag);
+       return flag >> OFFSET_BIT_SHIFT;
+}
+
+static inline unsigned long long cpver_of_node(struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       return le64_to_cpu(rn->footer.cp_ver);
+}
+
+static inline block_t next_blkaddr_of_node(struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       return le32_to_cpu(rn->footer.next_blkaddr);
+}
+
+/*
+ * f2fs assigns the following node offsets described as (num).
+ * N = NIDS_PER_BLOCK
+ *
+ *  Inode block (0)
+ *    |- direct node (1)
+ *    |- direct node (2)
+ *    |- indirect node (3)
+ *    |            `- direct node (4 => 4 + N - 1)
+ *    |- indirect node (4 + N)
+ *    |            `- direct node (5 + N => 5 + 2N - 1)
+ *    `- double indirect node (5 + 2N)
+ *                 `- indirect node (6 + 2N)
+ *                       `- direct node (x(N + 1))
+ */
+static inline bool IS_DNODE(struct page *node_page)
+{
+       unsigned int ofs = ofs_of_node(node_page);
+       if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
+                       ofs == 5 + 2 * NIDS_PER_BLOCK)
+               return false;
+       if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
+               ofs -= 6 + 2 * NIDS_PER_BLOCK;
+               if ((long int)ofs % (NIDS_PER_BLOCK + 1))
+                       return false;
+       }
+       return true;
+}
+
+static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
+{
+       struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+
+       wait_on_page_writeback(p);
+
+       if (i)
+               rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
+       else
+               rn->in.nid[off] = cpu_to_le32(nid);
+       set_page_dirty(p);
+}
+
+static inline nid_t get_nid(struct page *p, int off, bool i)
+{
+       struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+       if (i)
+               return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+       return le32_to_cpu(rn->in.nid[off]);
+}
+
+/*
+ * Coldness identification:
+ *  - Mark cold files in f2fs_inode_info
+ *  - Mark cold node blocks in their node footer
+ *  - Mark cold data pages in page cache
+ */
+static inline int is_cold_file(struct inode *inode)
+{
+       return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT;
+}
+
+static inline int is_cold_data(struct page *page)
+{
+       return PageChecked(page);
+}
+
+static inline void set_cold_data(struct page *page)
+{
+       SetPageChecked(page);
+}
+
+static inline void clear_cold_data(struct page *page)
+{
+       ClearPageChecked(page);
+}
+
+static inline int is_cold_node(struct page *page)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+       return flag & (0x1 << COLD_BIT_SHIFT);
+}
+
+static inline unsigned char is_fsync_dnode(struct page *page)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+       return flag & (0x1 << FSYNC_BIT_SHIFT);
+}
+
+static inline unsigned char is_dent_dnode(struct page *page)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+       return flag & (0x1 << DENT_BIT_SHIFT);
+}
+
+static inline void set_cold_node(struct inode *inode, struct page *page)
+{
+       struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+
+       if (S_ISDIR(inode->i_mode))
+               flag &= ~(0x1 << COLD_BIT_SHIFT);
+       else
+               flag |= (0x1 << COLD_BIT_SHIFT);
+       rn->footer.flag = cpu_to_le32(flag);
+}
+
+static inline void set_fsync_mark(struct page *page, int mark)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+       if (mark)
+               flag |= (0x1 << FSYNC_BIT_SHIFT);
+       else
+               flag &= ~(0x1 << FSYNC_BIT_SHIFT);
+       rn->footer.flag = cpu_to_le32(flag);
+}
+
+static inline void set_dentry_mark(struct page *page, int mark)
+{
+       void *kaddr = page_address(page);
+       struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+       unsigned int flag = le32_to_cpu(rn->footer.flag);
+       if (mark)
+               flag |= (0x1 << DENT_BIT_SHIFT);
+       else
+               flag &= ~(0x1 << DENT_BIT_SHIFT);
+       rn->footer.flag = cpu_to_le32(flag);
+}
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
new file mode 100644 (file)
index 0000000..f42e406
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * fs/f2fs/recovery.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *fsync_entry_slab;
+
+bool space_for_roll_forward(struct f2fs_sb_info *sbi)
+{
+       if (sbi->last_valid_block_count + sbi->alloc_valid_block_count
+                       > sbi->user_block_count)
+               return false;
+       return true;
+}
+
+static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
+                                                               nid_t ino)
+{
+       struct list_head *this;
+       struct fsync_inode_entry *entry;
+
+       list_for_each(this, head) {
+               entry = list_entry(this, struct fsync_inode_entry, list);
+               if (entry->inode->i_ino == ino)
+                       return entry;
+       }
+       return NULL;
+}
+
+static int recover_dentry(struct page *ipage, struct inode *inode)
+{
+       struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage);
+       struct f2fs_inode *raw_inode = &(raw_node->i);
+       struct dentry dent, parent;
+       struct f2fs_dir_entry *de;
+       struct page *page;
+       struct inode *dir;
+       int err = 0;
+
+       if (!is_dent_dnode(ipage))
+               goto out;
+
+       dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino));
+       if (IS_ERR(dir)) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       parent.d_inode = dir;
+       dent.d_parent = &parent;
+       dent.d_name.len = le32_to_cpu(raw_inode->i_namelen);
+       dent.d_name.name = raw_inode->i_name;
+
+       de = f2fs_find_entry(dir, &dent.d_name, &page);
+       if (de) {
+               kunmap(page);
+               f2fs_put_page(page, 0);
+       } else {
+               err = f2fs_add_link(&dent, inode);
+       }
+       iput(dir);
+out:
+       kunmap(ipage);
+       return err;
+}
+
+static int recover_inode(struct inode *inode, struct page *node_page)
+{
+       void *kaddr = page_address(node_page);
+       struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
+       struct f2fs_inode *raw_inode = &(raw_node->i);
+
+       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+       i_size_write(inode, le64_to_cpu(raw_inode->i_size));
+       inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
+       inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
+       inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
+       inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+       inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
+       inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+
+       return recover_dentry(node_page, inode);
+}
+
+static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
+{
+       unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
+       struct curseg_info *curseg;
+       struct page *page;
+       block_t blkaddr;
+       int err = 0;
+
+       /* get node pages in the current segment */
+       curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
+       blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
+
+       /* read node page */
+       page = alloc_page(GFP_F2FS_ZERO);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+       lock_page(page);
+
+       while (1) {
+               struct fsync_inode_entry *entry;
+
+               if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+                       goto out;
+
+               if (cp_ver != cpver_of_node(page))
+                       goto out;
+
+               if (!is_fsync_dnode(page))
+                       goto next;
+
+               entry = get_fsync_inode(head, ino_of_node(page));
+               if (entry) {
+                       entry->blkaddr = blkaddr;
+                       if (IS_INODE(page) && is_dent_dnode(page))
+                               set_inode_flag(F2FS_I(entry->inode),
+                                                       FI_INC_LINK);
+               } else {
+                       if (IS_INODE(page) && is_dent_dnode(page)) {
+                               if (recover_inode_page(sbi, page)) {
+                                       err = -ENOMEM;
+                                       goto out;
+                               }
+                       }
+
+                       /* add this fsync inode to the list */
+                       entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
+                       if (!entry) {
+                               err = -ENOMEM;
+                               goto out;
+                       }
+
+                       entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
+                       if (IS_ERR(entry->inode)) {
+                               err = PTR_ERR(entry->inode);
+                               kmem_cache_free(fsync_entry_slab, entry);
+                               goto out;
+                       }
+
+                       list_add_tail(&entry->list, head);
+                       entry->blkaddr = blkaddr;
+               }
+               if (IS_INODE(page)) {
+                       err = recover_inode(entry->inode, page);
+                       if (err)
+                               goto out;
+               }
+next:
+               /* check next segment */
+               blkaddr = next_blkaddr_of_node(page);
+               ClearPageUptodate(page);
+       }
+out:
+       unlock_page(page);
+       __free_pages(page, 0);
+       return err;
+}
+
+static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
+                                       struct list_head *head)
+{
+       struct fsync_inode_entry *entry, *tmp;
+
+       list_for_each_entry_safe(entry, tmp, head, list) {
+               iput(entry->inode);
+               list_del(&entry->list);
+               kmem_cache_free(fsync_entry_slab, entry);
+       }
+}
+
+static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
+                                               block_t blkaddr)
+{
+       struct seg_entry *sentry;
+       unsigned int segno = GET_SEGNO(sbi, blkaddr);
+       unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
+                                       (sbi->blocks_per_seg - 1);
+       struct f2fs_summary sum;
+       nid_t ino;
+       void *kaddr;
+       struct inode *inode;
+       struct page *node_page;
+       block_t bidx;
+       int i;
+
+       sentry = get_seg_entry(sbi, segno);
+       if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
+               return;
+
+       /* Get the previous summary */
+       for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
+               struct curseg_info *curseg = CURSEG_I(sbi, i);
+               if (curseg->segno == segno) {
+                       sum = curseg->sum_blk->entries[blkoff];
+                       break;
+               }
+       }
+       if (i > CURSEG_COLD_DATA) {
+               struct page *sum_page = get_sum_page(sbi, segno);
+               struct f2fs_summary_block *sum_node;
+               kaddr = page_address(sum_page);
+               sum_node = (struct f2fs_summary_block *)kaddr;
+               sum = sum_node->entries[blkoff];
+               f2fs_put_page(sum_page, 1);
+       }
+
+       /* Get the node page */
+       node_page = get_node_page(sbi, le32_to_cpu(sum.nid));
+       bidx = start_bidx_of_node(ofs_of_node(node_page)) +
+                               le16_to_cpu(sum.ofs_in_node);
+       ino = ino_of_node(node_page);
+       f2fs_put_page(node_page, 1);
+
+       /* Deallocate previous index in the node page */
+       inode = f2fs_iget_nowait(sbi->sb, ino);
+       if (IS_ERR(inode))
+               return;
+
+       truncate_hole(inode, bidx, bidx + 1);
+       iput(inode);
+}
+
+static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+                                       struct page *page, block_t blkaddr)
+{
+       unsigned int start, end;
+       struct dnode_of_data dn;
+       struct f2fs_summary sum;
+       struct node_info ni;
+
+       start = start_bidx_of_node(ofs_of_node(page));
+       if (IS_INODE(page))
+               end = start + ADDRS_PER_INODE;
+       else
+               end = start + ADDRS_PER_BLOCK;
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       if (get_dnode_of_data(&dn, start, 0))
+               return;
+
+       wait_on_page_writeback(dn.node_page);
+
+       get_node_info(sbi, dn.nid, &ni);
+       BUG_ON(ni.ino != ino_of_node(page));
+       BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page));
+
+       for (; start < end; start++) {
+               block_t src, dest;
+
+               src = datablock_addr(dn.node_page, dn.ofs_in_node);
+               dest = datablock_addr(page, dn.ofs_in_node);
+
+               if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
+                       if (src == NULL_ADDR) {
+                               int err = reserve_new_block(&dn);
+                               /* We should not get -ENOSPC */
+                               BUG_ON(err);
+                       }
+
+                       /* Check the previous node page having this index */
+                       check_index_in_prev_nodes(sbi, dest);
+
+                       set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
+
+                       /* write dummy data page */
+                       recover_data_page(sbi, NULL, &sum, src, dest);
+                       update_extent_cache(dest, &dn);
+               }
+               dn.ofs_in_node++;
+       }
+
+       /* write node page in place */
+       set_summary(&sum, dn.nid, 0, 0);
+       if (IS_INODE(dn.node_page))
+               sync_inode_page(&dn);
+
+       copy_node_footer(dn.node_page, page);
+       fill_node_footer(dn.node_page, dn.nid, ni.ino,
+                                       ofs_of_node(page), false);
+       set_page_dirty(dn.node_page);
+
+       recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
+       f2fs_put_dnode(&dn);
+}
+
+static void recover_data(struct f2fs_sb_info *sbi,
+                               struct list_head *head, int type)
+{
+       unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
+       struct curseg_info *curseg;
+       struct page *page;
+       block_t blkaddr;
+
+       /* get node pages in the current segment */
+       curseg = CURSEG_I(sbi, type);
+       blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+
+       /* read node page */
+       page = alloc_page(GFP_NOFS | __GFP_ZERO);
+       if (IS_ERR(page))
+               return;
+       lock_page(page);
+
+       while (1) {
+               struct fsync_inode_entry *entry;
+
+               if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+                       goto out;
+
+               if (cp_ver != cpver_of_node(page))
+                       goto out;
+
+               entry = get_fsync_inode(head, ino_of_node(page));
+               if (!entry)
+                       goto next;
+
+               do_recover_data(sbi, entry->inode, page, blkaddr);
+
+               if (entry->blkaddr == blkaddr) {
+                       iput(entry->inode);
+                       list_del(&entry->list);
+                       kmem_cache_free(fsync_entry_slab, entry);
+               }
+next:
+               /* check next segment */
+               blkaddr = next_blkaddr_of_node(page);
+               ClearPageUptodate(page);
+       }
+out:
+       unlock_page(page);
+       __free_pages(page, 0);
+
+       allocate_new_segments(sbi);
+}
+
+void recover_fsync_data(struct f2fs_sb_info *sbi)
+{
+       struct list_head inode_list;
+
+       fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
+                       sizeof(struct fsync_inode_entry), NULL);
+       if (unlikely(!fsync_entry_slab))
+               return;
+
+       INIT_LIST_HEAD(&inode_list);
+
+       /* step #1: find fsynced inode numbers */
+       if (find_fsync_dnodes(sbi, &inode_list))
+               goto out;
+
+       if (list_empty(&inode_list))
+               goto out;
+
+       /* step #2: recover data */
+       sbi->por_doing = 1;
+       recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
+       sbi->por_doing = 0;
+       BUG_ON(!list_empty(&inode_list));
+out:
+       destroy_fsync_dnodes(sbi, &inode_list);
+       kmem_cache_destroy(fsync_entry_slab);
+       write_checkpoint(sbi, false, false);
+}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
new file mode 100644 (file)
index 0000000..4b00990
--- /dev/null
@@ -0,0 +1,1757 @@
+/*
+ * fs/f2fs/segment.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/prefetch.h>
+#include <linux/vmalloc.h>
+
+#include "f2fs.h"
+#include "segment.h"
+#include "node.h"
+
+/*
+ * This function balances dirty node and dentry pages.
+ * In addition, it controls garbage collection.
+ */
+void f2fs_balance_fs(struct f2fs_sb_info *sbi)
+{
+       /*
+        * We should do GC or end up with checkpoint, if there are so many dirty
+        * dir/node pages without enough free segments.
+        */
+       if (has_not_enough_free_secs(sbi)) {
+               mutex_lock(&sbi->gc_mutex);
+               f2fs_gc(sbi);
+       }
+}
+
+static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
+               enum dirty_type dirty_type)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+       /* need not be added */
+       if (IS_CURSEG(sbi, segno))
+               return;
+
+       if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+               dirty_i->nr_dirty[dirty_type]++;
+
+       if (dirty_type == DIRTY) {
+               struct seg_entry *sentry = get_seg_entry(sbi, segno);
+               dirty_type = sentry->type;
+               if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+                       dirty_i->nr_dirty[dirty_type]++;
+       }
+}
+
+static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
+               enum dirty_type dirty_type)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+       if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+               dirty_i->nr_dirty[dirty_type]--;
+
+       if (dirty_type == DIRTY) {
+               struct seg_entry *sentry = get_seg_entry(sbi, segno);
+               dirty_type = sentry->type;
+               if (test_and_clear_bit(segno,
+                                       dirty_i->dirty_segmap[dirty_type]))
+                       dirty_i->nr_dirty[dirty_type]--;
+               clear_bit(segno, dirty_i->victim_segmap[FG_GC]);
+               clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
+       }
+}
+
+/*
+ * Should not occur error such as -ENOMEM.
+ * Adding dirty entry into seglist is not critical operation.
+ * If a given segment is one of current working segments, it won't be added.
+ */
+void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned short valid_blocks;
+
+       if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno))
+               return;
+
+       mutex_lock(&dirty_i->seglist_lock);
+
+       valid_blocks = get_valid_blocks(sbi, segno, 0);
+
+       if (valid_blocks == 0) {
+               __locate_dirty_segment(sbi, segno, PRE);
+               __remove_dirty_segment(sbi, segno, DIRTY);
+       } else if (valid_blocks < sbi->blocks_per_seg) {
+               __locate_dirty_segment(sbi, segno, DIRTY);
+       } else {
+               /* Recovery routine with SSR needs this */
+               __remove_dirty_segment(sbi, segno, DIRTY);
+       }
+
+       mutex_unlock(&dirty_i->seglist_lock);
+       return;
+}
+
+/*
+ * Should call clear_prefree_segments after checkpoint is done.
+ */
+static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned int segno, offset = 0;
+       unsigned int total_segs = TOTAL_SEGS(sbi);
+
+       mutex_lock(&dirty_i->seglist_lock);
+       while (1) {
+               segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
+                               offset);
+               if (segno >= total_segs)
+                       break;
+               __set_test_and_free(sbi, segno);
+               offset = segno + 1;
+       }
+       mutex_unlock(&dirty_i->seglist_lock);
+}
+
+void clear_prefree_segments(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned int segno, offset = 0;
+       unsigned int total_segs = TOTAL_SEGS(sbi);
+
+       mutex_lock(&dirty_i->seglist_lock);
+       while (1) {
+               segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
+                               offset);
+               if (segno >= total_segs)
+                       break;
+
+               offset = segno + 1;
+               if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE]))
+                       dirty_i->nr_dirty[PRE]--;
+
+               /* Let's use trim */
+               if (test_opt(sbi, DISCARD))
+                       blkdev_issue_discard(sbi->sb->s_bdev,
+                                       START_BLOCK(sbi, segno) <<
+                                       sbi->log_sectors_per_block,
+                                       1 << (sbi->log_sectors_per_block +
+                                               sbi->log_blocks_per_seg),
+                                       GFP_NOFS, 0);
+       }
+       mutex_unlock(&dirty_i->seglist_lock);
+}
+
+static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap))
+               sit_i->dirty_sentries++;
+}
+
+static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
+                                       unsigned int segno, int modified)
+{
+       struct seg_entry *se = get_seg_entry(sbi, segno);
+       se->type = type;
+       if (modified)
+               __mark_sit_entry_dirty(sbi, segno);
+}
+
+static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
+{
+       struct seg_entry *se;
+       unsigned int segno, offset;
+       long int new_vblocks;
+
+       segno = GET_SEGNO(sbi, blkaddr);
+
+       se = get_seg_entry(sbi, segno);
+       new_vblocks = se->valid_blocks + del;
+       offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
+
+       BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) ||
+                               (new_vblocks > sbi->blocks_per_seg)));
+
+       se->valid_blocks = new_vblocks;
+       se->mtime = get_mtime(sbi);
+       SIT_I(sbi)->max_mtime = se->mtime;
+
+       /* Update valid block bitmap */
+       if (del > 0) {
+               if (f2fs_set_bit(offset, se->cur_valid_map))
+                       BUG();
+       } else {
+               if (!f2fs_clear_bit(offset, se->cur_valid_map))
+                       BUG();
+       }
+       if (!f2fs_test_bit(offset, se->ckpt_valid_map))
+               se->ckpt_valid_blocks += del;
+
+       __mark_sit_entry_dirty(sbi, segno);
+
+       /* update total number of valid blocks to be written in ckpt area */
+       SIT_I(sbi)->written_valid_blocks += del;
+
+       if (sbi->segs_per_sec > 1)
+               get_sec_entry(sbi, segno)->valid_blocks += del;
+}
+
+static void refresh_sit_entry(struct f2fs_sb_info *sbi,
+                       block_t old_blkaddr, block_t new_blkaddr)
+{
+       update_sit_entry(sbi, new_blkaddr, 1);
+       if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
+               update_sit_entry(sbi, old_blkaddr, -1);
+}
+
+void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
+{
+       unsigned int segno = GET_SEGNO(sbi, addr);
+       struct sit_info *sit_i = SIT_I(sbi);
+
+       BUG_ON(addr == NULL_ADDR);
+       if (addr == NEW_ADDR)
+               return;
+
+       /* add it into sit main buffer */
+       mutex_lock(&sit_i->sentry_lock);
+
+       update_sit_entry(sbi, addr, -1);
+
+       /* add it into dirty seglist */
+       locate_dirty_segment(sbi, segno);
+
+       mutex_unlock(&sit_i->sentry_lock);
+}
+
+/*
+ * This function should be resided under the curseg_mutex lock
+ */
+static void __add_sum_entry(struct f2fs_sb_info *sbi, int type,
+               struct f2fs_summary *sum, unsigned short offset)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       void *addr = curseg->sum_blk;
+       addr += offset * sizeof(struct f2fs_summary);
+       memcpy(addr, sum, sizeof(struct f2fs_summary));
+       return;
+}
+
+/*
+ * Calculate the number of current summary pages for writing
+ */
+int npages_for_summary_flush(struct f2fs_sb_info *sbi)
+{
+       int total_size_bytes = 0;
+       int valid_sum_count = 0;
+       int i, sum_space;
+
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+               if (sbi->ckpt->alloc_type[i] == SSR)
+                       valid_sum_count += sbi->blocks_per_seg;
+               else
+                       valid_sum_count += curseg_blkoff(sbi, i);
+       }
+
+       total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1)
+                       + sizeof(struct nat_journal) + 2
+                       + sizeof(struct sit_journal) + 2;
+       sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE;
+       if (total_size_bytes < sum_space)
+               return 1;
+       else if (total_size_bytes < 2 * sum_space)
+               return 2;
+       return 3;
+}
+
+/*
+ * Caller should put this summary page
+ */
+struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
+}
+
+static void write_sum_page(struct f2fs_sb_info *sbi,
+                       struct f2fs_summary_block *sum_blk, block_t blk_addr)
+{
+       struct page *page = grab_meta_page(sbi, blk_addr);
+       void *kaddr = page_address(page);
+       memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE);
+       set_page_dirty(page);
+       f2fs_put_page(page, 1);
+}
+
+static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
+                                       int ofs_unit, int type)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE];
+       unsigned int segno, next_segno, i;
+       int ofs = 0;
+
+       /*
+        * If there is not enough reserved sections,
+        * we should not reuse prefree segments.
+        */
+       if (has_not_enough_free_secs(sbi))
+               return NULL_SEGNO;
+
+       /*
+        * NODE page should not reuse prefree segment,
+        * since those information is used for SPOR.
+        */
+       if (IS_NODESEG(type))
+               return NULL_SEGNO;
+next:
+       segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs++);
+       ofs = ((segno / ofs_unit) * ofs_unit) + ofs_unit;
+       if (segno < TOTAL_SEGS(sbi)) {
+               /* skip intermediate segments in a section */
+               if (segno % ofs_unit)
+                       goto next;
+
+               /* skip if whole section is not prefree */
+               next_segno = find_next_zero_bit(prefree_segmap,
+                                               TOTAL_SEGS(sbi), segno + 1);
+               if (next_segno - segno < ofs_unit)
+                       goto next;
+
+               /* skip if whole section was not free at the last checkpoint */
+               for (i = 0; i < ofs_unit; i++)
+                       if (get_seg_entry(sbi, segno)->ckpt_valid_blocks)
+                               goto next;
+               return segno;
+       }
+       return NULL_SEGNO;
+}
+
+/*
+ * Find a new segment from the free segments bitmap to right order
+ * This function should be returned with success, otherwise BUG
+ */
+static void get_new_segment(struct f2fs_sb_info *sbi,
+                       unsigned int *newseg, bool new_sec, int dir)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int total_secs = sbi->total_sections;
+       unsigned int segno, secno, zoneno;
+       unsigned int total_zones = sbi->total_sections / sbi->secs_per_zone;
+       unsigned int hint = *newseg / sbi->segs_per_sec;
+       unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg);
+       unsigned int left_start = hint;
+       bool init = true;
+       int go_left = 0;
+       int i;
+
+       write_lock(&free_i->segmap_lock);
+
+       if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
+               segno = find_next_zero_bit(free_i->free_segmap,
+                                       TOTAL_SEGS(sbi), *newseg + 1);
+               if (segno < TOTAL_SEGS(sbi))
+                       goto got_it;
+       }
+find_other_zone:
+       secno = find_next_zero_bit(free_i->free_secmap, total_secs, hint);
+       if (secno >= total_secs) {
+               if (dir == ALLOC_RIGHT) {
+                       secno = find_next_zero_bit(free_i->free_secmap,
+                                               total_secs, 0);
+                       BUG_ON(secno >= total_secs);
+               } else {
+                       go_left = 1;
+                       left_start = hint - 1;
+               }
+       }
+       if (go_left == 0)
+               goto skip_left;
+
+       while (test_bit(left_start, free_i->free_secmap)) {
+               if (left_start > 0) {
+                       left_start--;
+                       continue;
+               }
+               left_start = find_next_zero_bit(free_i->free_secmap,
+                                               total_secs, 0);
+               BUG_ON(left_start >= total_secs);
+               break;
+       }
+       secno = left_start;
+skip_left:
+       hint = secno;
+       segno = secno * sbi->segs_per_sec;
+       zoneno = secno / sbi->secs_per_zone;
+
+       /* give up on finding another zone */
+       if (!init)
+               goto got_it;
+       if (sbi->secs_per_zone == 1)
+               goto got_it;
+       if (zoneno == old_zoneno)
+               goto got_it;
+       if (dir == ALLOC_LEFT) {
+               if (!go_left && zoneno + 1 >= total_zones)
+                       goto got_it;
+               if (go_left && zoneno == 0)
+                       goto got_it;
+       }
+       for (i = 0; i < NR_CURSEG_TYPE; i++)
+               if (CURSEG_I(sbi, i)->zone == zoneno)
+                       break;
+
+       if (i < NR_CURSEG_TYPE) {
+               /* zone is in user, try another */
+               if (go_left)
+                       hint = zoneno * sbi->secs_per_zone - 1;
+               else if (zoneno + 1 >= total_zones)
+                       hint = 0;
+               else
+                       hint = (zoneno + 1) * sbi->secs_per_zone;
+               init = false;
+               goto find_other_zone;
+       }
+got_it:
+       /* set it as dirty segment in free segmap */
+       BUG_ON(test_bit(segno, free_i->free_segmap));
+       __set_inuse(sbi, segno);
+       *newseg = segno;
+       write_unlock(&free_i->segmap_lock);
+}
+
+static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       struct summary_footer *sum_footer;
+
+       curseg->segno = curseg->next_segno;
+       curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno);
+       curseg->next_blkoff = 0;
+       curseg->next_segno = NULL_SEGNO;
+
+       sum_footer = &(curseg->sum_blk->footer);
+       memset(sum_footer, 0, sizeof(struct summary_footer));
+       if (IS_DATASEG(type))
+               SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
+       if (IS_NODESEG(type))
+               SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
+       __set_sit_entry_type(sbi, type, curseg->segno, modified);
+}
+
+/*
+ * Allocate a current working segment.
+ * This function always allocates a free segment in LFS manner.
+ */
+static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       unsigned int segno = curseg->segno;
+       int dir = ALLOC_LEFT;
+
+       write_sum_page(sbi, curseg->sum_blk,
+                               GET_SUM_BLOCK(sbi, curseg->segno));
+       if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
+               dir = ALLOC_RIGHT;
+
+       if (test_opt(sbi, NOHEAP))
+               dir = ALLOC_RIGHT;
+
+       get_new_segment(sbi, &segno, new_sec, dir);
+       curseg->next_segno = segno;
+       reset_curseg(sbi, type, 1);
+       curseg->alloc_type = LFS;
+}
+
+static void __next_free_blkoff(struct f2fs_sb_info *sbi,
+                       struct curseg_info *seg, block_t start)
+{
+       struct seg_entry *se = get_seg_entry(sbi, seg->segno);
+       block_t ofs;
+       for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) {
+               if (!f2fs_test_bit(ofs, se->ckpt_valid_map)
+                       && !f2fs_test_bit(ofs, se->cur_valid_map))
+                       break;
+       }
+       seg->next_blkoff = ofs;
+}
+
+/*
+ * If a segment is written by LFS manner, next block offset is just obtained
+ * by increasing the current block offset. However, if a segment is written by
+ * SSR manner, next block offset obtained by calling __next_free_blkoff
+ */
+static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
+                               struct curseg_info *seg)
+{
+       if (seg->alloc_type == SSR)
+               __next_free_blkoff(sbi, seg, seg->next_blkoff + 1);
+       else
+               seg->next_blkoff++;
+}
+
+/*
+ * This function always allocates a used segment (from dirty seglist) by SSR
+ * manner, so it should recover the existing segment information of valid blocks
+ */
+static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       unsigned int new_segno = curseg->next_segno;
+       struct f2fs_summary_block *sum_node;
+       struct page *sum_page;
+
+       write_sum_page(sbi, curseg->sum_blk,
+                               GET_SUM_BLOCK(sbi, curseg->segno));
+       __set_test_and_inuse(sbi, new_segno);
+
+       mutex_lock(&dirty_i->seglist_lock);
+       __remove_dirty_segment(sbi, new_segno, PRE);
+       __remove_dirty_segment(sbi, new_segno, DIRTY);
+       mutex_unlock(&dirty_i->seglist_lock);
+
+       reset_curseg(sbi, type, 1);
+       curseg->alloc_type = SSR;
+       __next_free_blkoff(sbi, curseg, 0);
+
+       if (reuse) {
+               sum_page = get_sum_page(sbi, new_segno);
+               sum_node = (struct f2fs_summary_block *)page_address(sum_page);
+               memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
+               f2fs_put_page(sum_page, 1);
+       }
+}
+
+/*
+ * flush out current segment and replace it with new segment
+ * This function should be returned with success, otherwise BUG
+ */
+static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
+                                               int type, bool force)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       unsigned int ofs_unit;
+
+       if (force) {
+               new_curseg(sbi, type, true);
+               goto out;
+       }
+
+       ofs_unit = need_SSR(sbi) ? 1 : sbi->segs_per_sec;
+       curseg->next_segno = check_prefree_segments(sbi, ofs_unit, type);
+
+       if (curseg->next_segno != NULL_SEGNO)
+               change_curseg(sbi, type, false);
+       else if (type == CURSEG_WARM_NODE)
+               new_curseg(sbi, type, false);
+       else if (need_SSR(sbi) && get_ssr_segment(sbi, type))
+               change_curseg(sbi, type, true);
+       else
+               new_curseg(sbi, type, false);
+out:
+       sbi->segment_count[curseg->alloc_type]++;
+}
+
+void allocate_new_segments(struct f2fs_sb_info *sbi)
+{
+       struct curseg_info *curseg;
+       unsigned int old_curseg;
+       int i;
+
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+               curseg = CURSEG_I(sbi, i);
+               old_curseg = curseg->segno;
+               SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true);
+               locate_dirty_segment(sbi, old_curseg);
+       }
+}
+
+static const struct segment_allocation default_salloc_ops = {
+       .allocate_segment = allocate_segment_by_default,
+};
+
+static void f2fs_end_io_write(struct bio *bio, int err)
+{
+       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_private *p = bio->bi_private;
+
+       do {
+               struct page *page = bvec->bv_page;
+
+               if (--bvec >= bio->bi_io_vec)
+                       prefetchw(&bvec->bv_page->flags);
+               if (!uptodate) {
+                       SetPageError(page);
+                       if (page->mapping)
+                               set_bit(AS_EIO, &page->mapping->flags);
+                       set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG);
+               }
+               end_page_writeback(page);
+               dec_page_count(p->sbi, F2FS_WRITEBACK);
+       } while (bvec >= bio->bi_io_vec);
+
+       if (p->is_sync)
+               complete(p->wait);
+       kfree(p);
+       bio_put(bio);
+}
+
+struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages)
+{
+       struct bio *bio;
+       struct bio_private *priv;
+retry:
+       priv = kmalloc(sizeof(struct bio_private), GFP_NOFS);
+       if (!priv) {
+               cond_resched();
+               goto retry;
+       }
+
+       /* No failure on bio allocation */
+       bio = bio_alloc(GFP_NOIO, npages);
+       bio->bi_bdev = bdev;
+       bio->bi_private = priv;
+       return bio;
+}
+
+static void do_submit_bio(struct f2fs_sb_info *sbi,
+                               enum page_type type, bool sync)
+{
+       int rw = sync ? WRITE_SYNC : WRITE;
+       enum page_type btype = type > META ? META : type;
+
+       if (type >= META_FLUSH)
+               rw = WRITE_FLUSH_FUA;
+
+       if (sbi->bio[btype]) {
+               struct bio_private *p = sbi->bio[btype]->bi_private;
+               p->sbi = sbi;
+               sbi->bio[btype]->bi_end_io = f2fs_end_io_write;
+               if (type == META_FLUSH) {
+                       DECLARE_COMPLETION_ONSTACK(wait);
+                       p->is_sync = true;
+                       p->wait = &wait;
+                       submit_bio(rw, sbi->bio[btype]);
+                       wait_for_completion(&wait);
+               } else {
+                       p->is_sync = false;
+                       submit_bio(rw, sbi->bio[btype]);
+               }
+               sbi->bio[btype] = NULL;
+       }
+}
+
+void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync)
+{
+       down_write(&sbi->bio_sem);
+       do_submit_bio(sbi, type, sync);
+       up_write(&sbi->bio_sem);
+}
+
+static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
+                               block_t blk_addr, enum page_type type)
+{
+       struct block_device *bdev = sbi->sb->s_bdev;
+
+       verify_block_addr(sbi, blk_addr);
+
+       down_write(&sbi->bio_sem);
+
+       inc_page_count(sbi, F2FS_WRITEBACK);
+
+       if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1)
+               do_submit_bio(sbi, type, false);
+alloc_new:
+       if (sbi->bio[type] == NULL) {
+               sbi->bio[type] = f2fs_bio_alloc(bdev, bio_get_nr_vecs(bdev));
+               sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
+               /*
+                * The end_io will be assigned at the sumbission phase.
+                * Until then, let bio_add_page() merge consecutive IOs as much
+                * as possible.
+                */
+       }
+
+       if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) <
+                                                       PAGE_CACHE_SIZE) {
+               do_submit_bio(sbi, type, false);
+               goto alloc_new;
+       }
+
+       sbi->last_block_in_bio[type] = blk_addr;
+
+       up_write(&sbi->bio_sem);
+}
+
+static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       if (curseg->next_blkoff < sbi->blocks_per_seg)
+               return true;
+       return false;
+}
+
+static int __get_segment_type_2(struct page *page, enum page_type p_type)
+{
+       if (p_type == DATA)
+               return CURSEG_HOT_DATA;
+       else
+               return CURSEG_HOT_NODE;
+}
+
+static int __get_segment_type_4(struct page *page, enum page_type p_type)
+{
+       if (p_type == DATA) {
+               struct inode *inode = page->mapping->host;
+
+               if (S_ISDIR(inode->i_mode))
+                       return CURSEG_HOT_DATA;
+               else
+                       return CURSEG_COLD_DATA;
+       } else {
+               if (IS_DNODE(page) && !is_cold_node(page))
+                       return CURSEG_HOT_NODE;
+               else
+                       return CURSEG_COLD_NODE;
+       }
+}
+
+static int __get_segment_type_6(struct page *page, enum page_type p_type)
+{
+       if (p_type == DATA) {
+               struct inode *inode = page->mapping->host;
+
+               if (S_ISDIR(inode->i_mode))
+                       return CURSEG_HOT_DATA;
+               else if (is_cold_data(page) || is_cold_file(inode))
+                       return CURSEG_COLD_DATA;
+               else
+                       return CURSEG_WARM_DATA;
+       } else {
+               if (IS_DNODE(page))
+                       return is_cold_node(page) ? CURSEG_WARM_NODE :
+                                               CURSEG_HOT_NODE;
+               else
+                       return CURSEG_COLD_NODE;
+       }
+}
+
+static int __get_segment_type(struct page *page, enum page_type p_type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+       switch (sbi->active_logs) {
+       case 2:
+               return __get_segment_type_2(page, p_type);
+       case 4:
+               return __get_segment_type_4(page, p_type);
+       }
+       /* NR_CURSEG_TYPE(6) logs by default */
+       BUG_ON(sbi->active_logs != NR_CURSEG_TYPE);
+       return __get_segment_type_6(page, p_type);
+}
+
+static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
+                       block_t old_blkaddr, block_t *new_blkaddr,
+                       struct f2fs_summary *sum, enum page_type p_type)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct curseg_info *curseg;
+       unsigned int old_cursegno;
+       int type;
+
+       type = __get_segment_type(page, p_type);
+       curseg = CURSEG_I(sbi, type);
+
+       mutex_lock(&curseg->curseg_mutex);
+
+       *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+       old_cursegno = curseg->segno;
+
+       /*
+        * __add_sum_entry should be resided under the curseg_mutex
+        * because, this function updates a summary entry in the
+        * current summary block.
+        */
+       __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+       mutex_lock(&sit_i->sentry_lock);
+       __refresh_next_blkoff(sbi, curseg);
+       sbi->block_count[curseg->alloc_type]++;
+
+       /*
+        * SIT information should be updated before segment allocation,
+        * since SSR needs latest valid block information.
+        */
+       refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr);
+
+       if (!__has_curseg_space(sbi, type))
+               sit_i->s_ops->allocate_segment(sbi, type, false);
+
+       locate_dirty_segment(sbi, old_cursegno);
+       locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+       mutex_unlock(&sit_i->sentry_lock);
+
+       if (p_type == NODE)
+               fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
+
+       /* writeout dirty page into bdev */
+       submit_write_page(sbi, page, *new_blkaddr, p_type);
+
+       mutex_unlock(&curseg->curseg_mutex);
+}
+
+int write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
+                       struct writeback_control *wbc)
+{
+       if (wbc->for_reclaim)
+               return AOP_WRITEPAGE_ACTIVATE;
+
+       set_page_writeback(page);
+       submit_write_page(sbi, page, page->index, META);
+       return 0;
+}
+
+void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
+               unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
+{
+       struct f2fs_summary sum;
+       set_summary(&sum, nid, 0, 0);
+       do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
+}
+
+void write_data_page(struct inode *inode, struct page *page,
+               struct dnode_of_data *dn, block_t old_blkaddr,
+               block_t *new_blkaddr)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_summary sum;
+       struct node_info ni;
+
+       BUG_ON(old_blkaddr == NULL_ADDR);
+       get_node_info(sbi, dn->nid, &ni);
+       set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
+
+       do_write_page(sbi, page, old_blkaddr,
+                       new_blkaddr, &sum, DATA);
+}
+
+void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
+                                       block_t old_blk_addr)
+{
+       submit_write_page(sbi, page, old_blk_addr, DATA);
+}
+
+void recover_data_page(struct f2fs_sb_info *sbi,
+                       struct page *page, struct f2fs_summary *sum,
+                       block_t old_blkaddr, block_t new_blkaddr)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct curseg_info *curseg;
+       unsigned int segno, old_cursegno;
+       struct seg_entry *se;
+       int type;
+
+       segno = GET_SEGNO(sbi, new_blkaddr);
+       se = get_seg_entry(sbi, segno);
+       type = se->type;
+
+       if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) {
+               if (old_blkaddr == NULL_ADDR)
+                       type = CURSEG_COLD_DATA;
+               else
+                       type = CURSEG_WARM_DATA;
+       }
+       curseg = CURSEG_I(sbi, type);
+
+       mutex_lock(&curseg->curseg_mutex);
+       mutex_lock(&sit_i->sentry_lock);
+
+       old_cursegno = curseg->segno;
+
+       /* change the current segment */
+       if (segno != curseg->segno) {
+               curseg->next_segno = segno;
+               change_curseg(sbi, type, true);
+       }
+
+       curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
+                                       (sbi->blocks_per_seg - 1);
+       __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+       refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
+
+       locate_dirty_segment(sbi, old_cursegno);
+       locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+
+       mutex_unlock(&sit_i->sentry_lock);
+       mutex_unlock(&curseg->curseg_mutex);
+}
+
+void rewrite_node_page(struct f2fs_sb_info *sbi,
+                       struct page *page, struct f2fs_summary *sum,
+                       block_t old_blkaddr, block_t new_blkaddr)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       int type = CURSEG_WARM_NODE;
+       struct curseg_info *curseg;
+       unsigned int segno, old_cursegno;
+       block_t next_blkaddr = next_blkaddr_of_node(page);
+       unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
+
+       curseg = CURSEG_I(sbi, type);
+
+       mutex_lock(&curseg->curseg_mutex);
+       mutex_lock(&sit_i->sentry_lock);
+
+       segno = GET_SEGNO(sbi, new_blkaddr);
+       old_cursegno = curseg->segno;
+
+       /* change the current segment */
+       if (segno != curseg->segno) {
+               curseg->next_segno = segno;
+               change_curseg(sbi, type, true);
+       }
+       curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
+                                       (sbi->blocks_per_seg - 1);
+       __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+       /* change the current log to the next block addr in advance */
+       if (next_segno != segno) {
+               curseg->next_segno = next_segno;
+               change_curseg(sbi, type, true);
+       }
+       curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) &
+                                       (sbi->blocks_per_seg - 1);
+
+       /* rewrite node page */
+       set_page_writeback(page);
+       submit_write_page(sbi, page, new_blkaddr, NODE);
+       f2fs_submit_bio(sbi, NODE, true);
+       refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
+
+       locate_dirty_segment(sbi, old_cursegno);
+       locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+
+       mutex_unlock(&sit_i->sentry_lock);
+       mutex_unlock(&curseg->curseg_mutex);
+}
+
+static int read_compacted_summaries(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       struct curseg_info *seg_i;
+       unsigned char *kaddr;
+       struct page *page;
+       block_t start;
+       int i, j, offset;
+
+       start = start_sum_block(sbi);
+
+       page = get_meta_page(sbi, start++);
+       kaddr = (unsigned char *)page_address(page);
+
+       /* Step 1: restore nat cache */
+       seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
+
+       /* Step 2: restore sit cache */
+       seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
+       memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
+                                               SUM_JOURNAL_SIZE);
+       offset = 2 * SUM_JOURNAL_SIZE;
+
+       /* Step 3: restore summary entries */
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+               unsigned short blk_off;
+               unsigned int segno;
+
+               seg_i = CURSEG_I(sbi, i);
+               segno = le32_to_cpu(ckpt->cur_data_segno[i]);
+               blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
+               seg_i->next_segno = segno;
+               reset_curseg(sbi, i, 0);
+               seg_i->alloc_type = ckpt->alloc_type[i];
+               seg_i->next_blkoff = blk_off;
+
+               if (seg_i->alloc_type == SSR)
+                       blk_off = sbi->blocks_per_seg;
+
+               for (j = 0; j < blk_off; j++) {
+                       struct f2fs_summary *s;
+                       s = (struct f2fs_summary *)(kaddr + offset);
+                       seg_i->sum_blk->entries[j] = *s;
+                       offset += SUMMARY_SIZE;
+                       if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
+                                               SUM_FOOTER_SIZE)
+                               continue;
+
+                       f2fs_put_page(page, 1);
+                       page = NULL;
+
+                       page = get_meta_page(sbi, start++);
+                       kaddr = (unsigned char *)page_address(page);
+                       offset = 0;
+               }
+       }
+       f2fs_put_page(page, 1);
+       return 0;
+}
+
+static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
+{
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       struct f2fs_summary_block *sum;
+       struct curseg_info *curseg;
+       struct page *new;
+       unsigned short blk_off;
+       unsigned int segno = 0;
+       block_t blk_addr = 0;
+
+       /* get segment number and block addr */
+       if (IS_DATASEG(type)) {
+               segno = le32_to_cpu(ckpt->cur_data_segno[type]);
+               blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
+                                                       CURSEG_HOT_DATA]);
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+                       blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
+               else
+                       blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
+       } else {
+               segno = le32_to_cpu(ckpt->cur_node_segno[type -
+                                                       CURSEG_HOT_NODE]);
+               blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
+                                                       CURSEG_HOT_NODE]);
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG))
+                       blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
+                                                       type - CURSEG_HOT_NODE);
+               else
+                       blk_addr = GET_SUM_BLOCK(sbi, segno);
+       }
+
+       new = get_meta_page(sbi, blk_addr);
+       sum = (struct f2fs_summary_block *)page_address(new);
+
+       if (IS_NODESEG(type)) {
+               if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) {
+                       struct f2fs_summary *ns = &sum->entries[0];
+                       int i;
+                       for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
+                               ns->version = 0;
+                               ns->ofs_in_node = 0;
+                       }
+               } else {
+                       if (restore_node_summary(sbi, segno, sum)) {
+                               f2fs_put_page(new, 1);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       /* set uncompleted segment to curseg */
+       curseg = CURSEG_I(sbi, type);
+       mutex_lock(&curseg->curseg_mutex);
+       memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE);
+       curseg->next_segno = segno;
+       reset_curseg(sbi, type, 0);
+       curseg->alloc_type = ckpt->alloc_type[type];
+       curseg->next_blkoff = blk_off;
+       mutex_unlock(&curseg->curseg_mutex);
+       f2fs_put_page(new, 1);
+       return 0;
+}
+
+static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
+{
+       int type = CURSEG_HOT_DATA;
+
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) {
+               /* restore for compacted data summary */
+               if (read_compacted_summaries(sbi))
+                       return -EINVAL;
+               type = CURSEG_HOT_NODE;
+       }
+
+       for (; type <= CURSEG_COLD_NODE; type++)
+               if (read_normal_summaries(sbi, type))
+                       return -EINVAL;
+       return 0;
+}
+
+static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
+{
+       struct page *page;
+       unsigned char *kaddr;
+       struct f2fs_summary *summary;
+       struct curseg_info *seg_i;
+       int written_size = 0;
+       int i, j;
+
+       page = grab_meta_page(sbi, blkaddr++);
+       kaddr = (unsigned char *)page_address(page);
+
+       /* Step 1: write nat cache */
+       seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
+       memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE);
+       written_size += SUM_JOURNAL_SIZE;
+
+       /* Step 2: write sit cache */
+       seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
+       memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits,
+                                               SUM_JOURNAL_SIZE);
+       written_size += SUM_JOURNAL_SIZE;
+
+       set_page_dirty(page);
+
+       /* Step 3: write summary entries */
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+               unsigned short blkoff;
+               seg_i = CURSEG_I(sbi, i);
+               if (sbi->ckpt->alloc_type[i] == SSR)
+                       blkoff = sbi->blocks_per_seg;
+               else
+                       blkoff = curseg_blkoff(sbi, i);
+
+               for (j = 0; j < blkoff; j++) {
+                       if (!page) {
+                               page = grab_meta_page(sbi, blkaddr++);
+                               kaddr = (unsigned char *)page_address(page);
+                               written_size = 0;
+                       }
+                       summary = (struct f2fs_summary *)(kaddr + written_size);
+                       *summary = seg_i->sum_blk->entries[j];
+                       written_size += SUMMARY_SIZE;
+                       set_page_dirty(page);
+
+                       if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
+                                                       SUM_FOOTER_SIZE)
+                               continue;
+
+                       f2fs_put_page(page, 1);
+                       page = NULL;
+               }
+       }
+       if (page)
+               f2fs_put_page(page, 1);
+}
+
+static void write_normal_summaries(struct f2fs_sb_info *sbi,
+                                       block_t blkaddr, int type)
+{
+       int i, end;
+       if (IS_DATASEG(type))
+               end = type + NR_CURSEG_DATA_TYPE;
+       else
+               end = type + NR_CURSEG_NODE_TYPE;
+
+       for (i = type; i < end; i++) {
+               struct curseg_info *sum = CURSEG_I(sbi, i);
+               mutex_lock(&sum->curseg_mutex);
+               write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type));
+               mutex_unlock(&sum->curseg_mutex);
+       }
+}
+
+void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG))
+               write_compacted_summaries(sbi, start_blk);
+       else
+               write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
+}
+
+void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+       if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG))
+               write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
+       return;
+}
+
+int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type,
+                                       unsigned int val, int alloc)
+{
+       int i;
+
+       if (type == NAT_JOURNAL) {
+               for (i = 0; i < nats_in_cursum(sum); i++) {
+                       if (le32_to_cpu(nid_in_journal(sum, i)) == val)
+                               return i;
+               }
+               if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES)
+                       return update_nats_in_cursum(sum, 1);
+       } else if (type == SIT_JOURNAL) {
+               for (i = 0; i < sits_in_cursum(sum); i++)
+                       if (le32_to_cpu(segno_in_journal(sum, i)) == val)
+                               return i;
+               if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES)
+                       return update_sits_in_cursum(sum, 1);
+       }
+       return -1;
+}
+
+static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
+                                       unsigned int segno)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
+       block_t blk_addr = sit_i->sit_base_addr + offset;
+
+       check_seg_range(sbi, segno);
+
+       /* calculate sit block address */
+       if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+               blk_addr += sit_i->sit_blocks;
+
+       return get_meta_page(sbi, blk_addr);
+}
+
+static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
+                                       unsigned int start)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct page *src_page, *dst_page;
+       pgoff_t src_off, dst_off;
+       void *src_addr, *dst_addr;
+
+       src_off = current_sit_addr(sbi, start);
+       dst_off = next_sit_addr(sbi, src_off);
+
+       /* get current sit block page without lock */
+       src_page = get_meta_page(sbi, src_off);
+       dst_page = grab_meta_page(sbi, dst_off);
+       BUG_ON(PageDirty(src_page));
+
+       src_addr = page_address(src_page);
+       dst_addr = page_address(dst_page);
+       memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
+
+       set_page_dirty(dst_page);
+       f2fs_put_page(src_page, 1);
+
+       set_to_next_sit(sit_i, start);
+
+       return dst_page;
+}
+
+static bool flush_sits_in_journal(struct f2fs_sb_info *sbi)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       int i;
+
+       /*
+        * If the journal area in the current summary is full of sit entries,
+        * all the sit entries will be flushed. Otherwise the sit entries
+        * are not able to replace with newly hot sit entries.
+        */
+       if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) {
+               for (i = sits_in_cursum(sum) - 1; i >= 0; i--) {
+                       unsigned int segno;
+                       segno = le32_to_cpu(segno_in_journal(sum, i));
+                       __mark_sit_entry_dirty(sbi, segno);
+               }
+               update_sits_in_cursum(sum, -sits_in_cursum(sum));
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * CP calls this function, which flushes SIT entries including sit_journal,
+ * and moves prefree segs to free segs.
+ */
+void flush_sit_entries(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned long *bitmap = sit_i->dirty_sentries_bitmap;
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       unsigned long nsegs = TOTAL_SEGS(sbi);
+       struct page *page = NULL;
+       struct f2fs_sit_block *raw_sit = NULL;
+       unsigned int start = 0, end = 0;
+       unsigned int segno = -1;
+       bool flushed;
+
+       mutex_lock(&curseg->curseg_mutex);
+       mutex_lock(&sit_i->sentry_lock);
+
+       /*
+        * "flushed" indicates whether sit entries in journal are flushed
+        * to the SIT area or not.
+        */
+       flushed = flush_sits_in_journal(sbi);
+
+       while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) {
+               struct seg_entry *se = get_seg_entry(sbi, segno);
+               int sit_offset, offset;
+
+               sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
+
+               if (flushed)
+                       goto to_sit_page;
+
+               offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1);
+               if (offset >= 0) {
+                       segno_in_journal(sum, offset) = cpu_to_le32(segno);
+                       seg_info_to_raw_sit(se, &sit_in_journal(sum, offset));
+                       goto flush_done;
+               }
+to_sit_page:
+               if (!page || (start > segno) || (segno > end)) {
+                       if (page) {
+                               f2fs_put_page(page, 1);
+                               page = NULL;
+                       }
+
+                       start = START_SEGNO(sit_i, segno);
+                       end = start + SIT_ENTRY_PER_BLOCK - 1;
+
+                       /* read sit block that will be updated */
+                       page = get_next_sit_page(sbi, start);
+                       raw_sit = page_address(page);
+               }
+
+               /* udpate entry in SIT block */
+               seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]);
+flush_done:
+               __clear_bit(segno, bitmap);
+               sit_i->dirty_sentries--;
+       }
+       mutex_unlock(&sit_i->sentry_lock);
+       mutex_unlock(&curseg->curseg_mutex);
+
+       /* writeout last modified SIT block */
+       f2fs_put_page(page, 1);
+
+       set_prefree_as_free_segments(sbi);
+}
+
+static int build_sit_info(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       struct sit_info *sit_i;
+       unsigned int sit_segs, start;
+       char *src_bitmap, *dst_bitmap;
+       unsigned int bitmap_size;
+
+       /* allocate memory for SIT information */
+       sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL);
+       if (!sit_i)
+               return -ENOMEM;
+
+       SM_I(sbi)->sit_info = sit_i;
+
+       sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry));
+       if (!sit_i->sentries)
+               return -ENOMEM;
+
+       bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!sit_i->dirty_sentries_bitmap)
+               return -ENOMEM;
+
+       for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+               sit_i->sentries[start].cur_valid_map
+                       = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
+               sit_i->sentries[start].ckpt_valid_map
+                       = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
+               if (!sit_i->sentries[start].cur_valid_map
+                               || !sit_i->sentries[start].ckpt_valid_map)
+                       return -ENOMEM;
+       }
+
+       if (sbi->segs_per_sec > 1) {
+               sit_i->sec_entries = vzalloc(sbi->total_sections *
+                                       sizeof(struct sec_entry));
+               if (!sit_i->sec_entries)
+                       return -ENOMEM;
+       }
+
+       /* get information related with SIT */
+       sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1;
+
+       /* setup SIT bitmap from ckeckpoint pack */
+       bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
+       src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
+
+       dst_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!dst_bitmap)
+               return -ENOMEM;
+       memcpy(dst_bitmap, src_bitmap, bitmap_size);
+
+       /* init SIT information */
+       sit_i->s_ops = &default_salloc_ops;
+
+       sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr);
+       sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
+       sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count);
+       sit_i->sit_bitmap = dst_bitmap;
+       sit_i->bitmap_size = bitmap_size;
+       sit_i->dirty_sentries = 0;
+       sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
+       sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
+       sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec;
+       mutex_init(&sit_i->sentry_lock);
+       return 0;
+}
+
+static int build_free_segmap(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_sm_info *sm_info = SM_I(sbi);
+       struct free_segmap_info *free_i;
+       unsigned int bitmap_size, sec_bitmap_size;
+
+       /* allocate memory for free segmap information */
+       free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL);
+       if (!free_i)
+               return -ENOMEM;
+
+       SM_I(sbi)->free_info = free_i;
+
+       bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL);
+       if (!free_i->free_segmap)
+               return -ENOMEM;
+
+       sec_bitmap_size = f2fs_bitmap_size(sbi->total_sections);
+       free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL);
+       if (!free_i->free_secmap)
+               return -ENOMEM;
+
+       /* set all segments as dirty temporarily */
+       memset(free_i->free_segmap, 0xff, bitmap_size);
+       memset(free_i->free_secmap, 0xff, sec_bitmap_size);
+
+       /* init free segmap information */
+       free_i->start_segno =
+               (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr);
+       free_i->free_segments = 0;
+       free_i->free_sections = 0;
+       rwlock_init(&free_i->segmap_lock);
+       return 0;
+}
+
+static int build_curseg(struct f2fs_sb_info *sbi)
+{
+       struct curseg_info *array;
+       int i;
+
+       array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
+       if (!array)
+               return -ENOMEM;
+
+       SM_I(sbi)->curseg_array = array;
+
+       for (i = 0; i < NR_CURSEG_TYPE; i++) {
+               mutex_init(&array[i].curseg_mutex);
+               array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
+               if (!array[i].sum_blk)
+                       return -ENOMEM;
+               array[i].segno = NULL_SEGNO;
+               array[i].next_blkoff = 0;
+       }
+       return restore_curseg_summaries(sbi);
+}
+
+static void build_sit_entries(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+       struct f2fs_summary_block *sum = curseg->sum_blk;
+       unsigned int start;
+
+       for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+               struct seg_entry *se = &sit_i->sentries[start];
+               struct f2fs_sit_block *sit_blk;
+               struct f2fs_sit_entry sit;
+               struct page *page;
+               int i;
+
+               mutex_lock(&curseg->curseg_mutex);
+               for (i = 0; i < sits_in_cursum(sum); i++) {
+                       if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
+                               sit = sit_in_journal(sum, i);
+                               mutex_unlock(&curseg->curseg_mutex);
+                               goto got_it;
+                       }
+               }
+               mutex_unlock(&curseg->curseg_mutex);
+               page = get_current_sit_page(sbi, start);
+               sit_blk = (struct f2fs_sit_block *)page_address(page);
+               sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
+               f2fs_put_page(page, 1);
+got_it:
+               check_block_count(sbi, start, &sit);
+               seg_info_from_raw_sit(se, &sit);
+               if (sbi->segs_per_sec > 1) {
+                       struct sec_entry *e = get_sec_entry(sbi, start);
+                       e->valid_blocks += se->valid_blocks;
+               }
+       }
+}
+
+static void init_free_segmap(struct f2fs_sb_info *sbi)
+{
+       unsigned int start;
+       int type;
+
+       for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+               struct seg_entry *sentry = get_seg_entry(sbi, start);
+               if (!sentry->valid_blocks)
+                       __set_free(sbi, start);
+       }
+
+       /* set use the current segments */
+       for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) {
+               struct curseg_info *curseg_t = CURSEG_I(sbi, type);
+               __set_test_and_inuse(sbi, curseg_t->segno);
+       }
+}
+
+static void init_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int segno = 0, offset = 0;
+       unsigned short valid_blocks;
+
+       while (segno < TOTAL_SEGS(sbi)) {
+               /* find dirty segment based on free segmap */
+               segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset);
+               if (segno >= TOTAL_SEGS(sbi))
+                       break;
+               offset = segno + 1;
+               valid_blocks = get_valid_blocks(sbi, segno, 0);
+               if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks)
+                       continue;
+               mutex_lock(&dirty_i->seglist_lock);
+               __locate_dirty_segment(sbi, segno, DIRTY);
+               mutex_unlock(&dirty_i->seglist_lock);
+       }
+}
+
+static int init_victim_segmap(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+       dirty_i->victim_segmap[FG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
+       dirty_i->victim_segmap[BG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!dirty_i->victim_segmap[FG_GC] || !dirty_i->victim_segmap[BG_GC])
+               return -ENOMEM;
+       return 0;
+}
+
+static int build_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i;
+       unsigned int bitmap_size, i;
+
+       /* allocate memory for dirty segments list information */
+       dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL);
+       if (!dirty_i)
+               return -ENOMEM;
+
+       SM_I(sbi)->dirty_info = dirty_i;
+       mutex_init(&dirty_i->seglist_lock);
+
+       bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+       for (i = 0; i < NR_DIRTY_TYPE; i++) {
+               dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL);
+               if (!dirty_i->dirty_segmap[i])
+                       return -ENOMEM;
+       }
+
+       init_dirty_segmap(sbi);
+       return init_victim_segmap(sbi);
+}
+
+/*
+ * Update min, max modified time for cost-benefit GC algorithm
+ */
+static void init_min_max_mtime(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int segno;
+
+       mutex_lock(&sit_i->sentry_lock);
+
+       sit_i->min_mtime = LLONG_MAX;
+
+       for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+               unsigned int i;
+               unsigned long long mtime = 0;
+
+               for (i = 0; i < sbi->segs_per_sec; i++)
+                       mtime += get_seg_entry(sbi, segno + i)->mtime;
+
+               mtime = div_u64(mtime, sbi->segs_per_sec);
+
+               if (sit_i->min_mtime > mtime)
+                       sit_i->min_mtime = mtime;
+       }
+       sit_i->max_mtime = get_mtime(sbi);
+       mutex_unlock(&sit_i->sentry_lock);
+}
+
+int build_segment_manager(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+       struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+       struct f2fs_sm_info *sm_info;
+       int err;
+
+       sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL);
+       if (!sm_info)
+               return -ENOMEM;
+
+       /* init sm info */
+       sbi->sm_info = sm_info;
+       INIT_LIST_HEAD(&sm_info->wblist_head);
+       spin_lock_init(&sm_info->wblist_lock);
+       sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+       sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
+       sm_info->segment_count = le32_to_cpu(raw_super->segment_count);
+       sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
+       sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
+       sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main);
+       sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+
+       err = build_sit_info(sbi);
+       if (err)
+               return err;
+       err = build_free_segmap(sbi);
+       if (err)
+               return err;
+       err = build_curseg(sbi);
+       if (err)
+               return err;
+
+       /* reinit free segmap based on SIT */
+       build_sit_entries(sbi);
+
+       init_free_segmap(sbi);
+       err = build_dirty_segmap(sbi);
+       if (err)
+               return err;
+
+       init_min_max_mtime(sbi);
+       return 0;
+}
+
+static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
+               enum dirty_type dirty_type)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+       mutex_lock(&dirty_i->seglist_lock);
+       kfree(dirty_i->dirty_segmap[dirty_type]);
+       dirty_i->nr_dirty[dirty_type] = 0;
+       mutex_unlock(&dirty_i->seglist_lock);
+}
+
+void reset_victim_segmap(struct f2fs_sb_info *sbi)
+{
+       unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+       memset(DIRTY_I(sbi)->victim_segmap[FG_GC], 0, bitmap_size);
+}
+
+static void destroy_victim_segmap(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+       kfree(dirty_i->victim_segmap[FG_GC]);
+       kfree(dirty_i->victim_segmap[BG_GC]);
+}
+
+static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       int i;
+
+       if (!dirty_i)
+               return;
+
+       /* discard pre-free/dirty segments list */
+       for (i = 0; i < NR_DIRTY_TYPE; i++)
+               discard_dirty_segmap(sbi, i);
+
+       destroy_victim_segmap(sbi);
+       SM_I(sbi)->dirty_info = NULL;
+       kfree(dirty_i);
+}
+
+static void destroy_curseg(struct f2fs_sb_info *sbi)
+{
+       struct curseg_info *array = SM_I(sbi)->curseg_array;
+       int i;
+
+       if (!array)
+               return;
+       SM_I(sbi)->curseg_array = NULL;
+       for (i = 0; i < NR_CURSEG_TYPE; i++)
+               kfree(array[i].sum_blk);
+       kfree(array);
+}
+
+static void destroy_free_segmap(struct f2fs_sb_info *sbi)
+{
+       struct free_segmap_info *free_i = SM_I(sbi)->free_info;
+       if (!free_i)
+               return;
+       SM_I(sbi)->free_info = NULL;
+       kfree(free_i->free_segmap);
+       kfree(free_i->free_secmap);
+       kfree(free_i);
+}
+
+static void destroy_sit_info(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int start;
+
+       if (!sit_i)
+               return;
+
+       if (sit_i->sentries) {
+               for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+                       kfree(sit_i->sentries[start].cur_valid_map);
+                       kfree(sit_i->sentries[start].ckpt_valid_map);
+               }
+       }
+       vfree(sit_i->sentries);
+       vfree(sit_i->sec_entries);
+       kfree(sit_i->dirty_sentries_bitmap);
+
+       SM_I(sbi)->sit_info = NULL;
+       kfree(sit_i->sit_bitmap);
+       kfree(sit_i);
+}
+
+void destroy_segment_manager(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_sm_info *sm_info = SM_I(sbi);
+       destroy_dirty_segmap(sbi);
+       destroy_curseg(sbi);
+       destroy_free_segmap(sbi);
+       destroy_sit_info(sbi);
+       sbi->sm_info = NULL;
+       kfree(sm_info);
+}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
new file mode 100644 (file)
index 0000000..66a288a
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+ * fs/f2fs/segment.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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.
+ */
+/* constant macro */
+#define NULL_SEGNO                     ((unsigned int)(~0))
+
+/* V: Logical segment # in volume, R: Relative segment # in main area */
+#define GET_L2R_SEGNO(free_i, segno)   (segno - free_i->start_segno)
+#define GET_R2L_SEGNO(free_i, segno)   (segno + free_i->start_segno)
+
+#define IS_DATASEG(t)                                                  \
+       ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) ||           \
+       (t == CURSEG_WARM_DATA))
+
+#define IS_NODESEG(t)                                                  \
+       ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) ||           \
+       (t == CURSEG_WARM_NODE))
+
+#define IS_CURSEG(sbi, segno)                                          \
+       ((segno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||    \
+        (segno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||   \
+        (segno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||   \
+        (segno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||    \
+        (segno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||   \
+        (segno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
+
+#define IS_CURSEC(sbi, secno)                                          \
+       ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /              \
+         sbi->segs_per_sec) || \
+        (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /             \
+         sbi->segs_per_sec) || \
+        (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /             \
+         sbi->segs_per_sec) || \
+        (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /              \
+         sbi->segs_per_sec) || \
+        (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /             \
+         sbi->segs_per_sec) || \
+        (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /             \
+         sbi->segs_per_sec))   \
+
+#define START_BLOCK(sbi, segno)                                                \
+       (SM_I(sbi)->seg0_blkaddr +                                      \
+        (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg))
+#define NEXT_FREE_BLKADDR(sbi, curseg)                                 \
+       (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff)
+
+#define MAIN_BASE_BLOCK(sbi)   (SM_I(sbi)->main_blkaddr)
+
+#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr)                            \
+       ((blk_addr) - SM_I(sbi)->seg0_blkaddr)
+#define GET_SEGNO_FROM_SEG0(sbi, blk_addr)                             \
+       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
+#define GET_SEGNO(sbi, blk_addr)                                       \
+       (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ?          \
+       NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),                 \
+               GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
+#define GET_SECNO(sbi, segno)                                  \
+       ((segno) / sbi->segs_per_sec)
+#define GET_ZONENO_FROM_SEGNO(sbi, segno)                              \
+       ((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
+
+#define GET_SUM_BLOCK(sbi, segno)                              \
+       ((sbi->sm_info->ssa_blkaddr) + segno)
+
+#define GET_SUM_TYPE(footer) ((footer)->entry_type)
+#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
+
+#define SIT_ENTRY_OFFSET(sit_i, segno)                                 \
+       (segno % sit_i->sents_per_block)
+#define SIT_BLOCK_OFFSET(sit_i, segno)                                 \
+       (segno / SIT_ENTRY_PER_BLOCK)
+#define        START_SEGNO(sit_i, segno)               \
+       (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK)
+#define f2fs_bitmap_size(nr)                   \
+       (BITS_TO_LONGS(nr) * sizeof(unsigned long))
+#define TOTAL_SEGS(sbi)        (SM_I(sbi)->main_segments)
+
+#define SECTOR_FROM_BLOCK(sbi, blk_addr)                               \
+       (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
+
+/* during checkpoint, bio_private is used to synchronize the last bio */
+struct bio_private {
+       struct f2fs_sb_info *sbi;
+       bool is_sync;
+       void *wait;
+};
+
+/*
+ * indicate a block allocation direction: RIGHT and LEFT.
+ * RIGHT means allocating new sections towards the end of volume.
+ * LEFT means the opposite direction.
+ */
+enum {
+       ALLOC_RIGHT = 0,
+       ALLOC_LEFT
+};
+
+/*
+ * In the victim_sel_policy->alloc_mode, there are two block allocation modes.
+ * LFS writes data sequentially with cleaning operations.
+ * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations.
+ */
+enum {
+       LFS = 0,
+       SSR
+};
+
+/*
+ * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes.
+ * GC_CB is based on cost-benefit algorithm.
+ * GC_GREEDY is based on greedy algorithm.
+ */
+enum {
+       GC_CB = 0,
+       GC_GREEDY
+};
+
+/*
+ * BG_GC means the background cleaning job.
+ * FG_GC means the on-demand cleaning job.
+ */
+enum {
+       BG_GC = 0,
+       FG_GC
+};
+
+/* for a function parameter to select a victim segment */
+struct victim_sel_policy {
+       int alloc_mode;                 /* LFS or SSR */
+       int gc_mode;                    /* GC_CB or GC_GREEDY */
+       unsigned long *dirty_segmap;    /* dirty segment bitmap */
+       unsigned int offset;            /* last scanned bitmap offset */
+       unsigned int ofs_unit;          /* bitmap search unit */
+       unsigned int min_cost;          /* minimum cost */
+       unsigned int min_segno;         /* segment # having min. cost */
+};
+
+struct seg_entry {
+       unsigned short valid_blocks;    /* # of valid blocks */
+       unsigned char *cur_valid_map;   /* validity bitmap of blocks */
+       /*
+        * # of valid blocks and the validity bitmap stored in the the last
+        * checkpoint pack. This information is used by the SSR mode.
+        */
+       unsigned short ckpt_valid_blocks;
+       unsigned char *ckpt_valid_map;
+       unsigned char type;             /* segment type like CURSEG_XXX_TYPE */
+       unsigned long long mtime;       /* modification time of the segment */
+};
+
+struct sec_entry {
+       unsigned int valid_blocks;      /* # of valid blocks in a section */
+};
+
+struct segment_allocation {
+       void (*allocate_segment)(struct f2fs_sb_info *, int, bool);
+};
+
+struct sit_info {
+       const struct segment_allocation *s_ops;
+
+       block_t sit_base_addr;          /* start block address of SIT area */
+       block_t sit_blocks;             /* # of blocks used by SIT area */
+       block_t written_valid_blocks;   /* # of valid blocks in main area */
+       char *sit_bitmap;               /* SIT bitmap pointer */
+       unsigned int bitmap_size;       /* SIT bitmap size */
+
+       unsigned long *dirty_sentries_bitmap;   /* bitmap for dirty sentries */
+       unsigned int dirty_sentries;            /* # of dirty sentries */
+       unsigned int sents_per_block;           /* # of SIT entries per block */
+       struct mutex sentry_lock;               /* to protect SIT cache */
+       struct seg_entry *sentries;             /* SIT segment-level cache */
+       struct sec_entry *sec_entries;          /* SIT section-level cache */
+
+       /* for cost-benefit algorithm in cleaning procedure */
+       unsigned long long elapsed_time;        /* elapsed time after mount */
+       unsigned long long mounted_time;        /* mount time */
+       unsigned long long min_mtime;           /* min. modification time */
+       unsigned long long max_mtime;           /* max. modification time */
+};
+
+struct free_segmap_info {
+       unsigned int start_segno;       /* start segment number logically */
+       unsigned int free_segments;     /* # of free segments */
+       unsigned int free_sections;     /* # of free sections */
+       rwlock_t segmap_lock;           /* free segmap lock */
+       unsigned long *free_segmap;     /* free segment bitmap */
+       unsigned long *free_secmap;     /* free section bitmap */
+};
+
+/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
+enum dirty_type {
+       DIRTY_HOT_DATA,         /* dirty segments assigned as hot data logs */
+       DIRTY_WARM_DATA,        /* dirty segments assigned as warm data logs */
+       DIRTY_COLD_DATA,        /* dirty segments assigned as cold data logs */
+       DIRTY_HOT_NODE,         /* dirty segments assigned as hot node logs */
+       DIRTY_WARM_NODE,        /* dirty segments assigned as warm node logs */
+       DIRTY_COLD_NODE,        /* dirty segments assigned as cold node logs */
+       DIRTY,                  /* to count # of dirty segments */
+       PRE,                    /* to count # of entirely obsolete segments */
+       NR_DIRTY_TYPE
+};
+
+struct dirty_seglist_info {
+       const struct victim_selection *v_ops;   /* victim selction operation */
+       unsigned long *dirty_segmap[NR_DIRTY_TYPE];
+       struct mutex seglist_lock;              /* lock for segment bitmaps */
+       int nr_dirty[NR_DIRTY_TYPE];            /* # of dirty segments */
+       unsigned long *victim_segmap[2];        /* BG_GC, FG_GC */
+};
+
+/* victim selection function for cleaning and SSR */
+struct victim_selection {
+       int (*get_victim)(struct f2fs_sb_info *, unsigned int *,
+                                                       int, int, char);
+};
+
+/* for active log information */
+struct curseg_info {
+       struct mutex curseg_mutex;              /* lock for consistency */
+       struct f2fs_summary_block *sum_blk;     /* cached summary block */
+       unsigned char alloc_type;               /* current allocation type */
+       unsigned int segno;                     /* current segment number */
+       unsigned short next_blkoff;             /* next block offset to write */
+       unsigned int zone;                      /* current zone number */
+       unsigned int next_segno;                /* preallocated segment */
+};
+
+/*
+ * inline functions
+ */
+static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
+{
+       return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
+}
+
+static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
+                                               unsigned int segno)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       return &sit_i->sentries[segno];
+}
+
+static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
+                                               unsigned int segno)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       return &sit_i->sec_entries[GET_SECNO(sbi, segno)];
+}
+
+static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
+                               unsigned int segno, int section)
+{
+       /*
+        * In order to get # of valid blocks in a section instantly from many
+        * segments, f2fs manages two counting structures separately.
+        */
+       if (section > 1)
+               return get_sec_entry(sbi, segno)->valid_blocks;
+       else
+               return get_seg_entry(sbi, segno)->valid_blocks;
+}
+
+static inline void seg_info_from_raw_sit(struct seg_entry *se,
+                                       struct f2fs_sit_entry *rs)
+{
+       se->valid_blocks = GET_SIT_VBLOCKS(rs);
+       se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
+       memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+       memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+       se->type = GET_SIT_TYPE(rs);
+       se->mtime = le64_to_cpu(rs->mtime);
+}
+
+static inline void seg_info_to_raw_sit(struct seg_entry *se,
+                                       struct f2fs_sit_entry *rs)
+{
+       unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) |
+                                       se->valid_blocks;
+       rs->vblocks = cpu_to_le16(raw_vblocks);
+       memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
+       memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+       se->ckpt_valid_blocks = se->valid_blocks;
+       rs->mtime = cpu_to_le64(se->mtime);
+}
+
+static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
+               unsigned int max, unsigned int segno)
+{
+       unsigned int ret;
+       read_lock(&free_i->segmap_lock);
+       ret = find_next_bit(free_i->free_segmap, max, segno);
+       read_unlock(&free_i->segmap_lock);
+       return ret;
+}
+
+static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int secno = segno / sbi->segs_per_sec;
+       unsigned int start_segno = secno * sbi->segs_per_sec;
+       unsigned int next;
+
+       write_lock(&free_i->segmap_lock);
+       clear_bit(segno, free_i->free_segmap);
+       free_i->free_segments++;
+
+       next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno);
+       if (next >= start_segno + sbi->segs_per_sec) {
+               clear_bit(secno, free_i->free_secmap);
+               free_i->free_sections++;
+       }
+       write_unlock(&free_i->segmap_lock);
+}
+
+static inline void __set_inuse(struct f2fs_sb_info *sbi,
+               unsigned int segno)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int secno = segno / sbi->segs_per_sec;
+       set_bit(segno, free_i->free_segmap);
+       free_i->free_segments--;
+       if (!test_and_set_bit(secno, free_i->free_secmap))
+               free_i->free_sections--;
+}
+
+static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
+               unsigned int segno)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int secno = segno / sbi->segs_per_sec;
+       unsigned int start_segno = secno * sbi->segs_per_sec;
+       unsigned int next;
+
+       write_lock(&free_i->segmap_lock);
+       if (test_and_clear_bit(segno, free_i->free_segmap)) {
+               free_i->free_segments++;
+
+               next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi),
+                                                               start_segno);
+               if (next >= start_segno + sbi->segs_per_sec) {
+                       if (test_and_clear_bit(secno, free_i->free_secmap))
+                               free_i->free_sections++;
+               }
+       }
+       write_unlock(&free_i->segmap_lock);
+}
+
+static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
+               unsigned int segno)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int secno = segno / sbi->segs_per_sec;
+       write_lock(&free_i->segmap_lock);
+       if (!test_and_set_bit(segno, free_i->free_segmap)) {
+               free_i->free_segments--;
+               if (!test_and_set_bit(secno, free_i->free_secmap))
+                       free_i->free_sections--;
+       }
+       write_unlock(&free_i->segmap_lock);
+}
+
+static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
+               void *dst_addr)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
+}
+
+static inline block_t written_block_count(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       block_t vblocks;
+
+       mutex_lock(&sit_i->sentry_lock);
+       vblocks = sit_i->written_valid_blocks;
+       mutex_unlock(&sit_i->sentry_lock);
+
+       return vblocks;
+}
+
+static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int free_segs;
+
+       read_lock(&free_i->segmap_lock);
+       free_segs = free_i->free_segments;
+       read_unlock(&free_i->segmap_lock);
+
+       return free_segs;
+}
+
+static inline int reserved_segments(struct f2fs_sb_info *sbi)
+{
+       return SM_I(sbi)->reserved_segments;
+}
+
+static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
+{
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int free_secs;
+
+       read_lock(&free_i->segmap_lock);
+       free_secs = free_i->free_sections;
+       read_unlock(&free_i->segmap_lock);
+
+       return free_secs;
+}
+
+static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
+{
+       return DIRTY_I(sbi)->nr_dirty[PRE];
+}
+
+static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
+{
+       return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
+               DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
+               DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
+               DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
+               DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
+               DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
+}
+
+static inline int overprovision_segments(struct f2fs_sb_info *sbi)
+{
+       return SM_I(sbi)->ovp_segments;
+}
+
+static inline int overprovision_sections(struct f2fs_sb_info *sbi)
+{
+       return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec;
+}
+
+static inline int reserved_sections(struct f2fs_sb_info *sbi)
+{
+       return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec;
+}
+
+static inline bool need_SSR(struct f2fs_sb_info *sbi)
+{
+       return (free_sections(sbi) < overprovision_sections(sbi));
+}
+
+static inline int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       return DIRTY_I(sbi)->v_ops->get_victim(sbi,
+                               &(curseg)->next_segno, BG_GC, type, SSR);
+}
+
+static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi)
+{
+       unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) *
+                       sbi->segs_per_sec;
+       int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
+                       >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+       int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
+                       >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+
+       if (sbi->por_doing)
+               return false;
+
+       if (free_sections(sbi) <= (node_secs + 2 * dent_secs +
+                                               reserved_sections(sbi)))
+               return true;
+       return false;
+}
+
+static inline int utilization(struct f2fs_sb_info *sbi)
+{
+       return (long int)valid_user_blocks(sbi) * 100 /
+                       (long int)sbi->user_block_count;
+}
+
+/*
+ * Sometimes f2fs may be better to drop out-of-place update policy.
+ * So, if fs utilization is over MIN_IPU_UTIL, then f2fs tries to write
+ * data in the original place likewise other traditional file systems.
+ * But, currently set 100 in percentage, which means it is disabled.
+ * See below need_inplace_update().
+ */
+#define MIN_IPU_UTIL           100
+static inline bool need_inplace_update(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       if (S_ISDIR(inode->i_mode))
+               return false;
+       if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL)
+               return true;
+       return false;
+}
+
+static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
+               int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       return curseg->segno;
+}
+
+static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
+               int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       return curseg->alloc_type;
+}
+
+static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       return curseg->next_blkoff;
+}
+
+static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+       unsigned int end_segno = SM_I(sbi)->segment_count - 1;
+       BUG_ON(segno > end_segno);
+}
+
+/*
+ * This function is used for only debugging.
+ * NOTE: In future, we have to remove this function.
+ */
+static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
+{
+       struct f2fs_sm_info *sm_info = SM_I(sbi);
+       block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg;
+       block_t start_addr = sm_info->seg0_blkaddr;
+       block_t end_addr = start_addr + total_blks - 1;
+       BUG_ON(blk_addr < start_addr);
+       BUG_ON(blk_addr > end_addr);
+}
+
+/*
+ * Summary block is always treated as invalid block
+ */
+static inline void check_block_count(struct f2fs_sb_info *sbi,
+               int segno, struct f2fs_sit_entry *raw_sit)
+{
+       struct f2fs_sm_info *sm_info = SM_I(sbi);
+       unsigned int end_segno = sm_info->segment_count - 1;
+       int valid_blocks = 0;
+       int i;
+
+       /* check segment usage */
+       BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg);
+
+       /* check boundary of a given segment number */
+       BUG_ON(segno > end_segno);
+
+       /* check bitmap with valid block count */
+       for (i = 0; i < sbi->blocks_per_seg; i++)
+               if (f2fs_test_bit(i, raw_sit->valid_map))
+                       valid_blocks++;
+       BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
+}
+
+static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
+                                               unsigned int start)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start);
+       block_t blk_addr = sit_i->sit_base_addr + offset;
+
+       check_seg_range(sbi, start);
+
+       /* calculate sit block address */
+       if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+               blk_addr += sit_i->sit_blocks;
+
+       return blk_addr;
+}
+
+static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
+                                               pgoff_t block_addr)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       block_addr -= sit_i->sit_base_addr;
+       if (block_addr < sit_i->sit_blocks)
+               block_addr += sit_i->sit_blocks;
+       else
+               block_addr -= sit_i->sit_blocks;
+
+       return block_addr + sit_i->sit_base_addr;
+}
+
+static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
+{
+       unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start);
+
+       if (f2fs_test_bit(block_off, sit_i->sit_bitmap))
+               f2fs_clear_bit(block_off, sit_i->sit_bitmap);
+       else
+               f2fs_set_bit(block_off, sit_i->sit_bitmap);
+}
+
+static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
+{
+       struct sit_info *sit_i = SIT_I(sbi);
+       return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec -
+                                               sit_i->mounted_time;
+}
+
+static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
+                       unsigned int ofs_in_node, unsigned char version)
+{
+       sum->nid = cpu_to_le32(nid);
+       sum->ofs_in_node = cpu_to_le16(ofs_in_node);
+       sum->version = version;
+}
+
+static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
+{
+       return __start_cp_addr(sbi) +
+               le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
+{
+       return __start_cp_addr(sbi) +
+               le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
+                               - (base + 1) + type;
+}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
new file mode 100644 (file)
index 0000000..37fad04
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ * fs/f2fs/super.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/statfs.h>
+#include <linux/proc_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/backing-dev.h>
+#include <linux/kthread.h>
+#include <linux/parser.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/random.h>
+#include <linux/exportfs.h>
+#include <linux/f2fs_fs.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "xattr.h"
+
+static struct kmem_cache *f2fs_inode_cachep;
+
+enum {
+       Opt_gc_background_off,
+       Opt_disable_roll_forward,
+       Opt_discard,
+       Opt_noheap,
+       Opt_nouser_xattr,
+       Opt_noacl,
+       Opt_active_logs,
+       Opt_disable_ext_identify,
+       Opt_err,
+};
+
+static match_table_t f2fs_tokens = {
+       {Opt_gc_background_off, "background_gc_off"},
+       {Opt_disable_roll_forward, "disable_roll_forward"},
+       {Opt_discard, "discard"},
+       {Opt_noheap, "no_heap"},
+       {Opt_nouser_xattr, "nouser_xattr"},
+       {Opt_noacl, "noacl"},
+       {Opt_active_logs, "active_logs=%u"},
+       {Opt_disable_ext_identify, "disable_ext_identify"},
+       {Opt_err, NULL},
+};
+
+void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       va_start(args, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+       printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf);
+       va_end(args);
+}
+
+static void init_once(void *foo)
+{
+       struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
+
+       inode_init_once(&fi->vfs_inode);
+}
+
+static struct inode *f2fs_alloc_inode(struct super_block *sb)
+{
+       struct f2fs_inode_info *fi;
+
+       fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_NOFS | __GFP_ZERO);
+       if (!fi)
+               return NULL;
+
+       init_once((void *) fi);
+
+       /* Initilize f2fs-specific inode info */
+       fi->vfs_inode.i_version = 1;
+       atomic_set(&fi->dirty_dents, 0);
+       fi->i_current_depth = 1;
+       fi->i_advise = 0;
+       rwlock_init(&fi->ext.ext_lock);
+
+       set_inode_flag(fi, FI_NEW_INODE);
+
+       return &fi->vfs_inode;
+}
+
+static void f2fs_i_callback(struct rcu_head *head)
+{
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
+}
+
+static void f2fs_destroy_inode(struct inode *inode)
+{
+       call_rcu(&inode->i_rcu, f2fs_i_callback);
+}
+
+static void f2fs_put_super(struct super_block *sb)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+       f2fs_destroy_stats(sbi);
+       stop_gc_thread(sbi);
+
+       write_checkpoint(sbi, false, true);
+
+       iput(sbi->node_inode);
+       iput(sbi->meta_inode);
+
+       /* destroy f2fs internal modules */
+       destroy_node_manager(sbi);
+       destroy_segment_manager(sbi);
+
+       kfree(sbi->ckpt);
+
+       sb->s_fs_info = NULL;
+       brelse(sbi->raw_super_buf);
+       kfree(sbi);
+}
+
+int f2fs_sync_fs(struct super_block *sb, int sync)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+       if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
+               return 0;
+
+       if (sync)
+               write_checkpoint(sbi, false, false);
+       else
+               f2fs_balance_fs(sbi);
+
+       return 0;
+}
+
+static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       struct super_block *sb = dentry->d_sb;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+       block_t total_count, user_block_count, start_count, ovp_count;
+
+       total_count = le64_to_cpu(sbi->raw_super->block_count);
+       user_block_count = sbi->user_block_count;
+       start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr);
+       ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
+       buf->f_type = F2FS_SUPER_MAGIC;
+       buf->f_bsize = sbi->blocksize;
+
+       buf->f_blocks = total_count - start_count;
+       buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
+       buf->f_bavail = user_block_count - valid_user_blocks(sbi);
+
+       buf->f_files = sbi->total_node_count;
+       buf->f_ffree = sbi->total_node_count - valid_inode_count(sbi);
+
+       buf->f_namelen = F2FS_MAX_NAME_LEN;
+       buf->f_fsid.val[0] = (u32)id;
+       buf->f_fsid.val[1] = (u32)(id >> 32);
+
+       return 0;
+}
+
+static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
+
+       if (test_opt(sbi, BG_GC))
+               seq_puts(seq, ",background_gc_on");
+       else
+               seq_puts(seq, ",background_gc_off");
+       if (test_opt(sbi, DISABLE_ROLL_FORWARD))
+               seq_puts(seq, ",disable_roll_forward");
+       if (test_opt(sbi, DISCARD))
+               seq_puts(seq, ",discard");
+       if (test_opt(sbi, NOHEAP))
+               seq_puts(seq, ",no_heap_alloc");
+#ifdef CONFIG_F2FS_FS_XATTR
+       if (test_opt(sbi, XATTR_USER))
+               seq_puts(seq, ",user_xattr");
+       else
+               seq_puts(seq, ",nouser_xattr");
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+       if (test_opt(sbi, POSIX_ACL))
+               seq_puts(seq, ",acl");
+       else
+               seq_puts(seq, ",noacl");
+#endif
+       if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
+               seq_puts(seq, ",disable_ext_indentify");
+
+       seq_printf(seq, ",active_logs=%u", sbi->active_logs);
+
+       return 0;
+}
+
+static struct super_operations f2fs_sops = {
+       .alloc_inode    = f2fs_alloc_inode,
+       .destroy_inode  = f2fs_destroy_inode,
+       .write_inode    = f2fs_write_inode,
+       .show_options   = f2fs_show_options,
+       .evict_inode    = f2fs_evict_inode,
+       .put_super      = f2fs_put_super,
+       .sync_fs        = f2fs_sync_fs,
+       .statfs         = f2fs_statfs,
+};
+
+static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
+               u64 ino, u32 generation)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct inode *inode;
+
+       if (ino < F2FS_ROOT_INO(sbi))
+               return ERR_PTR(-ESTALE);
+
+       /*
+        * f2fs_iget isn't quite right if the inode is currently unallocated!
+        * However f2fs_iget currently does appropriate checks to handle stale
+        * inodes so everything is OK.
+        */
+       inode = f2fs_iget(sb, ino);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (generation && inode->i_generation != generation) {
+               /* we didn't find the right inode.. */
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       return inode;
+}
+
+static struct dentry *f2fs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
+{
+       return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+                                   f2fs_nfs_get_inode);
+}
+
+static struct dentry *f2fs_fh_to_parent(struct super_block *sb, struct fid *fid,
+               int fh_len, int fh_type)
+{
+       return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+                                   f2fs_nfs_get_inode);
+}
+
+static const struct export_operations f2fs_export_ops = {
+       .fh_to_dentry = f2fs_fh_to_dentry,
+       .fh_to_parent = f2fs_fh_to_parent,
+       .get_parent = f2fs_get_parent,
+};
+
+static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi,
+                               char *options)
+{
+       substring_t args[MAX_OPT_ARGS];
+       char *p;
+       int arg = 0;
+
+       if (!options)
+               return 0;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               int token;
+               if (!*p)
+                       continue;
+               /*
+                * Initialize args struct so we know whether arg was
+                * found; some options take optional arguments.
+                */
+               args[0].to = args[0].from = NULL;
+               token = match_token(p, f2fs_tokens, args);
+
+               switch (token) {
+               case Opt_gc_background_off:
+                       clear_opt(sbi, BG_GC);
+                       break;
+               case Opt_disable_roll_forward:
+                       set_opt(sbi, DISABLE_ROLL_FORWARD);
+                       break;
+               case Opt_discard:
+                       set_opt(sbi, DISCARD);
+                       break;
+               case Opt_noheap:
+                       set_opt(sbi, NOHEAP);
+                       break;
+#ifdef CONFIG_F2FS_FS_XATTR
+               case Opt_nouser_xattr:
+                       clear_opt(sbi, XATTR_USER);
+                       break;
+#else
+               case Opt_nouser_xattr:
+                       f2fs_msg(sb, KERN_INFO,
+                               "nouser_xattr options not supported");
+                       break;
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+               case Opt_noacl:
+                       clear_opt(sbi, POSIX_ACL);
+                       break;
+#else
+               case Opt_noacl:
+                       f2fs_msg(sb, KERN_INFO, "noacl options not supported");
+                       break;
+#endif
+               case Opt_active_logs:
+                       if (args->from && match_int(args, &arg))
+                               return -EINVAL;
+                       if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
+                               return -EINVAL;
+                       sbi->active_logs = arg;
+                       break;
+               case Opt_disable_ext_identify:
+                       set_opt(sbi, DISABLE_EXT_IDENTIFY);
+                       break;
+               default:
+                       f2fs_msg(sb, KERN_ERR,
+                               "Unrecognized mount option \"%s\" or missing value",
+                               p);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static loff_t max_file_size(unsigned bits)
+{
+       loff_t result = ADDRS_PER_INODE;
+       loff_t leaf_count = ADDRS_PER_BLOCK;
+
+       /* two direct node blocks */
+       result += (leaf_count * 2);
+
+       /* two indirect node blocks */
+       leaf_count *= NIDS_PER_BLOCK;
+       result += (leaf_count * 2);
+
+       /* one double indirect node block */
+       leaf_count *= NIDS_PER_BLOCK;
+       result += leaf_count;
+
+       result <<= bits;
+       return result;
+}
+
+static int sanity_check_raw_super(struct super_block *sb,
+                       struct f2fs_super_block *raw_super)
+{
+       unsigned int blocksize;
+
+       if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
+               f2fs_msg(sb, KERN_INFO,
+                       "Magic Mismatch, valid(0x%x) - read(0x%x)",
+                       F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
+               return 1;
+       }
+
+       /* Currently, support only 4KB block size */
+       blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
+       if (blocksize != PAGE_CACHE_SIZE) {
+               f2fs_msg(sb, KERN_INFO,
+                       "Invalid blocksize (%u), supports only 4KB\n",
+                       blocksize);
+               return 1;
+       }
+       if (le32_to_cpu(raw_super->log_sectorsize) !=
+                                       F2FS_LOG_SECTOR_SIZE) {
+               f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize");
+               return 1;
+       }
+       if (le32_to_cpu(raw_super->log_sectors_per_block) !=
+                                       F2FS_LOG_SECTORS_PER_BLOCK) {
+               f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block");
+               return 1;
+       }
+       return 0;
+}
+
+static int sanity_check_ckpt(struct f2fs_super_block *raw_super,
+                               struct f2fs_checkpoint *ckpt)
+{
+       unsigned int total, fsmeta;
+
+       total = le32_to_cpu(raw_super->segment_count);
+       fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
+       fsmeta += le32_to_cpu(raw_super->segment_count_sit);
+       fsmeta += le32_to_cpu(raw_super->segment_count_nat);
+       fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
+       fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
+
+       if (fsmeta >= total)
+               return 1;
+       return 0;
+}
+
+static void init_sb_info(struct f2fs_sb_info *sbi)
+{
+       struct f2fs_super_block *raw_super = sbi->raw_super;
+       int i;
+
+       sbi->log_sectors_per_block =
+               le32_to_cpu(raw_super->log_sectors_per_block);
+       sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
+       sbi->blocksize = 1 << sbi->log_blocksize;
+       sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+       sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
+       sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
+       sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
+       sbi->total_sections = le32_to_cpu(raw_super->section_count);
+       sbi->total_node_count =
+               (le32_to_cpu(raw_super->segment_count_nat) / 2)
+                       * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
+       sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
+       sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
+       sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
+
+       for (i = 0; i < NR_COUNT_TYPE; i++)
+               atomic_set(&sbi->nr_pages[i], 0);
+}
+
+static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct f2fs_sb_info *sbi;
+       struct f2fs_super_block *raw_super;
+       struct buffer_head *raw_super_buf;
+       struct inode *root;
+       long err = -EINVAL;
+       int i;
+
+       /* allocate memory for f2fs-specific super block info */
+       sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
+       if (!sbi)
+               return -ENOMEM;
+
+       /* set a block size */
+       if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) {
+               f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
+               goto free_sbi;
+       }
+
+       /* read f2fs raw super block */
+       raw_super_buf = sb_bread(sb, 0);
+       if (!raw_super_buf) {
+               err = -EIO;
+               f2fs_msg(sb, KERN_ERR, "unable to read superblock");
+               goto free_sbi;
+       }
+       raw_super = (struct f2fs_super_block *)
+                       ((char *)raw_super_buf->b_data + F2FS_SUPER_OFFSET);
+
+       /* init some FS parameters */
+       sbi->active_logs = NR_CURSEG_TYPE;
+
+       set_opt(sbi, BG_GC);
+
+#ifdef CONFIG_F2FS_FS_XATTR
+       set_opt(sbi, XATTR_USER);
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+       set_opt(sbi, POSIX_ACL);
+#endif
+       /* parse mount options */
+       if (parse_options(sb, sbi, (char *)data))
+               goto free_sb_buf;
+
+       /* sanity checking of raw super */
+       if (sanity_check_raw_super(sb, raw_super)) {
+               f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem");
+               goto free_sb_buf;
+       }
+
+       sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize));
+       sb->s_max_links = F2FS_LINK_MAX;
+       get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+
+       sb->s_op = &f2fs_sops;
+       sb->s_xattr = f2fs_xattr_handlers;
+       sb->s_export_op = &f2fs_export_ops;
+       sb->s_magic = F2FS_SUPER_MAGIC;
+       sb->s_fs_info = sbi;
+       sb->s_time_gran = 1;
+       sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+               (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
+       memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
+
+       /* init f2fs-specific super block info */
+       sbi->sb = sb;
+       sbi->raw_super = raw_super;
+       sbi->raw_super_buf = raw_super_buf;
+       mutex_init(&sbi->gc_mutex);
+       mutex_init(&sbi->write_inode);
+       mutex_init(&sbi->writepages);
+       mutex_init(&sbi->cp_mutex);
+       for (i = 0; i < NR_LOCK_TYPE; i++)
+               mutex_init(&sbi->fs_lock[i]);
+       sbi->por_doing = 0;
+       spin_lock_init(&sbi->stat_lock);
+       init_rwsem(&sbi->bio_sem);
+       init_sb_info(sbi);
+
+       /* get an inode for meta space */
+       sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
+       if (IS_ERR(sbi->meta_inode)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode");
+               err = PTR_ERR(sbi->meta_inode);
+               goto free_sb_buf;
+       }
+
+       err = get_valid_checkpoint(sbi);
+       if (err) {
+               f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");
+               goto free_meta_inode;
+       }
+
+       /* sanity checking of checkpoint */
+       err = -EINVAL;
+       if (sanity_check_ckpt(raw_super, sbi->ckpt)) {
+               f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint");
+               goto free_cp;
+       }
+
+       sbi->total_valid_node_count =
+                               le32_to_cpu(sbi->ckpt->valid_node_count);
+       sbi->total_valid_inode_count =
+                               le32_to_cpu(sbi->ckpt->valid_inode_count);
+       sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
+       sbi->total_valid_block_count =
+                               le64_to_cpu(sbi->ckpt->valid_block_count);
+       sbi->last_valid_block_count = sbi->total_valid_block_count;
+       sbi->alloc_valid_block_count = 0;
+       INIT_LIST_HEAD(&sbi->dir_inode_list);
+       spin_lock_init(&sbi->dir_inode_lock);
+
+       init_orphan_info(sbi);
+
+       /* setup f2fs internal modules */
+       err = build_segment_manager(sbi);
+       if (err) {
+               f2fs_msg(sb, KERN_ERR,
+                       "Failed to initialize F2FS segment manager");
+               goto free_sm;
+       }
+       err = build_node_manager(sbi);
+       if (err) {
+               f2fs_msg(sb, KERN_ERR,
+                       "Failed to initialize F2FS node manager");
+               goto free_nm;
+       }
+
+       build_gc_manager(sbi);
+
+       /* get an inode for node space */
+       sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
+       if (IS_ERR(sbi->node_inode)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read node inode");
+               err = PTR_ERR(sbi->node_inode);
+               goto free_nm;
+       }
+
+       /* if there are nt orphan nodes free them */
+       err = -EINVAL;
+       if (recover_orphan_inodes(sbi))
+               goto free_node_inode;
+
+       /* read root inode and dentry */
+       root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
+       if (IS_ERR(root)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read root inode");
+               err = PTR_ERR(root);
+               goto free_node_inode;
+       }
+       if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
+               goto free_root_inode;
+
+       sb->s_root = d_make_root(root); /* allocate root dentry */
+       if (!sb->s_root) {
+               err = -ENOMEM;
+               goto free_root_inode;
+       }
+
+       /* recover fsynced data */
+       if (!test_opt(sbi, DISABLE_ROLL_FORWARD))
+               recover_fsync_data(sbi);
+
+       /* After POR, we can run background GC thread */
+       err = start_gc_thread(sbi);
+       if (err)
+               goto fail;
+
+       err = f2fs_build_stats(sbi);
+       if (err)
+               goto fail;
+
+       return 0;
+fail:
+       stop_gc_thread(sbi);
+free_root_inode:
+       dput(sb->s_root);
+       sb->s_root = NULL;
+free_node_inode:
+       iput(sbi->node_inode);
+free_nm:
+       destroy_node_manager(sbi);
+free_sm:
+       destroy_segment_manager(sbi);
+free_cp:
+       kfree(sbi->ckpt);
+free_meta_inode:
+       make_bad_inode(sbi->meta_inode);
+       iput(sbi->meta_inode);
+free_sb_buf:
+       brelse(raw_super_buf);
+free_sbi:
+       kfree(sbi);
+       return err;
+}
+
+static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
+                       const char *dev_name, void *data)
+{
+       return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
+}
+
+static struct file_system_type f2fs_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "f2fs",
+       .mount          = f2fs_mount,
+       .kill_sb        = kill_block_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+
+static int __init init_inodecache(void)
+{
+       f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
+                       sizeof(struct f2fs_inode_info), NULL);
+       if (f2fs_inode_cachep == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+static void destroy_inodecache(void)
+{
+       /*
+        * Make sure all delayed rcu free inodes are flushed before we
+        * destroy cache.
+        */
+       rcu_barrier();
+       kmem_cache_destroy(f2fs_inode_cachep);
+}
+
+static int __init init_f2fs_fs(void)
+{
+       int err;
+
+       err = init_inodecache();
+       if (err)
+               goto fail;
+       err = create_node_manager_caches();
+       if (err)
+               goto fail;
+       err = create_gc_caches();
+       if (err)
+               goto fail;
+       err = create_checkpoint_caches();
+       if (err)
+               goto fail;
+       err = register_filesystem(&f2fs_fs_type);
+       if (err)
+               goto fail;
+       f2fs_create_root_stats();
+fail:
+       return err;
+}
+
+static void __exit exit_f2fs_fs(void)
+{
+       f2fs_destroy_root_stats();
+       unregister_filesystem(&f2fs_fs_type);
+       destroy_checkpoint_caches();
+       destroy_gc_caches();
+       destroy_node_manager_caches();
+       destroy_inodecache();
+}
+
+module_init(init_f2fs_fs)
+module_exit(exit_f2fs_fs)
+
+MODULE_AUTHOR("Samsung Electronics's Praesto Team");
+MODULE_DESCRIPTION("Flash Friendly File System");
+MODULE_LICENSE("GPL");
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
new file mode 100644 (file)
index 0000000..8038c04
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * fs/f2fs/xattr.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/xattr.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko <luka.renko@hermes.si>.
+ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
+ *  Red Hat 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/rwsem.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "xattr.h"
+
+static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       int total_len, prefix_len = 0;
+       const char *prefix = NULL;
+
+       switch (type) {
+       case F2FS_XATTR_INDEX_USER:
+               if (!test_opt(sbi, XATTR_USER))
+                       return -EOPNOTSUPP;
+               prefix = XATTR_USER_PREFIX;
+               prefix_len = XATTR_USER_PREFIX_LEN;
+               break;
+       case F2FS_XATTR_INDEX_TRUSTED:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               prefix = XATTR_TRUSTED_PREFIX;
+               prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       total_len = prefix_len + name_len + 1;
+       if (list && total_len <= list_size) {
+               memcpy(list, prefix, prefix_len);
+               memcpy(list+prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return total_len;
+}
+
+static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+
+       switch (type) {
+       case F2FS_XATTR_INDEX_USER:
+               if (!test_opt(sbi, XATTR_USER))
+                       return -EOPNOTSUPP;
+               break;
+       case F2FS_XATTR_INDEX_TRUSTED:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return f2fs_getxattr(dentry->d_inode, type, name,
+                       buffer, size);
+}
+
+static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+
+       switch (type) {
+       case F2FS_XATTR_INDEX_USER:
+               if (!test_opt(sbi, XATTR_USER))
+                       return -EOPNOTSUPP;
+               break;
+       case F2FS_XATTR_INDEX_TRUSTED:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       return f2fs_setxattr(dentry->d_inode, type, name, value, size);
+}
+
+static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
+{
+       const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
+       size_t size;
+
+       if (type != F2FS_XATTR_INDEX_ADVISE)
+               return 0;
+
+       size = strlen(xname) + 1;
+       if (list && size <= list_size)
+               memcpy(list, xname, size);
+       return size;
+}
+
+static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
+{
+       struct inode *inode = dentry->d_inode;
+
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+
+       *((char *)buffer) = F2FS_I(inode)->i_advise;
+       return sizeof(char);
+}
+
+static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+{
+       struct inode *inode = dentry->d_inode;
+
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!inode_owner_or_capable(inode))
+               return -EPERM;
+       if (value == NULL)
+               return -EINVAL;
+
+       F2FS_I(inode)->i_advise |= *(char *)value;
+       return 0;
+}
+
+const struct xattr_handler f2fs_xattr_user_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .flags  = F2FS_XATTR_INDEX_USER,
+       .list   = f2fs_xattr_generic_list,
+       .get    = f2fs_xattr_generic_get,
+       .set    = f2fs_xattr_generic_set,
+};
+
+const struct xattr_handler f2fs_xattr_trusted_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .flags  = F2FS_XATTR_INDEX_TRUSTED,
+       .list   = f2fs_xattr_generic_list,
+       .get    = f2fs_xattr_generic_get,
+       .set    = f2fs_xattr_generic_set,
+};
+
+const struct xattr_handler f2fs_xattr_advise_handler = {
+       .prefix = F2FS_SYSTEM_ADVISE_PREFIX,
+       .flags  = F2FS_XATTR_INDEX_ADVISE,
+       .list   = f2fs_xattr_advise_list,
+       .get    = f2fs_xattr_advise_get,
+       .set    = f2fs_xattr_advise_set,
+};
+
+static const struct xattr_handler *f2fs_xattr_handler_map[] = {
+       [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
+#endif
+       [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
+       [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
+};
+
+const struct xattr_handler *f2fs_xattr_handlers[] = {
+       &f2fs_xattr_user_handler,
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+       &f2fs_xattr_acl_access_handler,
+       &f2fs_xattr_acl_default_handler,
+#endif
+       &f2fs_xattr_trusted_handler,
+       &f2fs_xattr_advise_handler,
+       NULL,
+};
+
+static inline const struct xattr_handler *f2fs_xattr_handler(int name_index)
+{
+       const struct xattr_handler *handler = NULL;
+
+       if (name_index > 0 && name_index < ARRAY_SIZE(f2fs_xattr_handler_map))
+               handler = f2fs_xattr_handler_map[name_index];
+       return handler;
+}
+
+int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
+               void *buffer, size_t buffer_size)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       struct f2fs_xattr_entry *entry;
+       struct page *page;
+       void *base_addr;
+       int error = 0, found = 0;
+       size_t value_len, name_len;
+
+       if (name == NULL)
+               return -EINVAL;
+       name_len = strlen(name);
+
+       if (!fi->i_xattr_nid)
+               return -ENODATA;
+
+       page = get_node_page(sbi, fi->i_xattr_nid);
+       base_addr = page_address(page);
+
+       list_for_each_xattr(entry, base_addr) {
+               if (entry->e_name_index != name_index)
+                       continue;
+               if (entry->e_name_len != name_len)
+                       continue;
+               if (!memcmp(entry->e_name, name, name_len)) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found) {
+               error = -ENODATA;
+               goto cleanup;
+       }
+
+       value_len = le16_to_cpu(entry->e_value_size);
+
+       if (buffer && value_len > buffer_size) {
+               error = -ERANGE;
+               goto cleanup;
+       }
+
+       if (buffer) {
+               char *pval = entry->e_name + entry->e_name_len;
+               memcpy(buffer, pval, value_len);
+       }
+       error = value_len;
+
+cleanup:
+       f2fs_put_page(page, 1);
+       return error;
+}
+
+ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+{
+       struct inode *inode = dentry->d_inode;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       struct f2fs_xattr_entry *entry;
+       struct page *page;
+       void *base_addr;
+       int error = 0;
+       size_t rest = buffer_size;
+
+       if (!fi->i_xattr_nid)
+               return 0;
+
+       page = get_node_page(sbi, fi->i_xattr_nid);
+       base_addr = page_address(page);
+
+       list_for_each_xattr(entry, base_addr) {
+               const struct xattr_handler *handler =
+                       f2fs_xattr_handler(entry->e_name_index);
+               size_t size;
+
+               if (!handler)
+                       continue;
+
+               size = handler->list(dentry, buffer, rest, entry->e_name,
+                               entry->e_name_len, handler->flags);
+               if (buffer && size > rest) {
+                       error = -ERANGE;
+                       goto cleanup;
+               }
+
+               if (buffer)
+                       buffer += size;
+               rest -= size;
+       }
+       error = buffer_size - rest;
+cleanup:
+       f2fs_put_page(page, 1);
+       return error;
+}
+
+int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+                                       const void *value, size_t value_len)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       struct f2fs_xattr_header *header = NULL;
+       struct f2fs_xattr_entry *here, *last;
+       struct page *page;
+       void *base_addr;
+       int error, found, free, newsize;
+       size_t name_len;
+       char *pval;
+
+       if (name == NULL)
+               return -EINVAL;
+       name_len = strlen(name);
+
+       if (value == NULL)
+               value_len = 0;
+
+       if (name_len > 255 || value_len > MAX_VALUE_LEN)
+               return -ERANGE;
+
+       f2fs_balance_fs(sbi);
+
+       mutex_lock_op(sbi, NODE_NEW);
+       if (!fi->i_xattr_nid) {
+               /* Allocate new attribute block */
+               struct dnode_of_data dn;
+
+               if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
+                       mutex_unlock_op(sbi, NODE_NEW);
+                       return -ENOSPC;
+               }
+               set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
+               mark_inode_dirty(inode);
+
+               page = new_node_page(&dn, XATTR_NODE_OFFSET);
+               if (IS_ERR(page)) {
+                       alloc_nid_failed(sbi, fi->i_xattr_nid);
+                       fi->i_xattr_nid = 0;
+                       mutex_unlock_op(sbi, NODE_NEW);
+                       return PTR_ERR(page);
+               }
+
+               alloc_nid_done(sbi, fi->i_xattr_nid);
+               base_addr = page_address(page);
+               header = XATTR_HDR(base_addr);
+               header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
+               header->h_refcount = cpu_to_le32(1);
+       } else {
+               /* The inode already has an extended attribute block. */
+               page = get_node_page(sbi, fi->i_xattr_nid);
+               if (IS_ERR(page)) {
+                       mutex_unlock_op(sbi, NODE_NEW);
+                       return PTR_ERR(page);
+               }
+
+               base_addr = page_address(page);
+               header = XATTR_HDR(base_addr);
+       }
+
+       if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
+               error = -EIO;
+               goto cleanup;
+       }
+
+       /* find entry with wanted name. */
+       found = 0;
+       list_for_each_xattr(here, base_addr) {
+               if (here->e_name_index != name_index)
+                       continue;
+               if (here->e_name_len != name_len)
+                       continue;
+               if (!memcmp(here->e_name, name, name_len)) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       last = here;
+
+       while (!IS_XATTR_LAST_ENTRY(last))
+               last = XATTR_NEXT_ENTRY(last);
+
+       newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
+                       name_len + value_len);
+
+       /* 1. Check space */
+       if (value) {
+               /* If value is NULL, it is remove operation.
+                * In case of update operation, we caculate free.
+                */
+               free = MIN_OFFSET - ((char *)last - (char *)header);
+               if (found)
+                       free = free - ENTRY_SIZE(here);
+
+               if (free < newsize) {
+                       error = -ENOSPC;
+                       goto cleanup;
+               }
+       }
+
+       /* 2. Remove old entry */
+       if (found) {
+               /* If entry is found, remove old entry.
+                * If not found, remove operation is not needed.
+                */
+               struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
+               int oldsize = ENTRY_SIZE(here);
+
+               memmove(here, next, (char *)last - (char *)next);
+               last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
+               memset(last, 0, oldsize);
+       }
+
+       /* 3. Write new entry */
+       if (value) {
+               /* Before we come here, old entry is removed.
+                * We just write new entry. */
+               memset(last, 0, newsize);
+               last->e_name_index = name_index;
+               last->e_name_len = name_len;
+               memcpy(last->e_name, name, name_len);
+               pval = last->e_name + name_len;
+               memcpy(pval, value, value_len);
+               last->e_value_size = cpu_to_le16(value_len);
+       }
+
+       set_page_dirty(page);
+       f2fs_put_page(page, 1);
+
+       if (is_inode_flag_set(fi, FI_ACL_MODE)) {
+               inode->i_mode = fi->i_acl_mode;
+               inode->i_ctime = CURRENT_TIME;
+               clear_inode_flag(fi, FI_ACL_MODE);
+       }
+       f2fs_write_inode(inode, NULL);
+       mutex_unlock_op(sbi, NODE_NEW);
+
+       return 0;
+cleanup:
+       f2fs_put_page(page, 1);
+       mutex_unlock_op(sbi, NODE_NEW);
+       return error;
+}
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
new file mode 100644 (file)
index 0000000..49c9558
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * fs/f2fs/xattr.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/xattr.h
+ *
+ * On-disk format of extended attributes for the ext2 filesystem.
+ *
+ * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.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 __F2FS_XATTR_H__
+#define __F2FS_XATTR_H__
+
+#include <linux/init.h>
+#include <linux/xattr.h>
+
+/* Magic value in attribute blocks */
+#define F2FS_XATTR_MAGIC                0xF2F52011
+
+/* Maximum number of references to one attribute block */
+#define F2FS_XATTR_REFCOUNT_MAX         1024
+
+/* Name indexes */
+#define F2FS_SYSTEM_ADVISE_PREFIX              "system.advise"
+#define F2FS_XATTR_INDEX_USER                  1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS      2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT     3
+#define F2FS_XATTR_INDEX_TRUSTED               4
+#define F2FS_XATTR_INDEX_LUSTRE                        5
+#define F2FS_XATTR_INDEX_SECURITY              6
+#define F2FS_XATTR_INDEX_ADVISE                        7
+
+struct f2fs_xattr_header {
+       __le32  h_magic;        /* magic number for identification */
+       __le32  h_refcount;     /* reference count */
+       __u32   h_reserved[4];  /* zero right now */
+};
+
+struct f2fs_xattr_entry {
+       __u8    e_name_index;
+       __u8    e_name_len;
+       __le16  e_value_size;   /* size of attribute value */
+       char    e_name[0];      /* attribute name */
+};
+
+#define XATTR_HDR(ptr)         ((struct f2fs_xattr_header *)(ptr))
+#define XATTR_ENTRY(ptr)       ((struct f2fs_xattr_entry *)(ptr))
+#define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr)+1))
+#define XATTR_ROUND            (3)
+
+#define XATTR_ALIGN(size)      ((size + XATTR_ROUND) & ~XATTR_ROUND)
+
+#define ENTRY_SIZE(entry) (XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + \
+                       entry->e_name_len + le16_to_cpu(entry->e_value_size)))
+
+#define XATTR_NEXT_ENTRY(entry)        ((struct f2fs_xattr_entry *)((char *)(entry) +\
+                       ENTRY_SIZE(entry)))
+
+#define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+
+#define list_for_each_xattr(entry, addr) \
+               for (entry = XATTR_FIRST_ENTRY(addr);\
+                               !IS_XATTR_LAST_ENTRY(entry);\
+                               entry = XATTR_NEXT_ENTRY(entry))
+
+
+#define MIN_OFFSET     XATTR_ALIGN(PAGE_SIZE - \
+                       sizeof(struct node_footer) - \
+                       sizeof(__u32))
+
+#define MAX_VALUE_LEN  (MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \
+                       sizeof(struct f2fs_xattr_entry))
+
+/*
+ * On-disk structure of f2fs_xattr
+ * We use only 1 block for xattr.
+ *
+ * +--------------------+
+ * | f2fs_xattr_header  |
+ * |                    |
+ * +--------------------+
+ * | f2fs_xattr_entry   |
+ * | .e_name_index = 1  |
+ * | .e_name_len = 3    |
+ * | .e_value_size = 14 |
+ * | .e_name = "foo"    |
+ * | "value_of_xattr"   |<- value_offs = e_name + e_name_len
+ * +--------------------+
+ * | f2fs_xattr_entry   |
+ * | .e_name_index = 4  |
+ * | .e_name = "bar"    |
+ * +--------------------+
+ * |                    |
+ * |        Free        |
+ * |                    |
+ * +--------------------+<- MIN_OFFSET
+ * |   node_footer      |
+ * | (nid, ino, offset) |
+ * +--------------------+
+ *
+ **/
+
+#ifdef CONFIG_F2FS_FS_XATTR
+extern const struct xattr_handler f2fs_xattr_user_handler;
+extern const struct xattr_handler f2fs_xattr_trusted_handler;
+extern const struct xattr_handler f2fs_xattr_acl_access_handler;
+extern const struct xattr_handler f2fs_xattr_acl_default_handler;
+extern const struct xattr_handler f2fs_xattr_advise_handler;
+
+extern const struct xattr_handler *f2fs_xattr_handlers[];
+
+extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+               const void *value, size_t value_len);
+extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
+               void *buffer, size_t buffer_size);
+extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
+               size_t buffer_size);
+
+#else
+
+#define f2fs_xattr_handlers    NULL
+static inline int f2fs_setxattr(struct inode *inode, int name_index,
+       const char *name, const void *value, size_t value_len)
+{
+       return -EOPNOTSUPP;
+}
+static inline int f2fs_getxattr(struct inode *inode, int name_index,
+               const char *name, void *buffer, size_t buffer_size)
+{
+       return -EOPNOTSUPP;
+}
+static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
+               size_t buffer_size)
+{
+       return -EOPNOTSUPP;
+}
+#endif
+
+#endif /* __F2FS_XATTR_H__ */
index 2a182342442edc772bdfafc11eb55d6639db6805..58bf744dbf392b51d05fedf979118cddd5b50663 100644 (file)
@@ -461,8 +461,7 @@ static int fat_parse_short(struct super_block *sb,
 }
 
 /*
- * Return values: negative -> error, 0 -> not found, positive -> found,
- * value is the total amount of slots, including the shortname entry.
+ * Return values: negative -> error/not found, 0 -> found.
  */
 int fat_search_long(struct inode *inode, const unsigned char *name,
                    int name_len, struct fat_slot_info *sinfo)
@@ -1255,7 +1254,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
 
        sinfo->nr_slots = nr_slots;
 
-       /* First stage: search free direcotry entries */
+       /* First stage: search free directory entries */
        free_slots = nr_bhs = 0;
        bh = prev = NULL;
        pos = 0;
index 35806813ea4ee3bb425795c52c0719f64979203a..f8f491677a4ac6cbce51a3acb3e6d78e54235cc1 100644 (file)
@@ -1344,7 +1344,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
        if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
                if (!silent)
-                       fat_msg(sb, KERN_ERR, "bogus directroy-entries per block"
+                       fat_msg(sb, KERN_ERR, "bogus directory-entries per block"
                               " (%u)", sbi->dir_entries);
                brelse(bh);
                goto out_invalid;
index 5eb600dc43a9064257a2485dde54f8a0ce332972..359d307b5507a5efd72f41c78434f5f9d35b2558 100644 (file)
@@ -135,6 +135,10 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
                }
                if (ret < 0)
                        return ret;
+               /*
+                * FIXME:Although we can add this cache, fat_cache_add() is
+                * assuming to be called after linear search with fat_cache_id.
+                */
 //             fat_cache_add(inode, new_fclus, new_dclus);
        } else {
                MSDOS_I(inode)->i_start = new_dclus;
index cccdc874bb55df99eb10f89f33a7bcb1f92ddc99..999ff5c3cab0edacd585447132180d5c35554e3c 100644 (file)
@@ -52,7 +52,7 @@ static long do_sys_name_to_handle(struct path *path,
        handle_bytes = handle_dwords * sizeof(u32);
        handle->handle_bytes = handle_bytes;
        if ((handle->handle_bytes > f_handle.handle_bytes) ||
-           (retval == 255) || (retval == -ENOSPC)) {
+           (retval == FILEID_INVALID) || (retval == -ENOSPC)) {
                /* As per old exportfs_encode_fh documentation
                 * we could return ENOSPC to indicate overflow
                 * But file system returned 255 always. So handle
index 15cb8618e95d0cf6568e8e9dd68b37008ea4d435..2b3570b7caeba28bab8df3a4598fbdfc75fdcfc7 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -490,7 +490,7 @@ void exit_files(struct task_struct *tsk)
        }
 }
 
-static void __devinit fdtable_defer_list_init(int cpu)
+static void fdtable_defer_list_init(int cpu)
 {
        struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
        spin_lock_init(&fddef->lock);
index a72bf9ddd0d2b56781bc84b591f45ff4e4627a93..de9e9653d611f57c9a1ae6a0f8c34ed25cd961c0 100644 (file)
@@ -458,8 +458,8 @@ void mark_files_ro(struct super_block *sb)
                spin_unlock(&f->f_lock);
                if (file_check_writeable(f) != 0)
                        continue;
+               __mnt_drop_write(f->f_path.mnt);
                file_release_write(f);
-               mnt_drop_write_file(f);
        } while_file_list_for_each_entry;
        lg_global_unlock(&files_lglock);
 }
index 6a3c48abd677f52eb2bd10a5bb89108cd5d89d0a..b52aed1dca97fc5769d43a34f8e51de2e28fd653 100644 (file)
@@ -314,10 +314,10 @@ EXPORT_SYMBOL(fscache_add_cache);
  */
 void fscache_io_error(struct fscache_cache *cache)
 {
-       set_bit(FSCACHE_IOERROR, &cache->flags);
-
-       printk(KERN_ERR "FS-Cache: Cache %s stopped due to I/O error\n",
-              cache->ops->name);
+       if (!test_and_set_bit(FSCACHE_IOERROR, &cache->flags))
+               printk(KERN_ERR "FS-Cache:"
+                      " Cache '%s' stopped due to I/O error\n",
+                      cache->ops->name);
 }
 EXPORT_SYMBOL(fscache_io_error);
 
index 990535071a8aeadf4a67e646b6fdcad86403d63b..8dcb114758e3620e5e631d43201ea5388b3b29f2 100644 (file)
@@ -369,6 +369,66 @@ cant_attach_object:
        return ret;
 }
 
+/*
+ * Invalidate an object.  Callable with spinlocks held.
+ */
+void __fscache_invalidate(struct fscache_cookie *cookie)
+{
+       struct fscache_object *object;
+
+       _enter("{%s}", cookie->def->name);
+
+       fscache_stat(&fscache_n_invalidates);
+
+       /* Only permit invalidation of data files.  Invalidating an index will
+        * require the caller to release all its attachments to the tree rooted
+        * there, and if it's doing that, it may as well just retire the
+        * cookie.
+        */
+       ASSERTCMP(cookie->def->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
+
+       /* We will be updating the cookie too. */
+       BUG_ON(!cookie->def->get_aux);
+
+       /* If there's an object, we tell the object state machine to handle the
+        * invalidation on our behalf, otherwise there's nothing to do.
+        */
+       if (!hlist_empty(&cookie->backing_objects)) {
+               spin_lock(&cookie->lock);
+
+               if (!hlist_empty(&cookie->backing_objects) &&
+                   !test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
+                                     &cookie->flags)) {
+                       object = hlist_entry(cookie->backing_objects.first,
+                                            struct fscache_object,
+                                            cookie_link);
+                       if (object->state < FSCACHE_OBJECT_DYING)
+                               fscache_raise_event(
+                                       object, FSCACHE_OBJECT_EV_INVALIDATE);
+               }
+
+               spin_unlock(&cookie->lock);
+       }
+
+       _leave("");
+}
+EXPORT_SYMBOL(__fscache_invalidate);
+
+/*
+ * Wait for object invalidation to complete.
+ */
+void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
+{
+       _enter("%p", cookie);
+
+       wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
+                   fscache_wait_bit_interruptible,
+                   TASK_UNINTERRUPTIBLE);
+
+       _leave("");
+}
+EXPORT_SYMBOL(__fscache_wait_on_invalidate);
+
 /*
  * update the index entries backing a cookie
  */
@@ -442,16 +502,34 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
 
        event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
 
+try_again:
        spin_lock(&cookie->lock);
 
        /* break links with all the active objects */
        while (!hlist_empty(&cookie->backing_objects)) {
+               int n_reads;
                object = hlist_entry(cookie->backing_objects.first,
                                     struct fscache_object,
                                     cookie_link);
 
                _debug("RELEASE OBJ%x", object->debug_id);
 
+               set_bit(FSCACHE_COOKIE_WAITING_ON_READS, &cookie->flags);
+               n_reads = atomic_read(&object->n_reads);
+               if (n_reads) {
+                       int n_ops = object->n_ops;
+                       int n_in_progress = object->n_in_progress;
+                       spin_unlock(&cookie->lock);
+                       printk(KERN_ERR "FS-Cache:"
+                              " Cookie '%s' still has %d outstanding reads (%d,%d)\n",
+                              cookie->def->name,
+                              n_reads, n_ops, n_in_progress);
+                       wait_on_bit(&cookie->flags, FSCACHE_COOKIE_WAITING_ON_READS,
+                                   fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+                       printk("Wait finished\n");
+                       goto try_again;
+               }
+
                /* detach each cache object from the object cookie */
                spin_lock(&object->lock);
                hlist_del_init(&object->cookie_link);
index f6aad48d38a86153beb9c8ad0b0e0d19b7a9760e..ee38fef4be5173dc43abf6648b5a7cf00037a7ca 100644 (file)
@@ -121,11 +121,18 @@ extern int fscache_submit_exclusive_op(struct fscache_object *,
                                       struct fscache_operation *);
 extern int fscache_submit_op(struct fscache_object *,
                             struct fscache_operation *);
-extern int fscache_cancel_op(struct fscache_operation *);
+extern int fscache_cancel_op(struct fscache_operation *,
+                            void (*)(struct fscache_operation *));
+extern void fscache_cancel_all_ops(struct fscache_object *);
 extern void fscache_abort_object(struct fscache_object *);
 extern void fscache_start_operations(struct fscache_object *);
 extern void fscache_operation_gc(struct work_struct *);
 
+/*
+ * page.c
+ */
+extern void fscache_invalidate_writes(struct fscache_cookie *);
+
 /*
  * proc.c
  */
@@ -194,6 +201,7 @@ extern atomic_t fscache_n_store_vmscan_not_storing;
 extern atomic_t fscache_n_store_vmscan_gone;
 extern atomic_t fscache_n_store_vmscan_busy;
 extern atomic_t fscache_n_store_vmscan_cancelled;
+extern atomic_t fscache_n_store_vmscan_wait;
 
 extern atomic_t fscache_n_marks;
 extern atomic_t fscache_n_uncaches;
@@ -205,6 +213,9 @@ extern atomic_t fscache_n_acquires_ok;
 extern atomic_t fscache_n_acquires_nobufs;
 extern atomic_t fscache_n_acquires_oom;
 
+extern atomic_t fscache_n_invalidates;
+extern atomic_t fscache_n_invalidates_run;
+
 extern atomic_t fscache_n_updates;
 extern atomic_t fscache_n_updates_null;
 extern atomic_t fscache_n_updates_run;
@@ -237,6 +248,7 @@ extern atomic_t fscache_n_cop_alloc_object;
 extern atomic_t fscache_n_cop_lookup_object;
 extern atomic_t fscache_n_cop_lookup_complete;
 extern atomic_t fscache_n_cop_grab_object;
+extern atomic_t fscache_n_cop_invalidate_object;
 extern atomic_t fscache_n_cop_update_object;
 extern atomic_t fscache_n_cop_drop_object;
 extern atomic_t fscache_n_cop_put_object;
@@ -278,6 +290,7 @@ extern const struct file_operations fscache_stats_fops;
 static inline void fscache_raise_event(struct fscache_object *object,
                                       unsigned event)
 {
+       BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS);
        if (!test_and_set_bit(event, &object->events) &&
            test_bit(event, &object->event_mask))
                fscache_enqueue_object(object);
index ebe29c58138085cb1479896771db5054c6b47bfd..f27c89d178855bbe2adfd0aba12a816eae7ab409 100644 (file)
@@ -245,7 +245,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
                   obj->n_in_progress,
                   obj->n_exclusive,
                   atomic_read(&obj->n_reads),
-                  obj->event_mask & FSCACHE_OBJECT_EVENTS_MASK,
+                  obj->event_mask,
                   obj->events,
                   obj->flags,
                   work_busy(&obj->work));
index b6b897c550acfea609acc9f99f0cdd2eaa90b2a3..50d41c1802110b472f93eae0cae5f775d332fd13 100644 (file)
@@ -14,6 +14,7 @@
 
 #define FSCACHE_DEBUG_LEVEL COOKIE
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "internal.h"
 
 const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
@@ -22,6 +23,7 @@ const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
        [FSCACHE_OBJECT_CREATING]       = "OBJECT_CREATING",
        [FSCACHE_OBJECT_AVAILABLE]      = "OBJECT_AVAILABLE",
        [FSCACHE_OBJECT_ACTIVE]         = "OBJECT_ACTIVE",
+       [FSCACHE_OBJECT_INVALIDATING]   = "OBJECT_INVALIDATING",
        [FSCACHE_OBJECT_UPDATING]       = "OBJECT_UPDATING",
        [FSCACHE_OBJECT_DYING]          = "OBJECT_DYING",
        [FSCACHE_OBJECT_LC_DYING]       = "OBJECT_LC_DYING",
@@ -39,6 +41,7 @@ const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = {
        [FSCACHE_OBJECT_CREATING]       = "CRTN",
        [FSCACHE_OBJECT_AVAILABLE]      = "AVBL",
        [FSCACHE_OBJECT_ACTIVE]         = "ACTV",
+       [FSCACHE_OBJECT_INVALIDATING]   = "INVL",
        [FSCACHE_OBJECT_UPDATING]       = "UPDT",
        [FSCACHE_OBJECT_DYING]          = "DYNG",
        [FSCACHE_OBJECT_LC_DYING]       = "LCDY",
@@ -54,6 +57,7 @@ static void fscache_put_object(struct fscache_object *);
 static void fscache_initialise_object(struct fscache_object *);
 static void fscache_lookup_object(struct fscache_object *);
 static void fscache_object_available(struct fscache_object *);
+static void fscache_invalidate_object(struct fscache_object *);
 static void fscache_release_object(struct fscache_object *);
 static void fscache_withdraw_object(struct fscache_object *);
 static void fscache_enqueue_dependents(struct fscache_object *);
@@ -78,6 +82,15 @@ static inline void fscache_done_parent_op(struct fscache_object *object)
        spin_unlock(&parent->lock);
 }
 
+/*
+ * Notify netfs of invalidation completion.
+ */
+static inline void fscache_invalidation_complete(struct fscache_cookie *cookie)
+{
+       if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
+               wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
+}
+
 /*
  * process events that have been sent to an object's state machine
  * - initiates parent lookup
@@ -90,6 +103,7 @@ static void fscache_object_state_machine(struct fscache_object *object)
 {
        enum fscache_object_state new_state;
        struct fscache_cookie *cookie;
+       int event;
 
        ASSERT(object != NULL);
 
@@ -101,7 +115,8 @@ static void fscache_object_state_machine(struct fscache_object *object)
                /* wait for the parent object to become ready */
        case FSCACHE_OBJECT_INIT:
                object->event_mask =
-                       ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED);
+                       FSCACHE_OBJECT_EVENTS_MASK &
+                       ~(1 << FSCACHE_OBJECT_EV_CLEARED);
                fscache_initialise_object(object);
                goto done;
 
@@ -125,6 +140,16 @@ static void fscache_object_state_machine(struct fscache_object *object)
        case FSCACHE_OBJECT_ACTIVE:
                goto active_transit;
 
+               /* Invalidate an object on disk */
+       case FSCACHE_OBJECT_INVALIDATING:
+               clear_bit(FSCACHE_OBJECT_EV_INVALIDATE, &object->events);
+               fscache_stat(&fscache_n_invalidates_run);
+               fscache_stat(&fscache_n_cop_invalidate_object);
+               fscache_invalidate_object(object);
+               fscache_stat_d(&fscache_n_cop_invalidate_object);
+               fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
+               goto active_transit;
+
                /* update the object metadata on disk */
        case FSCACHE_OBJECT_UPDATING:
                clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events);
@@ -251,13 +276,17 @@ static void fscache_object_state_machine(struct fscache_object *object)
 
        /* determine the transition from a lookup state */
 lookup_transit:
-       switch (fls(object->events & object->event_mask) - 1) {
+       event = fls(object->events & object->event_mask) - 1;
+       switch (event) {
        case FSCACHE_OBJECT_EV_WITHDRAW:
        case FSCACHE_OBJECT_EV_RETIRE:
        case FSCACHE_OBJECT_EV_RELEASE:
        case FSCACHE_OBJECT_EV_ERROR:
                new_state = FSCACHE_OBJECT_LC_DYING;
                goto change_state;
+       case FSCACHE_OBJECT_EV_INVALIDATE:
+               new_state = FSCACHE_OBJECT_INVALIDATING;
+               goto change_state;
        case FSCACHE_OBJECT_EV_REQUEUE:
                goto done;
        case -1:
@@ -268,13 +297,17 @@ lookup_transit:
 
        /* determine the transition from an active state */
 active_transit:
-       switch (fls(object->events & object->event_mask) - 1) {
+       event = fls(object->events & object->event_mask) - 1;
+       switch (event) {
        case FSCACHE_OBJECT_EV_WITHDRAW:
        case FSCACHE_OBJECT_EV_RETIRE:
        case FSCACHE_OBJECT_EV_RELEASE:
        case FSCACHE_OBJECT_EV_ERROR:
                new_state = FSCACHE_OBJECT_DYING;
                goto change_state;
+       case FSCACHE_OBJECT_EV_INVALIDATE:
+               new_state = FSCACHE_OBJECT_INVALIDATING;
+               goto change_state;
        case FSCACHE_OBJECT_EV_UPDATE:
                new_state = FSCACHE_OBJECT_UPDATING;
                goto change_state;
@@ -287,7 +320,8 @@ active_transit:
 
        /* determine the transition from a terminal state */
 terminal_transit:
-       switch (fls(object->events & object->event_mask) - 1) {
+       event = fls(object->events & object->event_mask) - 1;
+       switch (event) {
        case FSCACHE_OBJECT_EV_WITHDRAW:
                new_state = FSCACHE_OBJECT_WITHDRAWING;
                goto change_state;
@@ -320,8 +354,8 @@ done:
 
 unsupported_event:
        printk(KERN_ERR "FS-Cache:"
-              " Unsupported event %lx [mask %lx] in state %s\n",
-              object->events, object->event_mask,
+              " Unsupported event %d [%lx/%lx] in state %s\n",
+              event, object->events, object->event_mask,
               fscache_object_states[object->state]);
        BUG();
 }
@@ -587,8 +621,6 @@ static void fscache_object_available(struct fscache_object *object)
        if (object->n_in_progress == 0) {
                if (object->n_ops > 0) {
                        ASSERTCMP(object->n_ops, >=, object->n_obj_ops);
-                       ASSERTIF(object->n_ops > object->n_obj_ops,
-                                !list_empty(&object->pending_ops));
                        fscache_start_operations(object);
                } else {
                        ASSERT(list_empty(&object->pending_ops));
@@ -681,6 +713,7 @@ static void fscache_withdraw_object(struct fscache_object *object)
                if (object->cookie == cookie) {
                        hlist_del_init(&object->cookie_link);
                        object->cookie = NULL;
+                       fscache_invalidation_complete(cookie);
                        detached = true;
                }
                spin_unlock(&cookie->lock);
@@ -890,3 +923,55 @@ enum fscache_checkaux fscache_check_aux(struct fscache_object *object,
        return result;
 }
 EXPORT_SYMBOL(fscache_check_aux);
+
+/*
+ * Asynchronously invalidate an object.
+ */
+static void fscache_invalidate_object(struct fscache_object *object)
+{
+       struct fscache_operation *op;
+       struct fscache_cookie *cookie = object->cookie;
+
+       _enter("{OBJ%x}", object->debug_id);
+
+       /* Reject any new read/write ops and abort any that are pending. */
+       fscache_invalidate_writes(cookie);
+       clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
+       fscache_cancel_all_ops(object);
+
+       /* Now we have to wait for in-progress reads and writes */
+       op = kzalloc(sizeof(*op), GFP_KERNEL);
+       if (!op) {
+               fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR);
+               _leave(" [ENOMEM]");
+               return;
+       }
+
+       fscache_operation_init(op, object->cache->ops->invalidate_object, NULL);
+       op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE);
+
+       spin_lock(&cookie->lock);
+       if (fscache_submit_exclusive_op(object, op) < 0)
+               goto submit_op_failed;
+       spin_unlock(&cookie->lock);
+       fscache_put_operation(op);
+
+       /* Once we've completed the invalidation, we know there will be no data
+        * stored in the cache and thus we can reinstate the data-check-skip
+        * optimisation.
+        */
+       set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+
+       /* We can allow read and write requests to come in once again.  They'll
+        * queue up behind our exclusive invalidation operation.
+        */
+       fscache_invalidation_complete(cookie);
+       _leave("");
+       return;
+
+submit_op_failed:
+       spin_unlock(&cookie->lock);
+       kfree(op);
+       fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR);
+       _leave(" [EIO]");
+}
index 30afdfa7aec78b6a7e47ab791fbf9ec1198870d6..762a9ec4ffa4739686e41cd3f8521765ca6e9719 100644 (file)
@@ -37,6 +37,7 @@ void fscache_enqueue_operation(struct fscache_operation *op)
        ASSERT(op->processor != NULL);
        ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE);
        ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
 
        fscache_stat(&fscache_n_op_enqueue);
        switch (op->flags & FSCACHE_OP_TYPE) {
@@ -64,6 +65,9 @@ EXPORT_SYMBOL(fscache_enqueue_operation);
 static void fscache_run_op(struct fscache_object *object,
                           struct fscache_operation *op)
 {
+       ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
+
+       op->state = FSCACHE_OP_ST_IN_PROGRESS;
        object->n_in_progress++;
        if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
                wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
@@ -84,18 +88,21 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 
        _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
 
+       ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
+       ASSERTCMP(atomic_read(&op->usage), >, 0);
+
        spin_lock(&object->lock);
        ASSERTCMP(object->n_ops, >=, object->n_in_progress);
        ASSERTCMP(object->n_ops, >=, object->n_exclusive);
        ASSERT(list_empty(&op->pend_link));
 
-       ret = -ENOBUFS;
+       op->state = FSCACHE_OP_ST_PENDING;
        if (fscache_object_is_active(object)) {
                op->object = object;
                object->n_ops++;
                object->n_exclusive++;  /* reads and writes must wait */
 
-               if (object->n_ops > 1) {
+               if (object->n_in_progress > 0) {
                        atomic_inc(&op->usage);
                        list_add_tail(&op->pend_link, &object->pending_ops);
                        fscache_stat(&fscache_n_op_pend);
@@ -121,8 +128,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
                fscache_stat(&fscache_n_op_pend);
                ret = 0;
        } else {
-               /* not allowed to submit ops in any other state */
-               BUG();
+               /* If we're in any other state, there must have been an I/O
+                * error of some nature.
+                */
+               ASSERT(test_bit(FSCACHE_IOERROR, &object->cache->flags));
+               ret = -EIO;
        }
 
        spin_unlock(&object->lock);
@@ -186,6 +196,7 @@ int fscache_submit_op(struct fscache_object *object,
        _enter("{OBJ%x OP%x},{%u}",
               object->debug_id, op->debug_id, atomic_read(&op->usage));
 
+       ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
        ASSERTCMP(atomic_read(&op->usage), >, 0);
 
        spin_lock(&object->lock);
@@ -196,6 +207,7 @@ int fscache_submit_op(struct fscache_object *object,
        ostate = object->state;
        smp_rmb();
 
+       op->state = FSCACHE_OP_ST_PENDING;
        if (fscache_object_is_active(object)) {
                op->object = object;
                object->n_ops++;
@@ -225,12 +237,15 @@ int fscache_submit_op(struct fscache_object *object,
                   object->state == FSCACHE_OBJECT_LC_DYING ||
                   object->state == FSCACHE_OBJECT_WITHDRAWING) {
                fscache_stat(&fscache_n_op_rejected);
+               op->state = FSCACHE_OP_ST_CANCELLED;
                ret = -ENOBUFS;
        } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
                fscache_report_unexpected_submission(object, op, ostate);
                ASSERT(!fscache_object_is_active(object));
+               op->state = FSCACHE_OP_ST_CANCELLED;
                ret = -ENOBUFS;
        } else {
+               op->state = FSCACHE_OP_ST_CANCELLED;
                ret = -ENOBUFS;
        }
 
@@ -283,20 +298,28 @@ void fscache_start_operations(struct fscache_object *object)
 /*
  * cancel an operation that's pending on an object
  */
-int fscache_cancel_op(struct fscache_operation *op)
+int fscache_cancel_op(struct fscache_operation *op,
+                     void (*do_cancel)(struct fscache_operation *))
 {
        struct fscache_object *object = op->object;
        int ret;
 
        _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);
 
+       ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
+       ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
+       ASSERTCMP(atomic_read(&op->usage), >, 0);
+
        spin_lock(&object->lock);
 
        ret = -EBUSY;
-       if (!list_empty(&op->pend_link)) {
+       if (op->state == FSCACHE_OP_ST_PENDING) {
+               ASSERT(!list_empty(&op->pend_link));
                fscache_stat(&fscache_n_op_cancelled);
                list_del_init(&op->pend_link);
-               object->n_ops--;
+               if (do_cancel)
+                       do_cancel(op);
+               op->state = FSCACHE_OP_ST_CANCELLED;
                if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
                        object->n_exclusive--;
                if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
@@ -310,6 +333,70 @@ int fscache_cancel_op(struct fscache_operation *op)
        return ret;
 }
 
+/*
+ * Cancel all pending operations on an object
+ */
+void fscache_cancel_all_ops(struct fscache_object *object)
+{
+       struct fscache_operation *op;
+
+       _enter("OBJ%x", object->debug_id);
+
+       spin_lock(&object->lock);
+
+       while (!list_empty(&object->pending_ops)) {
+               op = list_entry(object->pending_ops.next,
+                               struct fscache_operation, pend_link);
+               fscache_stat(&fscache_n_op_cancelled);
+               list_del_init(&op->pend_link);
+
+               ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
+               op->state = FSCACHE_OP_ST_CANCELLED;
+
+               if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
+                       object->n_exclusive--;
+               if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
+                       wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
+               fscache_put_operation(op);
+               cond_resched_lock(&object->lock);
+       }
+
+       spin_unlock(&object->lock);
+       _leave("");
+}
+
+/*
+ * Record the completion or cancellation of an in-progress operation.
+ */
+void fscache_op_complete(struct fscache_operation *op, bool cancelled)
+{
+       struct fscache_object *object = op->object;
+
+       _enter("OBJ%x", object->debug_id);
+
+       ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
+       ASSERTCMP(object->n_in_progress, >, 0);
+       ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
+                   object->n_exclusive, >, 0);
+       ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
+                   object->n_in_progress, ==, 1);
+
+       spin_lock(&object->lock);
+
+       op->state = cancelled ?
+               FSCACHE_OP_ST_CANCELLED : FSCACHE_OP_ST_COMPLETE;
+
+       if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
+               object->n_exclusive--;
+       object->n_in_progress--;
+       if (object->n_in_progress == 0)
+               fscache_start_operations(object);
+
+       spin_unlock(&object->lock);
+       _leave("");
+}
+EXPORT_SYMBOL(fscache_op_complete);
+
 /*
  * release an operation
  * - queues pending ops if this is the last in-progress op
@@ -328,8 +415,9 @@ void fscache_put_operation(struct fscache_operation *op)
                return;
 
        _debug("PUT OP");
-       if (test_and_set_bit(FSCACHE_OP_DEAD, &op->flags))
-               BUG();
+       ASSERTIFCMP(op->state != FSCACHE_OP_ST_COMPLETE,
+                   op->state, ==, FSCACHE_OP_ST_CANCELLED);
+       op->state = FSCACHE_OP_ST_DEAD;
 
        fscache_stat(&fscache_n_op_release);
 
@@ -340,8 +428,14 @@ void fscache_put_operation(struct fscache_operation *op)
 
        object = op->object;
 
-       if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
-               atomic_dec(&object->n_reads);
+       if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) {
+               if (atomic_dec_and_test(&object->n_reads)) {
+                       clear_bit(FSCACHE_COOKIE_WAITING_ON_READS,
+                                 &object->cookie->flags);
+                       wake_up_bit(&object->cookie->flags,
+                                   FSCACHE_COOKIE_WAITING_ON_READS);
+               }
+       }
 
        /* now... we may get called with the object spinlock held, so we
         * complete the cleanup here only if we can immediately acquire the
@@ -359,16 +453,6 @@ void fscache_put_operation(struct fscache_operation *op)
                return;
        }
 
-       if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) {
-               ASSERTCMP(object->n_exclusive, >, 0);
-               object->n_exclusive--;
-       }
-
-       ASSERTCMP(object->n_in_progress, >, 0);
-       object->n_in_progress--;
-       if (object->n_in_progress == 0)
-               fscache_start_operations(object);
-
        ASSERTCMP(object->n_ops, >, 0);
        object->n_ops--;
        if (object->n_ops == 0)
@@ -407,23 +491,14 @@ void fscache_operation_gc(struct work_struct *work)
                spin_unlock(&cache->op_gc_list_lock);
 
                object = op->object;
+               spin_lock(&object->lock);
 
                _debug("GC DEFERRED REL OBJ%x OP%x",
                       object->debug_id, op->debug_id);
                fscache_stat(&fscache_n_op_gc);
 
                ASSERTCMP(atomic_read(&op->usage), ==, 0);
-
-               spin_lock(&object->lock);
-               if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) {
-                       ASSERTCMP(object->n_exclusive, >, 0);
-                       object->n_exclusive--;
-               }
-
-               ASSERTCMP(object->n_in_progress, >, 0);
-               object->n_in_progress--;
-               if (object->n_in_progress == 0)
-                       fscache_start_operations(object);
+               ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
 
                ASSERTCMP(object->n_ops, >, 0);
                object->n_ops--;
@@ -431,6 +506,7 @@ void fscache_operation_gc(struct work_struct *work)
                        fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
 
                spin_unlock(&object->lock);
+               kfree(op);
 
        } while (count++ < 20);
 
index 3f7a59bfa7ada5cf1f8da1d7a391c36322004fba..ff000e52072d171258b0bb59e5e0efd560329ce9 100644 (file)
@@ -56,6 +56,7 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
 
        _enter("%p,%p,%x", cookie, page, gfp);
 
+try_again:
        rcu_read_lock();
        val = radix_tree_lookup(&cookie->stores, page->index);
        if (!val) {
@@ -104,11 +105,19 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
        return true;
 
 page_busy:
-       /* we might want to wait here, but that could deadlock the allocator as
-        * the work threads writing to the cache may all end up sleeping
-        * on memory allocation */
-       fscache_stat(&fscache_n_store_vmscan_busy);
-       return false;
+       /* We will wait here if we're allowed to, but that could deadlock the
+        * allocator as the work threads writing to the cache may all end up
+        * sleeping on memory allocation, so we may need to impose a timeout
+        * too. */
+       if (!(gfp & __GFP_WAIT)) {
+               fscache_stat(&fscache_n_store_vmscan_busy);
+               return false;
+       }
+
+       fscache_stat(&fscache_n_store_vmscan_wait);
+       __fscache_wait_on_page_write(cookie, page);
+       gfp &= ~__GFP_WAIT;
+       goto try_again;
 }
 EXPORT_SYMBOL(__fscache_maybe_release_page);
 
@@ -162,6 +171,7 @@ static void fscache_attr_changed_op(struct fscache_operation *op)
                        fscache_abort_object(object);
        }
 
+       fscache_op_complete(op, true);
        _leave("");
 }
 
@@ -223,6 +233,8 @@ static void fscache_release_retrieval_op(struct fscache_operation *_op)
 
        _enter("{OP%x}", op->op.debug_id);
 
+       ASSERTCMP(op->n_pages, ==, 0);
+
        fscache_hist(fscache_retrieval_histogram, op->start_time);
        if (op->context)
                fscache_put_context(op->op.object->cookie, op->context);
@@ -290,6 +302,17 @@ static int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie)
        return 0;
 }
 
+/*
+ * Handle cancellation of a pending retrieval op
+ */
+static void fscache_do_cancel_retrieval(struct fscache_operation *_op)
+{
+       struct fscache_retrieval *op =
+               container_of(_op, struct fscache_retrieval, op);
+
+       op->n_pages = 0;
+}
+
 /*
  * wait for an object to become active (or dead)
  */
@@ -307,8 +330,8 @@ static int fscache_wait_for_retrieval_activation(struct fscache_object *object,
        fscache_stat(stat_op_waits);
        if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
                        fscache_wait_bit_interruptible,
-                       TASK_INTERRUPTIBLE) < 0) {
-               ret = fscache_cancel_op(&op->op);
+                       TASK_INTERRUPTIBLE) != 0) {
+               ret = fscache_cancel_op(&op->op, fscache_do_cancel_retrieval);
                if (ret == 0)
                        return -ERESTARTSYS;
 
@@ -320,7 +343,14 @@ static int fscache_wait_for_retrieval_activation(struct fscache_object *object,
        _debug("<<< GO");
 
 check_if_dead:
+       if (op->op.state == FSCACHE_OP_ST_CANCELLED) {
+               fscache_stat(stat_object_dead);
+               _leave(" = -ENOBUFS [cancelled]");
+               return -ENOBUFS;
+       }
        if (unlikely(fscache_object_is_dead(object))) {
+               pr_err("%s() = -ENOBUFS [obj dead %d]\n", __func__, op->op.state);
+               fscache_cancel_op(&op->op, fscache_do_cancel_retrieval);
                fscache_stat(stat_object_dead);
                return -ENOBUFS;
        }
@@ -353,6 +383,11 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
        if (hlist_empty(&cookie->backing_objects))
                goto nobufs;
 
+       if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
+               _leave(" = -ENOBUFS [invalidating]");
+               return -ENOBUFS;
+       }
+
        ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
        ASSERTCMP(page, !=, NULL);
 
@@ -364,6 +399,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
                _leave(" = -ENOMEM");
                return -ENOMEM;
        }
+       op->n_pages = 1;
 
        spin_lock(&cookie->lock);
 
@@ -375,10 +411,10 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
        ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP);
 
        atomic_inc(&object->n_reads);
-       set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
+       __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
 
        if (fscache_submit_op(object, &op->op) < 0)
-               goto nobufs_unlock;
+               goto nobufs_unlock_dec;
        spin_unlock(&cookie->lock);
 
        fscache_stat(&fscache_n_retrieval_ops);
@@ -425,6 +461,8 @@ error:
        _leave(" = %d", ret);
        return ret;
 
+nobufs_unlock_dec:
+       atomic_dec(&object->n_reads);
 nobufs_unlock:
        spin_unlock(&cookie->lock);
        kfree(op);
@@ -472,6 +510,11 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
        if (hlist_empty(&cookie->backing_objects))
                goto nobufs;
 
+       if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
+               _leave(" = -ENOBUFS [invalidating]");
+               return -ENOBUFS;
+       }
+
        ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
        ASSERTCMP(*nr_pages, >, 0);
        ASSERT(!list_empty(pages));
@@ -482,6 +525,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
        op = fscache_alloc_retrieval(mapping, end_io_func, context);
        if (!op)
                return -ENOMEM;
+       op->n_pages = *nr_pages;
 
        spin_lock(&cookie->lock);
 
@@ -491,10 +535,10 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
                             struct fscache_object, cookie_link);
 
        atomic_inc(&object->n_reads);
-       set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
+       __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
 
        if (fscache_submit_op(object, &op->op) < 0)
-               goto nobufs_unlock;
+               goto nobufs_unlock_dec;
        spin_unlock(&cookie->lock);
 
        fscache_stat(&fscache_n_retrieval_ops);
@@ -541,6 +585,8 @@ error:
        _leave(" = %d", ret);
        return ret;
 
+nobufs_unlock_dec:
+       atomic_dec(&object->n_reads);
 nobufs_unlock:
        spin_unlock(&cookie->lock);
        kfree(op);
@@ -577,12 +623,18 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
        ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
        ASSERTCMP(page, !=, NULL);
 
+       if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
+               _leave(" = -ENOBUFS [invalidating]");
+               return -ENOBUFS;
+       }
+
        if (fscache_wait_for_deferred_lookup(cookie) < 0)
                return -ERESTARTSYS;
 
        op = fscache_alloc_retrieval(page->mapping, NULL, NULL);
        if (!op)
                return -ENOMEM;
+       op->n_pages = 1;
 
        spin_lock(&cookie->lock);
 
@@ -658,9 +710,27 @@ static void fscache_write_op(struct fscache_operation *_op)
        spin_lock(&object->lock);
        cookie = object->cookie;
 
-       if (!fscache_object_is_active(object) || !cookie) {
+       if (!fscache_object_is_active(object)) {
+               /* If we get here, then the on-disk cache object likely longer
+                * exists, so we should just cancel this write operation.
+                */
+               spin_unlock(&object->lock);
+               fscache_op_complete(&op->op, false);
+               _leave(" [inactive]");
+               return;
+       }
+
+       if (!cookie) {
+               /* If we get here, then the cookie belonging to the object was
+                * detached, probably by the cookie being withdrawn due to
+                * memory pressure, which means that the pages we might write
+                * to the cache from no longer exist - therefore, we can just
+                * cancel this write operation.
+                */
                spin_unlock(&object->lock);
-               _leave("");
+               fscache_op_complete(&op->op, false);
+               _leave(" [cancel] op{f=%lx s=%u} obj{s=%u f=%lx}",
+                      _op->flags, _op->state, object->state, object->flags);
                return;
        }
 
@@ -696,6 +766,7 @@ static void fscache_write_op(struct fscache_operation *_op)
        fscache_end_page_write(object, page);
        if (ret < 0) {
                fscache_abort_object(object);
+               fscache_op_complete(&op->op, true);
        } else {
                fscache_enqueue_operation(&op->op);
        }
@@ -710,6 +781,38 @@ superseded:
        spin_unlock(&cookie->stores_lock);
        clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
        spin_unlock(&object->lock);
+       fscache_op_complete(&op->op, true);
+       _leave("");
+}
+
+/*
+ * Clear the pages pending writing for invalidation
+ */
+void fscache_invalidate_writes(struct fscache_cookie *cookie)
+{
+       struct page *page;
+       void *results[16];
+       int n, i;
+
+       _enter("");
+
+       while (spin_lock(&cookie->stores_lock),
+              n = radix_tree_gang_lookup_tag(&cookie->stores, results, 0,
+                                             ARRAY_SIZE(results),
+                                             FSCACHE_COOKIE_PENDING_TAG),
+              n > 0) {
+               for (i = n - 1; i >= 0; i--) {
+                       page = results[i];
+                       radix_tree_delete(&cookie->stores, page->index);
+               }
+
+               spin_unlock(&cookie->stores_lock);
+
+               for (i = n - 1; i >= 0; i--)
+                       page_cache_release(results[i]);
+       }
+
+       spin_unlock(&cookie->stores_lock);
        _leave("");
 }
 
@@ -759,7 +862,12 @@ int __fscache_write_page(struct fscache_cookie *cookie,
 
        fscache_stat(&fscache_n_stores);
 
-       op = kzalloc(sizeof(*op), GFP_NOIO);
+       if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
+               _leave(" = -ENOBUFS [invalidating]");
+               return -ENOBUFS;
+       }
+
+       op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY);
        if (!op)
                goto nomem;
 
@@ -914,6 +1022,40 @@ done:
 }
 EXPORT_SYMBOL(__fscache_uncache_page);
 
+/**
+ * fscache_mark_page_cached - Mark a page as being cached
+ * @op: The retrieval op pages are being marked for
+ * @page: The page to be marked
+ *
+ * Mark a netfs page as being cached.  After this is called, the netfs
+ * must call fscache_uncache_page() to remove the mark.
+ */
+void fscache_mark_page_cached(struct fscache_retrieval *op, struct page *page)
+{
+       struct fscache_cookie *cookie = op->op.object->cookie;
+
+#ifdef CONFIG_FSCACHE_STATS
+       atomic_inc(&fscache_n_marks);
+#endif
+
+       _debug("- mark %p{%lx}", page, page->index);
+       if (TestSetPageFsCache(page)) {
+               static bool once_only;
+               if (!once_only) {
+                       once_only = true;
+                       printk(KERN_WARNING "FS-Cache:"
+                              " Cookie type %s marked page %lx"
+                              " multiple times\n",
+                              cookie->def->name, page->index);
+               }
+       }
+
+       if (cookie->def->mark_page_cached)
+               cookie->def->mark_page_cached(cookie->netfs_data,
+                                             op->mapping, page);
+}
+EXPORT_SYMBOL(fscache_mark_page_cached);
+
 /**
  * fscache_mark_pages_cached - Mark pages as being cached
  * @op: The retrieval op pages are being marked for
@@ -925,32 +1067,11 @@ EXPORT_SYMBOL(__fscache_uncache_page);
 void fscache_mark_pages_cached(struct fscache_retrieval *op,
                               struct pagevec *pagevec)
 {
-       struct fscache_cookie *cookie = op->op.object->cookie;
        unsigned long loop;
 
-#ifdef CONFIG_FSCACHE_STATS
-       atomic_add(pagevec->nr, &fscache_n_marks);
-#endif
-
-       for (loop = 0; loop < pagevec->nr; loop++) {
-               struct page *page = pagevec->pages[loop];
-
-               _debug("- mark %p{%lx}", page, page->index);
-               if (TestSetPageFsCache(page)) {
-                       static bool once_only;
-                       if (!once_only) {
-                               once_only = true;
-                               printk(KERN_WARNING "FS-Cache:"
-                                      " Cookie type %s marked page %lx"
-                                      " multiple times\n",
-                                      cookie->def->name, page->index);
-                       }
-               }
-       }
+       for (loop = 0; loop < pagevec->nr; loop++)
+               fscache_mark_page_cached(op, pagevec->pages[loop]);
 
-       if (cookie->def->mark_pages_cached)
-               cookie->def->mark_pages_cached(cookie->netfs_data,
-                                              op->mapping, pagevec);
        pagevec_reinit(pagevec);
 }
 EXPORT_SYMBOL(fscache_mark_pages_cached);
index 4765190d537f827f5c8e10c1e75f026d714a00d6..8179e8bc4a3d668bc48c2625bde6a0448e54fc2e 100644 (file)
@@ -69,6 +69,7 @@ atomic_t fscache_n_store_vmscan_not_storing;
 atomic_t fscache_n_store_vmscan_gone;
 atomic_t fscache_n_store_vmscan_busy;
 atomic_t fscache_n_store_vmscan_cancelled;
+atomic_t fscache_n_store_vmscan_wait;
 
 atomic_t fscache_n_marks;
 atomic_t fscache_n_uncaches;
@@ -80,6 +81,9 @@ atomic_t fscache_n_acquires_ok;
 atomic_t fscache_n_acquires_nobufs;
 atomic_t fscache_n_acquires_oom;
 
+atomic_t fscache_n_invalidates;
+atomic_t fscache_n_invalidates_run;
+
 atomic_t fscache_n_updates;
 atomic_t fscache_n_updates_null;
 atomic_t fscache_n_updates_run;
@@ -112,6 +116,7 @@ atomic_t fscache_n_cop_alloc_object;
 atomic_t fscache_n_cop_lookup_object;
 atomic_t fscache_n_cop_lookup_complete;
 atomic_t fscache_n_cop_grab_object;
+atomic_t fscache_n_cop_invalidate_object;
 atomic_t fscache_n_cop_update_object;
 atomic_t fscache_n_cop_drop_object;
 atomic_t fscache_n_cop_put_object;
@@ -168,6 +173,10 @@ static int fscache_stats_show(struct seq_file *m, void *v)
                   atomic_read(&fscache_n_object_created),
                   atomic_read(&fscache_n_object_lookups_timed_out));
 
+       seq_printf(m, "Invals : n=%u run=%u\n",
+                  atomic_read(&fscache_n_invalidates),
+                  atomic_read(&fscache_n_invalidates_run));
+
        seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
                   atomic_read(&fscache_n_updates),
                   atomic_read(&fscache_n_updates_null),
@@ -224,11 +233,12 @@ static int fscache_stats_show(struct seq_file *m, void *v)
                   atomic_read(&fscache_n_store_radix_deletes),
                   atomic_read(&fscache_n_store_pages_over_limit));
 
-       seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u\n",
+       seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u wt=%u\n",
                   atomic_read(&fscache_n_store_vmscan_not_storing),
                   atomic_read(&fscache_n_store_vmscan_gone),
                   atomic_read(&fscache_n_store_vmscan_busy),
-                  atomic_read(&fscache_n_store_vmscan_cancelled));
+                  atomic_read(&fscache_n_store_vmscan_cancelled),
+                  atomic_read(&fscache_n_store_vmscan_wait));
 
        seq_printf(m, "Ops    : pend=%u run=%u enq=%u can=%u rej=%u\n",
                   atomic_read(&fscache_n_op_pend),
@@ -246,7 +256,8 @@ static int fscache_stats_show(struct seq_file *m, void *v)
                   atomic_read(&fscache_n_cop_lookup_object),
                   atomic_read(&fscache_n_cop_lookup_complete),
                   atomic_read(&fscache_n_cop_grab_object));
-       seq_printf(m, "CacheOp: upo=%d dro=%d pto=%d atc=%d syn=%d\n",
+       seq_printf(m, "CacheOp: inv=%d upo=%d dro=%d pto=%d atc=%d syn=%d\n",
+                  atomic_read(&fscache_n_cop_invalidate_object),
                   atomic_read(&fscache_n_cop_update_object),
                   atomic_read(&fscache_n_cop_drop_object),
                   atomic_read(&fscache_n_cop_put_object),
index 0cf160a94eda06afe6055d3c9e0aa806337121e3..1b2f6c2c3aaff697d2909cb88953e61b9d57b82b 100644 (file)
@@ -4,12 +4,24 @@ config FUSE_FS
          With FUSE it is possible to implement a fully functional filesystem
          in a userspace program.
 
-         There's also companion library: libfuse.  This library along with
-         utilities is available from the FUSE homepage:
+         There's also a companion library: libfuse2.  This library is available
+         from the FUSE homepage:
          <http://fuse.sourceforge.net/>
+         although chances are your distribution already has that library
+         installed if you've installed the "fuse" package itself.
 
          See <file:Documentation/filesystems/fuse.txt> for more information.
          See <file:Documentation/Changes> for needed library/utility version.
 
          If you want to develop a userspace FS, or if you want to use
          a filesystem based on FUSE, answer Y or M.
+
+config CUSE
+       tristate "Character device in Userspace support"
+       depends on FUSE_FS
+       help
+         This FUSE extension allows character devices to be
+         implemented in userspace.
+
+         If you want to develop or use a userspace character device
+         based on CUSE, answer Y or M.
index ee8d55042298272f6ac6c76982f4ecd5efb745ca..e397b675b029a6e9f2d6f7f59a0d73acec412fbe 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/module.h>
 
@@ -63,7 +62,7 @@ struct cuse_conn {
        bool                    unrestricted_ioctl;
 };
 
-static DEFINE_SPINLOCK(cuse_lock);             /* protects cuse_conntbl */
+static DEFINE_MUTEX(cuse_lock);                /* protects registration */
 static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
 static struct class *cuse_class;
 
@@ -114,14 +113,14 @@ static int cuse_open(struct inode *inode, struct file *file)
        int rc;
 
        /* look up and get the connection */
-       spin_lock(&cuse_lock);
+       mutex_lock(&cuse_lock);
        list_for_each_entry(pos, cuse_conntbl_head(devt), list)
                if (pos->dev->devt == devt) {
                        fuse_conn_get(&pos->fc);
                        cc = pos;
                        break;
                }
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* dead? */
        if (!cc)
@@ -267,7 +266,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp)
 static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo)
 {
        char *end = p + len;
-       char *key, *val;
+       char *uninitialized_var(key), *uninitialized_var(val);
        int rc;
 
        while (true) {
@@ -305,14 +304,14 @@ static void cuse_gendev_release(struct device *dev)
  */
 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
-       struct cuse_conn *cc = fc_to_cc(fc);
+       struct cuse_conn *cc = fc_to_cc(fc), *pos;
        struct cuse_init_out *arg = req->out.args[0].value;
        struct page *page = req->pages[0];
        struct cuse_devinfo devinfo = { };
        struct device *dev;
        struct cdev *cdev;
        dev_t devt;
-       int rc;
+       int rc, i;
 
        if (req->out.h.error ||
            arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
@@ -356,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        dev_set_drvdata(dev, cc);
        dev_set_name(dev, "%s", devinfo.name);
 
+       mutex_lock(&cuse_lock);
+
+       /* make sure the device-name is unique */
+       for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
+               list_for_each_entry(pos, &cuse_conntbl[i], list)
+                       if (!strcmp(dev_name(pos->dev), dev_name(dev)))
+                               goto err_unlock;
+       }
+
        rc = device_add(dev);
        if (rc)
-               goto err_device;
+               goto err_unlock;
 
        /* register cdev */
        rc = -ENOMEM;
        cdev = cdev_alloc();
        if (!cdev)
-               goto err_device;
+               goto err_unlock;
 
        cdev->owner = THIS_MODULE;
        cdev->ops = &cuse_frontend_fops;
@@ -377,9 +385,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        cc->cdev = cdev;
 
        /* make the device available */
-       spin_lock(&cuse_lock);
        list_add(&cc->list, cuse_conntbl_head(devt));
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* announce device availability */
        dev_set_uevent_suppress(dev, 0);
@@ -391,7 +398,8 @@ out:
 
 err_cdev:
        cdev_del(cdev);
-err_device:
+err_unlock:
+       mutex_unlock(&cuse_lock);
        put_device(dev);
 err_region:
        unregister_chrdev_region(devt, 1);
@@ -520,9 +528,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
        int rc;
 
        /* remove from the conntbl, no more access from this point on */
-       spin_lock(&cuse_lock);
+       mutex_lock(&cuse_lock);
        list_del_init(&cc->list);
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* remove device */
        if (cc->dev)
index c16335315e5da8843a41dc9de6ea5f27cae6df12..e83351aa5baddedc2d8000c3ac82936a25da28b7 100644 (file)
@@ -692,8 +692,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
        struct page *oldpage = *pagep;
        struct page *newpage;
        struct pipe_buffer *buf = cs->pipebufs;
-       struct address_space *mapping;
-       pgoff_t index;
 
        unlock_request(cs->fc, cs->req);
        fuse_copy_finish(cs);
@@ -724,9 +722,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
        if (fuse_check_page(newpage) != 0)
                goto out_fallback_unlock;
 
-       mapping = oldpage->mapping;
-       index = oldpage->index;
-
        /*
         * This is a new and locked page, it shouldn't be mapped or
         * have any special flags on it
index e21d4d8f87e36e45daf71f044712710f12b23322..f3ab824fa302bcae5909adf5c676c4bbb9417743 100644 (file)
@@ -2177,8 +2177,8 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        return ret;
 }
 
-long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
-                           loff_t length)
+static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
+                               loff_t length)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = ff->fc;
@@ -2213,7 +2213,6 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 
        return err;
 }
-EXPORT_SYMBOL_GPL(fuse_file_fallocate);
 
 static const struct file_operations fuse_file_operations = {
        .llseek         = fuse_file_llseek,
index 8dad6b09371660ff66d5fb17dba7c6e38bbd0d53..9802de0f85e61fe061ea150d15177c39b4128ca3 100644 (file)
@@ -241,6 +241,7 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
 
 static void gfs2_reverse_hex(char *c, u64 value)
 {
+       *c = '0';
        while (value) {
                *c-- = hex_asc[value & 0x0f];
                value >>= 4;
@@ -280,6 +281,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+       int lvb_needs_unlock = 0;
        int error;
 
        if (gl->gl_lksb.sb_lkid == 0) {
@@ -293,8 +295,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
        gfs2_update_request_times(gl);
 
        /* don't want to skip dlm_unlock writing the lvb when lock is ex */
+
+       if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE))
+               lvb_needs_unlock = 1;
+
        if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
-           gl->gl_lksb.sb_lvbptr && (gl->gl_state != LM_ST_EXCLUSIVE)) {
+           !lvb_needs_unlock) {
                gfs2_glock_free(gl);
                return;
        }
index 37ee061d899e81a8eb45f5bc64382634e573c108..b7eff078fe90f88f6561978b1917e50658482011 100644 (file)
@@ -350,10 +350,14 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
                BUG_ON(len < chunk_size);
                len -= chunk_size;
                block = gfs2_rbm_to_block(&rbm);
-               gfs2_rbm_from_block(&rbm, block + chunk_size);
-               n_unaligned = 3;
-               if (ptr)
+               if (gfs2_rbm_from_block(&rbm, block + chunk_size)) {
+                       n_unaligned = 0;
                        break;
+               }
+               if (ptr) {
+                       n_unaligned = 3;
+                       break;
+               }
                n_unaligned = len & 3;
        }
 
@@ -557,22 +561,20 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
  */
 int gfs2_rs_alloc(struct gfs2_inode *ip)
 {
-       struct gfs2_blkreserv *res;
+       int error = 0;
 
+       down_write(&ip->i_rw_mutex);
        if (ip->i_res)
-               return 0;
-
-       res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
-       if (!res)
-               return -ENOMEM;
+               goto out;
 
-       RB_CLEAR_NODE(&res->rs_node);
+       ip->i_res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
+       if (!ip->i_res) {
+               error = -ENOMEM;
+               goto out;
+       }
 
-       down_write(&ip->i_rw_mutex);
-       if (ip->i_res)
-               kmem_cache_free(gfs2_rsrv_cachep, res);
-       else
-               ip->i_res = res;
+       RB_CLEAR_NODE(&ip->i_res->rs_node);
+out:
        up_write(&ip->i_rw_mutex);
        return 0;
 }
@@ -1424,6 +1426,9 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
                rs->rs_free = extlen;
                rs->rs_inum = ip->i_no_addr;
                rs_insert(ip);
+       } else {
+               if (goal == rgd->rd_last_alloc + rgd->rd_data0)
+                       rgd->rd_last_alloc = 0;
        }
 }
 
index 0b35903219bc1056d4c1c3260ec75d7b68a1b269..d47f11658c178028273ce5e8853f624e923236ad 100644 (file)
@@ -35,6 +35,16 @@ static int hfs_readpage(struct file *file, struct page *page)
        return block_read_full_page(page, hfs_get_block);
 }
 
+static void hfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               hfs_file_truncate(inode);
+       }
+}
+
 static int hfs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -45,11 +55,8 @@ static int hfs_write_begin(struct file *file, struct address_space *mapping,
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                hfs_get_block,
                                &HFS_I(mapping->host)->phys_size);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               hfs_write_failed(mapping, pos + len);
 
        return ret;
 }
@@ -120,6 +127,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
        struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
        ssize_t ret;
 
@@ -135,7 +143,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
                loff_t end = offset + iov_length(iov, nr_segs);
 
                if (end > isize)
-                       vmtruncate(inode, isize);
+                       hfs_write_failed(mapping, end);
        }
 
        return ret;
@@ -617,9 +625,12 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
            attr->ia_size != i_size_read(inode)) {
                inode_dio_wait(inode);
 
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        return error;
+
+               truncate_setsize(inode, attr->ia_size);
+               hfs_file_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -668,7 +679,6 @@ static const struct file_operations hfs_file_operations = {
 
 static const struct inode_operations hfs_file_inode_operations = {
        .lookup         = hfs_file_lookup,
-       .truncate       = hfs_file_truncate,
        .setattr        = hfs_inode_setattr,
        .setxattr       = hfs_setxattr,
        .getxattr       = hfs_getxattr,
index 4cfbe2edd29692bfdb609c38c20b6d888349967f..6feefc0cb48a0cf2fe9a646e9de4d0434ac7cdce 100644 (file)
@@ -176,12 +176,14 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
        dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
        /* are all of the bits in range? */
        if ((offset + count) > sbi->total_blocks)
-               return -2;
+               return -ENOENT;
 
        mutex_lock(&sbi->alloc_mutex);
        mapping = sbi->alloc_file->i_mapping;
        pnr = offset / PAGE_CACHE_BITS;
        page = read_mapping_page(mapping, pnr, NULL);
+       if (IS_ERR(page))
+               goto kaboom;
        pptr = kmap(page);
        curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
        end = pptr + PAGE_CACHE_BITS / 32;
@@ -214,6 +216,8 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
                set_page_dirty(page);
                kunmap(page);
                page = read_mapping_page(mapping, ++pnr, NULL);
+               if (IS_ERR(page))
+                       goto kaboom;
                pptr = kmap(page);
                curr = pptr;
                end = pptr + PAGE_CACHE_BITS / 32;
@@ -232,4 +236,11 @@ out:
        mutex_unlock(&sbi->alloc_mutex);
 
        return 0;
+
+kaboom:
+       printk(KERN_CRIT "hfsplus: unable to mark blocks free: error %ld\n",
+                       PTR_ERR(page));
+       mutex_unlock(&sbi->alloc_mutex);
+
+       return -EIO;
 }
index 21023d9f8ff3d2a9d87b67c6c69efe5606d182ab..685d07d0ed18845cceb092cc564142664580929c 100644 (file)
@@ -159,7 +159,7 @@ void hfs_btree_close(struct hfs_btree *tree)
        kfree(tree);
 }
 
-void hfs_btree_write(struct hfs_btree *tree)
+int hfs_btree_write(struct hfs_btree *tree)
 {
        struct hfs_btree_header_rec *head;
        struct hfs_bnode *node;
@@ -168,7 +168,7 @@ void hfs_btree_write(struct hfs_btree *tree)
        node = hfs_bnode_find(tree, 0);
        if (IS_ERR(node))
                /* panic? */
-               return;
+               return -EIO;
        /* Load the header */
        page = node->page[0];
        head = (struct hfs_btree_header_rec *)(kmap(page) +
@@ -186,6 +186,7 @@ void hfs_btree_write(struct hfs_btree *tree)
        kunmap(page);
        set_page_dirty(page);
        hfs_bnode_put(node);
+       return 0;
 }
 
 static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
index 5849e3ef35cc9bdce0ddccbdf5186aafdf4fdee9..eba76eab6d625f68aadcba26f04c001040b244c2 100644 (file)
@@ -329,6 +329,7 @@ static int hfsplus_free_extents(struct super_block *sb,
 {
        u32 count, start;
        int i;
+       int err = 0;
 
        hfsplus_dump_extent(extent);
        for (i = 0; i < 8; extent++, i++) {
@@ -345,18 +346,33 @@ found:
        for (;;) {
                start = be32_to_cpu(extent->start_block);
                if (count <= block_nr) {
-                       hfsplus_block_free(sb, start, count);
+                       err = hfsplus_block_free(sb, start, count);
+                       if (err) {
+                               printk(KERN_ERR "hfs: can't free extent\n");
+                               dprint(DBG_EXTENT, " start: %u count: %u\n",
+                                       start, count);
+                       }
                        extent->block_count = 0;
                        extent->start_block = 0;
                        block_nr -= count;
                } else {
                        count -= block_nr;
-                       hfsplus_block_free(sb, start + count, block_nr);
+                       err = hfsplus_block_free(sb, start + count, block_nr);
+                       if (err) {
+                               printk(KERN_ERR "hfs: can't free extent\n");
+                               dprint(DBG_EXTENT, " start: %u count: %u\n",
+                                       start, count);
+                       }
                        extent->block_count = cpu_to_be32(count);
                        block_nr = 0;
                }
-               if (!block_nr || !i)
-                       return 0;
+               if (!block_nr || !i) {
+                       /*
+                        * Try to free all extents and
+                        * return only last error
+                        */
+                       return err;
+               }
                i--;
                extent--;
                count = be32_to_cpu(extent->block_count);
index c571de224b154638e9925fb4a2588b253ceffe63..a6da86b1b4c1ee22ab68b50128b27956aac2140e 100644 (file)
@@ -335,7 +335,7 @@ int hfsplus_block_free(struct super_block *, u32, u32);
 /* btree.c */
 struct hfs_btree *hfs_btree_open(struct super_block *, u32);
 void hfs_btree_close(struct hfs_btree *);
-void hfs_btree_write(struct hfs_btree *);
+int hfs_btree_write(struct hfs_btree *);
 struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *);
 void hfs_bmap_free(struct hfs_bnode *);
 
index 2172aa5976f5e9a6288c38a3f4c964ec13930c4c..799b336b59f977ea7219b33f07f50efaff51c340 100644 (file)
@@ -28,6 +28,16 @@ static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
        return block_write_full_page(page, hfsplus_get_block, wbc);
 }
 
+static void hfsplus_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               hfsplus_file_truncate(inode);
+       }
+}
+
 static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -38,11 +48,8 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                hfsplus_get_block,
                                &HFSPLUS_I(mapping->host)->phys_size);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               hfsplus_write_failed(mapping, pos + len);
 
        return ret;
 }
@@ -116,6 +123,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
        struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
        ssize_t ret;
 
@@ -131,7 +139,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
                loff_t end = offset + iov_length(iov, nr_segs);
 
                if (end > isize)
-                       vmtruncate(inode, isize);
+                       hfsplus_write_failed(mapping, end);
        }
 
        return ret;
@@ -300,10 +308,8 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
                inode_dio_wait(inode);
-
-               error = vmtruncate(inode, attr->ia_size);
-               if (error)
-                       return error;
+               truncate_setsize(inode, attr->ia_size);
+               hfsplus_file_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -358,7 +364,6 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
 
 static const struct inode_operations hfsplus_file_inode_operations = {
        .lookup         = hfsplus_file_lookup,
-       .truncate       = hfsplus_file_truncate,
        .setattr        = hfsplus_setattr,
        .setxattr       = hfsplus_setxattr,
        .getxattr       = hfsplus_getxattr,
index 811a84d2d9643677832219a0b960c6d42109480e..796198d26553c378bee3acf095ce9fe22f6ef51e 100644 (file)
@@ -127,8 +127,14 @@ static int hfsplus_system_write_inode(struct inode *inode)
                hfsplus_mark_mdb_dirty(inode->i_sb);
        }
        hfsplus_inode_write_fork(inode, fork);
-       if (tree)
-               hfs_btree_write(tree);
+       if (tree) {
+               int err = hfs_btree_write(tree);
+               if (err) {
+                       printk(KERN_ERR "hfs: b-tree write err: %d, ino %lu\n",
+                                       err, inode->i_ino);
+                       return err;
+               }
+       }
        return 0;
 }
 
@@ -226,6 +232,7 @@ out:
 
 static void delayed_sync_fs(struct work_struct *work)
 {
+       int err;
        struct hfsplus_sb_info *sbi;
 
        sbi = container_of(work, struct hfsplus_sb_info, sync_work.work);
@@ -234,7 +241,9 @@ static void delayed_sync_fs(struct work_struct *work)
        sbi->work_queued = 0;
        spin_unlock(&sbi->work_lock);
 
-       hfsplus_sync_fs(sbi->alloc_file->i_sb, 1);
+       err = hfsplus_sync_fs(sbi->alloc_file->i_sb, 1);
+       if (err)
+               printk(KERN_ERR "hfs: delayed sync fs err %d\n", err);
 }
 
 void hfsplus_mark_mdb_dirty(struct super_block *sb)
index 89d2a5803ae35b6644507352124f512048f0513e..fbfe2df5624b5c9ca42caca6c0bf077f489055df 100644 (file)
@@ -50,7 +50,7 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
        return disk_secno;
 }
 
-static void hpfs_truncate(struct inode *i)
+void hpfs_truncate(struct inode *i)
 {
        if (IS_IMMUTABLE(i)) return /*-EPERM*/;
        hpfs_lock_assert(i->i_sb);
@@ -105,6 +105,16 @@ static int hpfs_readpage(struct file *file, struct page *page)
        return block_read_full_page(page,hpfs_get_block);
 }
 
+static void hpfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               hpfs_truncate(inode);
+       }
+}
+
 static int hpfs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -115,11 +125,8 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping,
        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
                                hpfs_get_block,
                                &hpfs_i(mapping->host)->mmu_private);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               hpfs_write_failed(mapping, pos + len);
 
        return ret;
 }
@@ -166,6 +173,5 @@ const struct file_operations hpfs_file_ops =
 
 const struct inode_operations hpfs_file_iops =
 {
-       .truncate       = hpfs_truncate,
        .setattr        = hpfs_setattr,
 };
index 7102aaecc24414e6af90e8b7465d3fec02c3b3fd..b7ae286646b55e4f5f17dc5a724cb5c6a889e9a1 100644 (file)
@@ -252,6 +252,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, const char *,
 /* file.c */
 
 int hpfs_file_fsync(struct file *, loff_t, loff_t, int);
+void hpfs_truncate(struct inode *);
 extern const struct file_operations hpfs_file_ops;
 extern const struct inode_operations hpfs_file_iops;
 extern const struct address_space_operations hpfs_aops;
index 804a9a842cbc1cdf2191efa88eb522821cbcca55..5dc06c8371051855f836ce7666e659471c6cb988 100644 (file)
@@ -277,9 +277,12 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        goto out_unlock;
+
+               truncate_setsize(inode, attr->ia_size);
+               hpfs_truncate(inode);
        }
 
        setattr_copy(inode, attr);
index a2862339323b2a5f1e08dd7e25a779e1b683b828..81cc7eaff86321c2788c0aa83c236778e6fb4b70 100644 (file)
@@ -446,7 +446,8 @@ int __log_start_commit(journal_t *journal, tid_t target)
         * currently running transaction (if it exists).  Otherwise,
         * the target tid must be an old one.
         */
-       if (journal->j_running_transaction &&
+       if (journal->j_commit_request != target &&
+           journal->j_running_transaction &&
            journal->j_running_transaction->t_tid == target) {
                /*
                 * We want a new commit: OK, mark the request and wakeup the
index 42f6615af0ac47d984fc5084623570d231832cfb..df9f29760efa99931bef9fdd9609e7580d8852cd 100644 (file)
@@ -209,7 +209,8 @@ repeat:
                if (!new_transaction)
                        goto alloc_transaction;
                write_lock(&journal->j_state_lock);
-               if (!journal->j_running_transaction) {
+               if (!journal->j_running_transaction &&
+                   !journal->j_barrier_count) {
                        jbd2_get_transaction(journal, new_transaction);
                        new_transaction = NULL;
                }
@@ -1839,7 +1840,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
 
        BUFFER_TRACE(bh, "entry");
 
-retry:
        /*
         * It is safe to proceed here without the j_list_lock because the
         * buffers cannot be stolen by try_to_free_buffers as long as we are
@@ -1934,14 +1934,11 @@ retry:
                 * for commit and try again.
                 */
                if (partial_page) {
-                       tid_t tid = journal->j_committing_transaction->t_tid;
-
                        jbd2_journal_put_journal_head(jh);
                        spin_unlock(&journal->j_list_lock);
                        jbd_unlock_bh_state(bh);
                        write_unlock(&journal->j_state_lock);
-                       jbd2_log_wait_commit(journal, tid);
-                       goto retry;
+                       return -EBUSY;
                }
                /*
                 * OK, buffer won't be reachable after truncate. We just set
@@ -2002,21 +1999,23 @@ zap_buffer_unlocked:
  * @page:    page to flush
  * @offset:  length of page to invalidate.
  *
- * Reap page buffers containing data after offset in page.
- *
+ * Reap page buffers containing data after offset in page. Can return -EBUSY
+ * if buffers are part of the committing transaction and the page is straddling
+ * i_size. Caller then has to wait for current commit and try again.
  */
-void jbd2_journal_invalidatepage(journal_t *journal,
-                     struct page *page,
-                     unsigned long offset)
+int jbd2_journal_invalidatepage(journal_t *journal,
+                               struct page *page,
+                               unsigned long offset)
 {
        struct buffer_head *head, *bh, *next;
        unsigned int curr_off = 0;
        int may_free = 1;
+       int ret = 0;
 
        if (!PageLocked(page))
                BUG();
        if (!page_has_buffers(page))
-               return;
+               return 0;
 
        /* We will potentially be playing with lists other than just the
         * data lists (especially for journaled data mode), so be
@@ -2030,9 +2029,11 @@ void jbd2_journal_invalidatepage(journal_t *journal,
                if (offset <= curr_off) {
                        /* This block is wholly outside the truncation point */
                        lock_buffer(bh);
-                       may_free &= journal_unmap_buffer(journal, bh,
-                                                        offset > 0);
+                       ret = journal_unmap_buffer(journal, bh, offset > 0);
                        unlock_buffer(bh);
+                       if (ret < 0)
+                               return ret;
+                       may_free &= ret;
                }
                curr_off = next_off;
                bh = next;
@@ -2043,6 +2044,7 @@ void jbd2_journal_invalidatepage(journal_t *journal,
                if (may_free && try_to_free_buffers(page))
                        J_ASSERT(!page_has_buffers(page));
        }
+       return 0;
 }
 
 /*
index 9d3afd157f9908dc3278965efe353dcf42694092..dd7442c5835864b0e04bdff5befbd0f020232bfb 100644 (file)
@@ -119,9 +119,12 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
            iattr->ia_size != i_size_read(inode)) {
                inode_dio_wait(inode);
 
-               rc = vmtruncate(inode, iattr->ia_size);
+               rc = inode_newsize_ok(inode, iattr->ia_size);
                if (rc)
                        return rc;
+
+               truncate_setsize(inode, iattr->ia_size);
+               jfs_truncate(inode);
        }
 
        setattr_copy(inode, iattr);
@@ -133,7 +136,6 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
 }
 
 const struct inode_operations jfs_file_inode_operations = {
-       .truncate       = jfs_truncate,
        .setxattr       = jfs_setxattr,
        .getxattr       = jfs_getxattr,
        .listxattr      = jfs_listxattr,
index 4692bf3ca8cbcbaff9db883759b77d3d725cbc0d..b7dc47ba675efe6bb9619230aece38f1d7984de0 100644 (file)
@@ -300,6 +300,16 @@ static int jfs_readpages(struct file *file, struct address_space *mapping,
        return mpage_readpages(mapping, pages, nr_pages, jfs_get_block);
 }
 
+static void jfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               jfs_truncate(inode);
+       }
+}
+
 static int jfs_write_begin(struct file *file, struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
                                struct page **pagep, void **fsdata)
@@ -308,11 +318,8 @@ static int jfs_write_begin(struct file *file, struct address_space *mapping,
 
        ret = nobh_write_begin(mapping, pos, len, flags, pagep, fsdata,
                                jfs_get_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               jfs_write_failed(mapping, pos + len);
 
        return ret;
 }
@@ -326,6 +333,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
        const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
        struct inode *inode = file->f_mapping->host;
        ssize_t ret;
 
@@ -341,7 +349,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
                loff_t end = offset + iov_length(iov, nr_segs);
 
                if (end > isize)
-                       vmtruncate(inode, isize);
+                       jfs_write_failed(mapping, end);
        }
 
        return ret;
index 35fc6e74cd886954aab26d223c603573dfe26786..916da8c4158b0c01d834ead4b056b014eb1797a1 100644 (file)
@@ -369,8 +369,6 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr)
        struct inode *inode = dentry->d_inode;
        int error;
 
-       WARN_ON_ONCE(inode->i_op->truncate);
-
        error = inode_change_ok(inode, iattr);
        if (error)
                return error;
index e1a3b6bf63244237215824021d87f553bf4482a6..9a59cbade2fb5254b2602ba8baf212676d62bca3 100644 (file)
@@ -1887,9 +1887,15 @@ int logfs_truncate(struct inode *inode, u64 target)
                logfs_put_wblocks(sb, NULL, 1);
        }
 
-       if (!err)
-               err = vmtruncate(inode, target);
+       if (!err) {
+               err = inode_newsize_ok(inode, target);
+               if (err)
+                       goto out;
+
+               truncate_setsize(inode, target);
+       }
 
+ out:
        /* I don't trust error recovery yet. */
        WARN_ON(err);
        return err;
index 4493ce695ab83af7986eefdc72f683f65537c3a9..adc6f5494231bc947f45d8a3c526db0b36f39bf3 100644 (file)
@@ -34,9 +34,12 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        return error;
+
+               truncate_setsize(inode, attr->ia_size);
+               minix_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -45,7 +48,6 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
 }
 
 const struct inode_operations minix_file_inode_operations = {
-       .truncate       = minix_truncate,
        .setattr        = minix_setattr,
        .getattr        = minix_getattr,
 };
index 4fc5f8ab1c44a47534e1b2b9a0bb338aea451dc7..99541cceb584966da9aba7b70dd094653cf158b9 100644 (file)
@@ -395,6 +395,16 @@ int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
        return __block_write_begin(page, pos, len, minix_get_block);
 }
 
+static void minix_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               minix_truncate(inode);
+       }
+}
+
 static int minix_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -403,11 +413,8 @@ static int minix_write_begin(struct file *file, struct address_space *mapping,
 
        ret = block_write_begin(mapping, pos, len, flags, pagep,
                                minix_get_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               minix_write_failed(mapping, pos + len);
 
        return ret;
 }
index 5f4cdf3ad913fec928835d87fbe499efdf7d67e5..43a97ee1d4c864e4053f86aec5830e037721d125 100644 (file)
@@ -1275,9 +1275,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
        *need_lookup = false;
        dentry = d_lookup(dir, name);
        if (dentry) {
-               if (d_need_lookup(dentry)) {
-                       *need_lookup = true;
-               } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
+               if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
                        error = d_revalidate(dentry, flags);
                        if (unlikely(error <= 0)) {
                                if (error < 0) {
@@ -1383,8 +1381,6 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name,
                        return -ECHILD;
                nd->seq = seq;
 
-               if (unlikely(d_need_lookup(dentry)))
-                       goto unlazy;
                if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
                        status = d_revalidate(dentry, nd->flags);
                        if (unlikely(status <= 0)) {
@@ -1410,11 +1406,6 @@ unlazy:
        if (unlikely(!dentry))
                goto need_lookup;
 
-       if (unlikely(d_need_lookup(dentry))) {
-               dput(dentry);
-               goto need_lookup;
-       }
-
        if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
                status = d_revalidate(dentry, nd->flags);
        if (unlikely(status <= 0)) {
@@ -1859,7 +1850,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
        if (flags & LOOKUP_ROOT) {
                struct inode *inode = nd->root.dentry->d_inode;
                if (*name) {
-                       if (!inode->i_op->lookup)
+                       if (!can_lookup(inode))
                                return -ENOTDIR;
                        retval = inode_permission(inode, MAY_EXEC);
                        if (retval)
@@ -1903,6 +1894,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        get_fs_pwd(current->fs, &nd->path);
                }
        } else {
+               /* Caller must check execute permissions on the starting path component */
                struct fd f = fdget_raw(dfd);
                struct dentry *dentry;
 
@@ -1912,16 +1904,10 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                dentry = f.file->f_path.dentry;
 
                if (*name) {
-                       if (!S_ISDIR(dentry->d_inode->i_mode)) {
+                       if (!can_lookup(dentry->d_inode)) {
                                fdput(f);
                                return -ENOTDIR;
                        }
-
-                       retval = inode_permission(dentry->d_inode, MAY_EXEC);
-                       if (retval) {
-                               fdput(f);
-                               return retval;
-                       }
                }
 
                nd->path = f.file->f_path;
@@ -2189,15 +2175,19 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
  *     path-walking is complete.
  */
 static struct filename *
-user_path_parent(int dfd, const char __user *path, struct nameidata *nd)
+user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
+                unsigned int flags)
 {
        struct filename *s = getname(path);
        int error;
 
+       /* only LOOKUP_REVAL is allowed in extra flags */
+       flags &= LOOKUP_REVAL;
+
        if (IS_ERR(s))
                return s;
 
-       error = filename_lookup(dfd, s, LOOKUP_PARENT, nd);
+       error = filename_lookup(dfd, s, flags | LOOKUP_PARENT, nd);
        if (error) {
                putname(s);
                return ERR_PTR(error);
@@ -3044,12 +3034,22 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
        return file;
 }
 
-struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir)
+struct dentry *kern_path_create(int dfd, const char *pathname,
+                               struct path *path, unsigned int lookup_flags)
 {
        struct dentry *dentry = ERR_PTR(-EEXIST);
        struct nameidata nd;
        int err2;
-       int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
+       int error;
+       bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
+
+       /*
+        * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
+        * other flags passed in are ignored!
+        */
+       lookup_flags &= LOOKUP_REVAL;
+
+       error = do_path_lookup(dfd, pathname, LOOKUP_PARENT|lookup_flags, &nd);
        if (error)
                return ERR_PTR(error);
 
@@ -3113,13 +3113,14 @@ void done_path_create(struct path *path, struct dentry *dentry)
 }
 EXPORT_SYMBOL(done_path_create);
 
-struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
+struct dentry *user_path_create(int dfd, const char __user *pathname,
+                               struct path *path, unsigned int lookup_flags)
 {
        struct filename *tmp = getname(pathname);
        struct dentry *res;
        if (IS_ERR(tmp))
                return ERR_CAST(tmp);
-       res = kern_path_create(dfd, tmp->name, path, is_dir);
+       res = kern_path_create(dfd, tmp->name, path, lookup_flags);
        putname(tmp);
        return res;
 }
@@ -3175,12 +3176,13 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
        struct dentry *dentry;
        struct path path;
        int error;
+       unsigned int lookup_flags = 0;
 
        error = may_mknod(mode);
        if (error)
                return error;
-
-       dentry = user_path_create(dfd, filename, &path, 0);
+retry:
+       dentry = user_path_create(dfd, filename, &path, lookup_flags);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
@@ -3203,6 +3205,10 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
        }
 out:
        done_path_create(&path, dentry);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -3241,8 +3247,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
        struct dentry *dentry;
        struct path path;
        int error;
+       unsigned int lookup_flags = LOOKUP_DIRECTORY;
 
-       dentry = user_path_create(dfd, pathname, &path, 1);
+retry:
+       dentry = user_path_create(dfd, pathname, &path, lookup_flags);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
@@ -3252,6 +3260,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
        if (!error)
                error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
        done_path_create(&path, dentry);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -3327,8 +3339,9 @@ static long do_rmdir(int dfd, const char __user *pathname)
        struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
-
-       name = user_path_parent(dfd, pathname, &nd);
+       unsigned int lookup_flags = 0;
+retry:
+       name = user_path_parent(dfd, pathname, &nd, lookup_flags);
        if (IS_ERR(name))
                return PTR_ERR(name);
 
@@ -3370,6 +3383,10 @@ exit2:
 exit1:
        path_put(&nd.path);
        putname(name);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -3423,8 +3440,9 @@ static long do_unlinkat(int dfd, const char __user *pathname)
        struct dentry *dentry;
        struct nameidata nd;
        struct inode *inode = NULL;
-
-       name = user_path_parent(dfd, pathname, &nd);
+       unsigned int lookup_flags = 0;
+retry:
+       name = user_path_parent(dfd, pathname, &nd, lookup_flags);
        if (IS_ERR(name))
                return PTR_ERR(name);
 
@@ -3462,6 +3480,11 @@ exit2:
 exit1:
        path_put(&nd.path);
        putname(name);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               inode = NULL;
+               goto retry;
+       }
        return error;
 
 slashes:
@@ -3513,12 +3536,13 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
        struct filename *from;
        struct dentry *dentry;
        struct path path;
+       unsigned int lookup_flags = 0;
 
        from = getname(oldname);
        if (IS_ERR(from))
                return PTR_ERR(from);
-
-       dentry = user_path_create(newdfd, newname, &path, 0);
+retry:
+       dentry = user_path_create(newdfd, newname, &path, lookup_flags);
        error = PTR_ERR(dentry);
        if (IS_ERR(dentry))
                goto out_putname;
@@ -3527,6 +3551,10 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
        if (!error)
                error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
        done_path_create(&path, dentry);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out_putname:
        putname(from);
        return error;
@@ -3613,12 +3641,13 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 
        if (flags & AT_SYMLINK_FOLLOW)
                how |= LOOKUP_FOLLOW;
-
+retry:
        error = user_path_at(olddfd, oldname, how, &old_path);
        if (error)
                return error;
 
-       new_dentry = user_path_create(newdfd, newname, &new_path, 0);
+       new_dentry = user_path_create(newdfd, newname, &new_path,
+                                       (how & LOOKUP_REVAL));
        error = PTR_ERR(new_dentry);
        if (IS_ERR(new_dentry))
                goto out;
@@ -3635,6 +3664,10 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
        error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
 out_dput:
        done_path_create(&new_path, new_dentry);
+       if (retry_estale(error, how)) {
+               how |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        path_put(&old_path);
 
@@ -3807,15 +3840,17 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
        struct nameidata oldnd, newnd;
        struct filename *from;
        struct filename *to;
+       unsigned int lookup_flags = 0;
+       bool should_retry = false;
        int error;
-
-       from = user_path_parent(olddfd, oldname, &oldnd);
+retry:
+       from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
        if (IS_ERR(from)) {
                error = PTR_ERR(from);
                goto exit;
        }
 
-       to = user_path_parent(newdfd, newname, &newnd);
+       to = user_path_parent(newdfd, newname, &newnd, lookup_flags);
        if (IS_ERR(to)) {
                error = PTR_ERR(to);
                goto exit1;
@@ -3887,11 +3922,18 @@ exit3:
        unlock_rename(new_dir, old_dir);
        mnt_drop_write(oldnd.path.mnt);
 exit2:
+       if (retry_estale(error, lookup_flags))
+               should_retry = true;
        path_put(&newnd.path);
        putname(to);
 exit1:
        path_put(&oldnd.path);
        putname(from);
+       if (should_retry) {
+               should_retry = false;
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 exit:
        return error;
 }
index 398a50ff243848fae1145c695d6decc801d80f7d..55605c552787cae1188ef93ee522ddd958e8cd83 100644 (file)
@@ -313,7 +313,7 @@ int __mnt_want_write(struct vfsmount *m)
         * incremented count after it has set MNT_WRITE_HOLD.
         */
        smp_mb();
-       while (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
+       while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
                cpu_relax();
        /*
         * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
index d7e9fe77188a6869073bae3daa8c5a731d2a1edb..1acdad7fcec7cda8ca5aa9e88b92cce45b960c37 100644 (file)
@@ -976,9 +976,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                        goto out;
 
                if (attr->ia_size != i_size_read(inode)) {
-                       result = vmtruncate(inode, attr->ia_size);
-                       if (result)
-                               goto out;
+                       truncate_setsize(inode, attr->ia_size);
                        mark_inode_dirty(inode);
                }
        }
index c89b26bc9759251ab370da28eab07a266adbd573..264d1aa935f2b3e52e3e08bd26ee99c30912c8f6 100644 (file)
@@ -206,7 +206,7 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 
                list_for_each_entry(lo, &server->layouts, plh_layouts) {
                        ino = igrab(lo->plh_inode);
-                       if (ino)
+                       if (!ino)
                                continue;
                        spin_lock(&ino->i_lock);
                        /* Is this layout in the process of being freed? */
index 32e6c53520e22033237206e9264378efe33104e6..1b2d7eb93796dcbda72ee7d21deb0e7aa2b58952 100644 (file)
@@ -2153,12 +2153,16 @@ static int nfs_open_permission_mask(int openflags)
 {
        int mask = 0;
 
-       if ((openflags & O_ACCMODE) != O_WRONLY)
-               mask |= MAY_READ;
-       if ((openflags & O_ACCMODE) != O_RDONLY)
-               mask |= MAY_WRITE;
-       if (openflags & __FMODE_EXEC)
-               mask |= MAY_EXEC;
+       if (openflags & __FMODE_EXEC) {
+               /* ONLY check exec rights */
+               mask = MAY_EXEC;
+       } else {
+               if ((openflags & O_ACCMODE) != O_WRONLY)
+                       mask |= MAY_READ;
+               if ((openflags & O_ACCMODE) != O_RDONLY)
+                       mask |= MAY_WRITE;
+       }
+
        return mask;
 }
 
index c817787fbdb4024738a84d804a8800cd7b6dbedf..24d1d1c5fcaf9e50b7528d7ef2a9eff6fcf9f018 100644 (file)
@@ -307,6 +307,7 @@ void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
                nfs_fscache_inode_unlock(inode);
        }
 }
+EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
 
 /*
  * Replace a per-inode cookie due to revalidation detecting a file having
index c5b11b53ff33b33d4249a88443b102ae33f00df5..4ecb76652eba6059402c0d9e7320e4cdc1603b82 100644 (file)
@@ -152,6 +152,22 @@ static inline void nfs_readpage_to_fscache(struct inode *inode,
                __nfs_readpage_to_fscache(inode, page, sync);
 }
 
+/*
+ * Invalidate the contents of fscache for this inode.  This will not sleep.
+ */
+static inline void nfs_fscache_invalidate(struct inode *inode)
+{
+       fscache_invalidate(NFS_I(inode)->fscache);
+}
+
+/*
+ * Wait for an object to finish being invalidated.
+ */
+static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
+{
+       fscache_wait_on_invalidate(NFS_I(inode)->fscache);
+}
+
 /*
  * indicate the client caching state as readable text
  */
@@ -162,7 +178,6 @@ static inline const char *nfs_server_fscache_state(struct nfs_server *server)
        return "no ";
 }
 
-
 #else /* CONFIG_NFS_FSCACHE */
 static inline int nfs_fscache_register(void) { return 0; }
 static inline void nfs_fscache_unregister(void) {}
@@ -205,6 +220,10 @@ static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
 static inline void nfs_readpage_to_fscache(struct inode *inode,
                                           struct page *page, int sync) {}
 
+
+static inline void nfs_fscache_invalidate(struct inode *inode) {}
+static inline void nfs_fscache_wait_on_invalidate(struct inode *inode) {}
+
 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
 {
        return "no ";
index 2faae14d89f46e97d76f1e82c85f776426c85816..ebeb94ce1b0bd5355cc28042ad2bb67753324a88 100644 (file)
@@ -161,10 +161,12 @@ static void nfs_zap_caches_locked(struct inode *inode)
        nfsi->attrtimeo_timestamp = jiffies;
 
        memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));
-       if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
+       if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
-       else
+               nfs_fscache_invalidate(inode);
+       } else {
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+       }
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -179,6 +181,7 @@ void nfs_zap_mapping(struct inode *inode, struct address_space *mapping)
        if (mapping->nrpages != 0) {
                spin_lock(&inode->i_lock);
                NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
+               nfs_fscache_invalidate(inode);
                spin_unlock(&inode->i_lock);
        }
 }
@@ -881,7 +884,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
                memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
        spin_unlock(&inode->i_lock);
        nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
-       nfs_fscache_reset_inode_cookie(inode);
+       nfs_fscache_wait_on_invalidate(inode);
        dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
                        inode->i_sb->s_id, (long long)NFS_FILEID(inode));
        return 0;
@@ -957,6 +960,10 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr
                i_size_write(inode, nfs_size_to_loff_t(fattr->size));
                ret |= NFS_INO_INVALID_ATTR;
        }
+
+       if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+               nfs_fscache_invalidate(inode);
+
        return ret;
 }
 
@@ -1205,8 +1212,10 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr
        struct nfs_inode *nfsi = NFS_I(inode);
 
        nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
-       if (S_ISDIR(inode->i_mode))
+       if (S_ISDIR(inode->i_mode)) {
                nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+               nfs_fscache_invalidate(inode);
+       }
        if ((fattr->valid & NFS_ATTR_FATTR) == 0)
                return 0;
        return nfs_refresh_inode_locked(inode, fattr);
@@ -1494,6 +1503,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        (save_cache_validity & NFS_INO_REVAL_FORCED))
                nfsi->cache_validity |= invalid;
 
+       if (invalid & NFS_INO_INVALID_DATA)
+               nfs_fscache_invalidate(inode);
+
        return 0;
  out_err:
        /*
index dd057bc6b65b28d3822229e0c0d5d0777b7955b9..fc8dc20fdeb9c90274d5acb8ef2bb831af297425 100644 (file)
@@ -177,11 +177,31 @@ out_nofree:
        return mnt;
 }
 
+static int
+nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+       if (NFS_FH(dentry->d_inode)->size != 0)
+               return nfs_getattr(mnt, dentry, stat);
+       generic_fillattr(dentry->d_inode, stat);
+       return 0;
+}
+
+static int
+nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       if (NFS_FH(dentry->d_inode)->size != 0)
+               return nfs_setattr(dentry, attr);
+       return -EACCES;
+}
+
 const struct inode_operations nfs_mountpoint_inode_operations = {
        .getattr        = nfs_getattr,
+       .setattr        = nfs_setattr,
 };
 
 const struct inode_operations nfs_referral_inode_operations = {
+       .getattr        = nfs_namespace_getattr,
+       .setattr        = nfs_namespace_setattr,
 };
 
 static void nfs_expire_automounts(struct work_struct *work)
index acc3472681244d004f743a198e802709a38927b4..2e9779b58b7af6f3d143e60af3fba6abc8902a11 100644 (file)
@@ -236,11 +236,10 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
        error = nfs4_discover_server_trunking(clp, &old);
        if (error < 0)
                goto error;
+       nfs_put_client(clp);
        if (clp != old) {
                clp->cl_preserve_clid = true;
-               nfs_put_client(clp);
                clp = old;
-               atomic_inc(&clp->cl_count);
        }
 
        return clp;
@@ -306,7 +305,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
                .clientid       = new->cl_clientid,
                .confirm        = new->cl_confirm,
        };
-       int status;
+       int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
        list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -332,40 +331,33 @@ int nfs40_walk_client_list(struct nfs_client *new,
 
                if (prev)
                        nfs_put_client(prev);
+               prev = pos;
 
                status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
-               if (status == 0) {
+               switch (status) {
+               case -NFS4ERR_STALE_CLIENTID:
+                       break;
+               case 0:
                        nfs4_swap_callback_idents(pos, new);
 
-                       nfs_put_client(pos);
+                       prev = NULL;
                        *result = pos;
                        dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
                                __func__, pos, atomic_read(&pos->cl_count));
-                       return 0;
-               }
-               if (status != -NFS4ERR_STALE_CLIENTID) {
-                       nfs_put_client(pos);
-                       dprintk("NFS: <-- %s status = %d, no result\n",
-                               __func__, status);
-                       return status;
+               default:
+                       goto out;
                }
 
                spin_lock(&nn->nfs_client_lock);
-               prev = pos;
        }
+       spin_unlock(&nn->nfs_client_lock);
 
-       /*
-        * No matching nfs_client found.  This should be impossible,
-        * because the new nfs_client has already been added to
-        * nfs_client_list by nfs_get_client().
-        *
-        * Don't BUG(), since the caller is holding a mutex.
-        */
+       /* No match found. The server lost our clientid */
+out:
        if (prev)
                nfs_put_client(prev);
-       spin_unlock(&nn->nfs_client_lock);
-       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-       return -NFS4ERR_STALE_CLIENTID;
+       dprintk("NFS: <-- %s status = %d\n", __func__, status);
+       return status;
 }
 
 #ifdef CONFIG_NFS_V4_1
@@ -432,7 +424,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
 {
        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
        struct nfs_client *pos, *n, *prev = NULL;
-       int error;
+       int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
        list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -448,14 +440,17 @@ int nfs41_walk_client_list(struct nfs_client *new,
                                nfs_put_client(prev);
                        prev = pos;
 
-                       error = nfs_wait_client_init_complete(pos);
-                       if (error < 0) {
+                       nfs4_schedule_lease_recovery(pos);
+                       status = nfs_wait_client_init_complete(pos);
+                       if (status < 0) {
                                nfs_put_client(pos);
                                spin_lock(&nn->nfs_client_lock);
                                continue;
                        }
-
+                       status = pos->cl_cons_state;
                        spin_lock(&nn->nfs_client_lock);
+                       if (status < 0)
+                               continue;
                }
 
                if (pos->rpc_ops != new->rpc_ops)
@@ -473,6 +468,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
                if (!nfs4_match_serverowners(pos, new))
                        continue;
 
+               atomic_inc(&pos->cl_count);
                spin_unlock(&nn->nfs_client_lock);
                dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
                        __func__, pos, atomic_read(&pos->cl_count));
@@ -481,16 +477,10 @@ int nfs41_walk_client_list(struct nfs_client *new,
                return 0;
        }
 
-       /*
-        * No matching nfs_client found.  This should be impossible,
-        * because the new nfs_client has already been added to
-        * nfs_client_list by nfs_get_client().
-        *
-        * Don't BUG(), since the caller is holding a mutex.
-        */
+       /* No matching nfs_client found. */
        spin_unlock(&nn->nfs_client_lock);
-       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-       return -NFS4ERR_STALE_CLIENTID;
+       dprintk("NFS: <-- %s status = %d\n", __func__, status);
+       return status;
 }
 #endif /* CONFIG_NFS_V4_1 */
 
index e7699308364acf6f84fcf62e5f815ed2c74c2b5c..08ddcccb8887cd49ee554edbd4a35f83f59de0e4 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <linux/nfs_fs.h>
 #include "internal.h"
+#include "fscache.h"
 #include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_FILE
@@ -74,6 +75,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
 
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        nfs_file_set_open_context(filp, ctx);
+       nfs_fscache_set_inode_cookie(inode, filp);
        err = 0;
 
 out_put_ctx:
index 493f0f41c5547d94eecf12de33bc8acf1545c2f7..cf747ef8665078a2a684b256402ab63484a77665 100644 (file)
@@ -64,7 +64,7 @@
 #include "pnfs.h"
 #include "netns.h"
 #include "nfs4session.h"
-
+#include "fscache.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PROC
 
@@ -734,6 +734,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
        if (!cinfo->atomic || cinfo->before != dir->i_version)
                nfs_force_lookup_revalidate(dir);
        dir->i_version = cinfo->after;
+       nfs_fscache_invalidate(dir);
        spin_unlock(&dir->i_lock);
 }
 
@@ -1625,7 +1626,8 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
 
 static int nfs4_opendata_access(struct rpc_cred *cred,
                                struct nfs4_opendata *opendata,
-                               struct nfs4_state *state, fmode_t fmode)
+                               struct nfs4_state *state, fmode_t fmode,
+                               int openflags)
 {
        struct nfs_access_entry cache;
        u32 mask;
@@ -1637,11 +1639,14 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
 
        mask = 0;
        /* don't check MAY_WRITE - a newly created file may not have
-        * write mode bits, but POSIX allows the creating process to write */
-       if (fmode & FMODE_READ)
-               mask |= MAY_READ;
-       if (fmode & FMODE_EXEC)
-               mask |= MAY_EXEC;
+        * write mode bits, but POSIX allows the creating process to write.
+        * use openflags to check for exec, because fmode won't
+        * always have FMODE_EXEC set when file open for exec. */
+       if (openflags & __FMODE_EXEC) {
+               /* ONLY check for exec rights */
+               mask = MAY_EXEC;
+       } else if (fmode & FMODE_READ)
+               mask = MAY_READ;
 
        cache.cred = cred;
        cache.jiffies = jiffies;
@@ -1895,7 +1900,7 @@ static int _nfs4_do_open(struct inode *dir,
        if (server->caps & NFS_CAP_POSIX_LOCK)
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
-       status = nfs4_opendata_access(cred, opendata, state, fmode);
+       status = nfs4_opendata_access(cred, opendata, state, fmode, flags);
        if (status != 0)
                goto err_opendata_put;
 
index 9448c579d41a40068897f99cbc5db09bccf3e063..e61f68d5ef218dd64cdfec220bab02069cf1d72e 100644 (file)
@@ -136,16 +136,11 @@ int nfs40_discover_server_trunking(struct nfs_client *clp,
        clp->cl_confirm = clid.confirm;
 
        status = nfs40_walk_client_list(clp, result, cred);
-       switch (status) {
-       case -NFS4ERR_STALE_CLIENTID:
-               set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
-       case 0:
+       if (status == 0) {
                /* Sustain the lease, even if it's empty.  If the clientid4
                 * goes stale it's of no use for trunking discovery. */
                nfs4_schedule_state_renewal(*result);
-               break;
        }
-
 out:
        return status;
 }
@@ -1863,6 +1858,7 @@ again:
        case -ETIMEDOUT:
        case -EAGAIN:
                ssleep(1);
+       case -NFS4ERR_STALE_CLIENTID:
                dprintk("NFS: %s after status %d, retrying\n",
                        __func__, status);
                goto again;
@@ -2022,8 +2018,18 @@ static int nfs4_reset_session(struct nfs_client *clp)
        nfs4_begin_drain_session(clp);
        cred = nfs4_get_exchange_id_cred(clp);
        status = nfs4_proc_destroy_session(clp->cl_session, cred);
-       if (status && status != -NFS4ERR_BADSESSION &&
-           status != -NFS4ERR_DEADSESSION) {
+       switch (status) {
+       case 0:
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+               break;
+       case -NFS4ERR_BACK_CHAN_BUSY:
+       case -NFS4ERR_DELAY:
+               set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+               status = 0;
+               ssleep(1);
+               goto out;
+       default:
                status = nfs4_recovery_handle_error(clp, status);
                goto out;
        }
index e7165d915362838ab485e51ddde95db97ecd96c0..d00260b0810332c622e82faa44d4d94b75c111db 100644 (file)
@@ -254,7 +254,7 @@ static void
 pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit)
 {
        lo->plh_retry_timestamp = jiffies;
-       if (test_and_set_bit(fail_bit, &lo->plh_flags))
+       if (!test_and_set_bit(fail_bit, &lo->plh_flags))
                atomic_inc(&lo->plh_refcount);
 }
 
index b6bdb18e892c8ea5bf04869e296b1cdafca4d4a7..a5e5d9899d56fa622c1156609b406ee953527d6c 100644 (file)
@@ -91,12 +91,16 @@ void nfs_readdata_release(struct nfs_read_data *rdata)
        put_nfs_open_context(rdata->args.context);
        if (rdata->pages.pagevec != rdata->pages.page_array)
                kfree(rdata->pages.pagevec);
-       if (rdata != &read_header->rpc_data)
-               kfree(rdata);
-       else
+       if (rdata == &read_header->rpc_data) {
                rdata->header = NULL;
+               rdata = NULL;
+       }
        if (atomic_dec_and_test(&hdr->refcnt))
                hdr->completion_ops->completion(hdr);
+       /* Note: we only free the rpc_task after callbacks are done.
+        * See the comment in rpc_free_task() for why
+        */
+       kfree(rdata);
 }
 EXPORT_SYMBOL_GPL(nfs_readdata_release);
 
index aa5315bb3666817657e01323e84cb36c8c9f0078..b056b1628722218bbbadce33e86255e6953c8994 100644 (file)
@@ -1152,7 +1152,7 @@ static int nfs_get_option_str(substring_t args[], char **option)
 {
        kfree(*option);
        *option = match_strdup(args);
-       return !option;
+       return !*option;
 }
 
 static int nfs_get_option_ul(substring_t args[], unsigned long *option)
@@ -2375,19 +2375,30 @@ static void nfs_get_cache_cookie(struct super_block *sb,
                                 struct nfs_parsed_mount_data *parsed,
                                 struct nfs_clone_mount *cloned)
 {
+       struct nfs_server *nfss = NFS_SB(sb);
        char *uniq = NULL;
        int ulen = 0;
 
-       if (parsed && parsed->fscache_uniq) {
-               uniq = parsed->fscache_uniq;
-               ulen = strlen(parsed->fscache_uniq);
+       nfss->fscache_key = NULL;
+       nfss->fscache = NULL;
+
+       if (parsed) {
+               if (!(parsed->options & NFS_OPTION_FSCACHE))
+                       return;
+               if (parsed->fscache_uniq) {
+                       uniq = parsed->fscache_uniq;
+                       ulen = strlen(parsed->fscache_uniq);
+               }
        } else if (cloned) {
                struct nfs_server *mnt_s = NFS_SB(cloned->sb);
+               if (!(mnt_s->options & NFS_OPTION_FSCACHE))
+                       return;
                if (mnt_s->fscache_key) {
                        uniq = mnt_s->fscache_key->key.uniquifier;
                        ulen = mnt_s->fscache_key->key.uniq_len;
                };
-       }
+       } else
+               return;
 
        nfs_fscache_get_super_cookie(sb, uniq, ulen);
 }
@@ -2578,27 +2589,23 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
        struct nfs_server *server;
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
        struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
-       int error;
 
-       dprintk("--> nfs_xdev_mount_common()\n");
+       dprintk("--> nfs_xdev_mount()\n");
 
        mount_info.mntfh = mount_info.cloned->fh;
 
        /* create a new volume representation */
        server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
-       if (IS_ERR(server)) {
-               error = PTR_ERR(server);
-               goto out_err;
-       }
 
-       mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod);
-       dprintk("<-- nfs_xdev_mount_common() = 0\n");
-out:
-       return mntroot;
+       if (IS_ERR(server))
+               mntroot = ERR_CAST(server);
+       else
+               mntroot = nfs_fs_mount_common(server, flags,
+                               dev_name, &mount_info, nfs_mod);
 
-out_err:
-       dprintk("<-- nfs_xdev_mount_common() = %d [error]\n", error);
-       goto out;
+       dprintk("<-- nfs_xdev_mount() = %ld\n",
+                       IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
+       return mntroot;
 }
 
 #if IS_ENABLED(CONFIG_NFS_V4)
index 5209916e1222f6217ae3ac4fa9fddf36c9c77f2a..c483cc50b82ee5aa77f80f0d057550526469f466 100644 (file)
@@ -126,12 +126,16 @@ void nfs_writedata_release(struct nfs_write_data *wdata)
        put_nfs_open_context(wdata->args.context);
        if (wdata->pages.pagevec != wdata->pages.page_array)
                kfree(wdata->pages.pagevec);
-       if (wdata != &write_header->rpc_data)
-               kfree(wdata);
-       else
+       if (wdata == &write_header->rpc_data) {
                wdata->header = NULL;
+               wdata = NULL;
+       }
        if (atomic_dec_and_test(&hdr->refcnt))
                hdr->completion_ops->completion(hdr);
+       /* Note: we only free the rpc_task after callbacks are done.
+        * See the comment in rpc_free_task() for why
+        */
+       kfree(wdata);
 }
 EXPORT_SYMBOL_GPL(nfs_writedata_release);
 
@@ -1794,7 +1798,8 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
        if (PagePrivate(page))
                return -EBUSY;
 
-       nfs_fscache_release_page(page, GFP_KERNEL);
+       if (!nfs_fscache_release_page(page, GFP_KERNEL))
+               return -EBUSY;
 
        return migrate_page(mapping, newpage, page, mode);
 }
index e6c38159622fe6bc337f3d24ada7db683838ceac..e761ee95617fda7d1a388a4da38fec6712ae6a0c 100644 (file)
 #include <linux/fs.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
+#include <linux/nsproxy.h>
+#include <linux/sunrpc/clnt.h>
+#include <asm/uaccess.h>
 
 #include "state.h"
-#include "fault_inject.h"
+#include "netns.h"
 
 struct nfsd_fault_inject_op {
        char *file;
-       void (*func)(u64);
+       u64 (*forget)(struct nfs4_client *, u64);
+       u64 (*print)(struct nfs4_client *, u64);
 };
 
 static struct nfsd_fault_inject_op inject_ops[] = {
        {
                .file   = "forget_clients",
-               .func   = nfsd_forget_clients,
+               .forget = nfsd_forget_client,
+               .print  = nfsd_print_client,
        },
        {
                .file   = "forget_locks",
-               .func   = nfsd_forget_locks,
+               .forget = nfsd_forget_client_locks,
+               .print  = nfsd_print_client_locks,
        },
        {
                .file   = "forget_openowners",
-               .func   = nfsd_forget_openowners,
+               .forget = nfsd_forget_client_openowners,
+               .print  = nfsd_print_client_openowners,
        },
        {
                .file   = "forget_delegations",
-               .func   = nfsd_forget_delegations,
+               .forget = nfsd_forget_client_delegations,
+               .print  = nfsd_print_client_delegations,
        },
        {
                .file   = "recall_delegations",
-               .func   = nfsd_recall_delegations,
+               .forget = nfsd_recall_client_delegations,
+               .print  = nfsd_print_client_delegations,
        },
 };
 
 static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
 static struct dentry *debug_dir;
 
-static int nfsd_inject_set(void *op_ptr, u64 val)
+static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
 {
-       struct nfsd_fault_inject_op *op = op_ptr;
+       u64 count = 0;
 
        if (val == 0)
                printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file);
        else
                printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val);
 
-       op->func(val);
-       return 0;
+       nfs4_lock_state();
+       count = nfsd_for_n_state(val, op->forget);
+       nfs4_unlock_state();
+       printk(KERN_INFO "NFSD: %s: found %llu", op->file, count);
 }
 
-static int nfsd_inject_get(void *data, u64 *val)
+static void nfsd_inject_set_client(struct nfsd_fault_inject_op *op,
+                                  struct sockaddr_storage *addr,
+                                  size_t addr_size)
 {
-       *val = 0;
-       return 0;
+       char buf[INET6_ADDRSTRLEN];
+       struct nfs4_client *clp;
+       u64 count;
+
+       nfs4_lock_state();
+       clp = nfsd_find_client(addr, addr_size);
+       if (clp) {
+               count = op->forget(clp, 0);
+               rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
+               printk(KERN_INFO "NFSD [%s]: Client %s had %llu state object(s)\n", op->file, buf, count);
+       }
+       nfs4_unlock_state();
+}
+
+static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val)
+{
+       nfs4_lock_state();
+       *val = nfsd_for_n_state(0, op->print);
+       nfs4_unlock_state();
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(fops_nfsd, nfsd_inject_get, nfsd_inject_set, "%llu\n");
+static ssize_t fault_inject_read(struct file *file, char __user *buf,
+                                size_t len, loff_t *ppos)
+{
+       static u64 val;
+       char read_buf[25];
+       size_t size, ret;
+       loff_t pos = *ppos;
+
+       if (!pos)
+               nfsd_inject_get(file->f_dentry->d_inode->i_private, &val);
+       size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);
+
+       if (pos < 0)
+               return -EINVAL;
+       if (pos >= size || !len)
+               return 0;
+       if (len > size - pos)
+               len = size - pos;
+       ret = copy_to_user(buf, read_buf + pos, len);
+       if (ret == len)
+               return -EFAULT;
+       len -= ret;
+       *ppos = pos + len;
+       return len;
+}
+
+static ssize_t fault_inject_write(struct file *file, const char __user *buf,
+                                 size_t len, loff_t *ppos)
+{
+       char write_buf[INET6_ADDRSTRLEN];
+       size_t size = min(sizeof(write_buf) - 1, len);
+       struct net *net = current->nsproxy->net_ns;
+       struct sockaddr_storage sa;
+       u64 val;
+
+       if (copy_from_user(write_buf, buf, size))
+               return -EFAULT;
+       write_buf[size] = '\0';
+
+       size = rpc_pton(net, write_buf, size, (struct sockaddr *)&sa, sizeof(sa));
+       if (size > 0)
+               nfsd_inject_set_client(file->f_dentry->d_inode->i_private, &sa, size);
+       else {
+               val = simple_strtoll(write_buf, NULL, 0);
+               nfsd_inject_set(file->f_dentry->d_inode->i_private, val);
+       }
+       return len; /* on success, claim we got the whole input */
+}
+
+static const struct file_operations fops_nfsd = {
+       .owner   = THIS_MODULE,
+       .read    = fault_inject_read,
+       .write   = fault_inject_write,
+};
 
 void nfsd_fault_inject_cleanup(void)
 {
diff --git a/fs/nfsd/fault_inject.h b/fs/nfsd/fault_inject.h
deleted file mode 100644 (file)
index 90bd057..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
- *
- * Function definitions for fault injection
- */
-
-#ifndef LINUX_NFSD_FAULT_INJECT_H
-#define LINUX_NFSD_FAULT_INJECT_H
-
-#ifdef CONFIG_NFSD_FAULT_INJECTION
-int nfsd_fault_inject_init(void);
-void nfsd_fault_inject_cleanup(void);
-void nfsd_forget_clients(u64);
-void nfsd_forget_locks(u64);
-void nfsd_forget_openowners(u64);
-void nfsd_forget_delegations(u64);
-void nfsd_recall_delegations(u64);
-#else /* CONFIG_NFSD_FAULT_INJECTION */
-static inline int nfsd_fault_inject_init(void) { return 0; }
-static inline void nfsd_fault_inject_cleanup(void) {}
-static inline void nfsd_forget_clients(u64 num) {}
-static inline void nfsd_forget_locks(u64 num) {}
-static inline void nfsd_forget_openowners(u64 num) {}
-static inline void nfsd_forget_delegations(u64 num) {}
-static inline void nfsd_recall_delegations(u64 num) {}
-#endif /* CONFIG_NFSD_FAULT_INJECTION */
-
-#endif /* LINUX_NFSD_FAULT_INJECT_H */
index 65c2431ea32fa6638cc34b8f240b351328bad751..1051bebff1b0d5c0c1da8d82043506d7eca465d3 100644 (file)
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
+/* Hash tables for nfs4_clientid state */
+#define CLIENT_HASH_BITS                 4
+#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
+#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
+
+#define LOCKOWNER_INO_HASH_BITS                8
+#define LOCKOWNER_INO_HASH_SIZE                (1 << LOCKOWNER_INO_HASH_BITS)
+
+#define SESSION_HASH_SIZE      512
+
 struct cld_net;
+struct nfsd4_client_tracking_ops;
 
 struct nfsd_net {
        struct cld_net *cld_net;
@@ -38,7 +49,62 @@ struct nfsd_net {
        struct lock_manager nfsd4_manager;
        bool grace_ended;
        time_t boot_time;
+
+       /*
+        * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
+        * used in reboot/reset lease grace period processing
+        *
+        * conf_id_hashtbl[], and conf_name_tree hold confirmed
+        * setclientid_confirmed info.
+        *
+        * unconf_str_hastbl[] and unconf_name_tree hold unconfirmed
+        * setclientid info.
+        */
+       struct list_head *reclaim_str_hashtbl;
+       int reclaim_str_hashtbl_size;
+       struct list_head *conf_id_hashtbl;
+       struct rb_root conf_name_tree;
+       struct list_head *unconf_id_hashtbl;
+       struct rb_root unconf_name_tree;
+       struct list_head *ownerstr_hashtbl;
+       struct list_head *lockowner_ino_hashtbl;
+       struct list_head *sessionid_hashtbl;
+       /*
+        * client_lru holds client queue ordered by nfs4_client.cl_time
+        * for lease renewal.
+        *
+        * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
+        * for last close replay.
+        *
+        * All of the above fields are protected by the client_mutex.
+        */
+       struct list_head client_lru;
+       struct list_head close_lru;
+
+       struct delayed_work laundromat_work;
+
+       /* client_lock protects the client lru list and session hash table */
+       spinlock_t client_lock;
+
+       struct file *rec_file;
+       bool in_grace;
+       struct nfsd4_client_tracking_ops *client_tracking_ops;
+
+       time_t nfsd4_lease;
+       time_t nfsd4_grace;
+
+       bool nfsd_net_up;
+
+       /*
+        * Time of server startup
+        */
+       struct timeval nfssvc_boot;
+
+       struct svc_serv *nfsd_serv;
 };
 
+/* Simple check to find out if a given net was properly initialized */
+#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
+
 extern int nfsd_net_id;
 #endif /* __NFSD_NETNS_H__ */
index b314888825d5e939e0a850bcd29553292a87af44..9170861c804a6de666e8ef385ec582d81b30bb92 100644 (file)
@@ -253,7 +253,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
                (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
                (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
        while (w > 0) {
-               if (!rqstp->rq_respages[rqstp->rq_resused++])
+               if (!*(rqstp->rq_next_page++))
                        return 0;
                w -= PAGE_SIZE;
        }
index a596e9d987e46abb499ee8ac6dcd44472d02bc71..9cbc1a841f87b39d47e81f40cf1e8eac6161a3d2 100644 (file)
@@ -184,7 +184,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
                        (resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
                        (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
                while (w > 0) {
-                       if (!rqstp->rq_respages[rqstp->rq_resused++])
+                       if (!*(rqstp->rq_next_page++))
                                return 0;
                        w -= PAGE_SIZE;
                }
index 97d90d1c86081edf89259bfc1c745082660855fc..1fc02dfdc5c4354d296c21e814362f8e411e91ee 100644 (file)
@@ -460,7 +460,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
        __be32  nfserr;
        int     count = 0;
        loff_t  offset;
-       int     i;
+       struct page **p;
        caddr_t page_addr = NULL;
 
        dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
@@ -484,8 +484,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
                                     &resp->common,
                                     nfs3svc_encode_entry_plus);
        memcpy(resp->verf, argp->verf, 8);
-       for (i=1; i<rqstp->rq_resused ; i++) {
-               page_addr = page_address(rqstp->rq_respages[i]);
+       for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
+               page_addr = page_address(*p);
 
                if (((caddr_t)resp->buffer >= page_addr) &&
                    ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
index 43f46cd9edea84e18040381a2647a54ca59debb0..324c0baf7cda30c0f6123417673dc395c8e292ff 100644 (file)
@@ -7,8 +7,10 @@
  */
 
 #include <linux/namei.h>
+#include <linux/sunrpc/svc_xprt.h>
 #include "xdr3.h"
 #include "auth.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY               NFSDDBG_XDR
 
@@ -323,7 +325,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_readargs *args)
 {
        unsigned int len;
-       int v,pn;
+       int v;
        u32 max_blocksize = svc_max_payload(rqstp);
 
        if (!(p = decode_fh(p, &args->fh)))
@@ -338,8 +340,9 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        /* set up the kvec */
        v=0;
        while (len > 0) {
-               pn = rqstp->rq_resused++;
-               rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
+               struct page *p = *(rqstp->rq_next_page++);
+
+               rqstp->rq_vec[v].iov_base = page_address(p);
                rqstp->rq_vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
                len -= rqstp->rq_vec[v].iov_len;
                v++;
@@ -461,8 +464,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
        len = ntohl(*p++);
        if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
                return 0;
-       args->tname = new =
-               page_address(rqstp->rq_respages[rqstp->rq_resused++]);
+       args->tname = new = page_address(*(rqstp->rq_next_page++));
        args->tlen = len;
        /* first copy and check from the first page */
        old = (char*)p;
@@ -533,8 +535,7 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
 {
        if (!(p = decode_fh(p, &args->fh)))
                return 0;
-       args->buffer =
-               page_address(rqstp->rq_respages[rqstp->rq_resused++]);
+       args->buffer = page_address(*(rqstp->rq_next_page++));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -565,8 +566,7 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        if (args->count > PAGE_SIZE)
                args->count = PAGE_SIZE;
 
-       args->buffer =
-               page_address(rqstp->rq_respages[rqstp->rq_resused++]);
+       args->buffer = page_address(*(rqstp->rq_next_page++));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -575,7 +575,7 @@ int
 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_readdirargs *args)
 {
-       int len, pn;
+       int len;
        u32 max_blocksize = svc_max_payload(rqstp);
 
        if (!(p = decode_fh(p, &args->fh)))
@@ -590,9 +590,9 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
        args->count = len;
 
        while (len > 0) {
-               pn = rqstp->rq_resused++;
+               struct page *p = *(rqstp->rq_next_page++);
                if (!args->buffer)
-                       args->buffer = page_address(rqstp->rq_respages[pn]);
+                       args->buffer = page_address(p);
                len -= PAGE_SIZE;
        }
 
@@ -720,12 +720,14 @@ int
 nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_writeres *resp)
 {
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
        p = encode_wcc_data(rqstp, p, &resp->fh);
        if (resp->status == 0) {
                *p++ = htonl(resp->count);
                *p++ = htonl(resp->committed);
-               *p++ = htonl(nfssvc_boot.tv_sec);
-               *p++ = htonl(nfssvc_boot.tv_usec);
+               *p++ = htonl(nn->nfssvc_boot.tv_sec);
+               *p++ = htonl(nn->nfssvc_boot.tv_usec);
        }
        return xdr_ressize_check(rqstp, p);
 }
@@ -876,7 +878,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
                                                        common);
        __be32          *p = cd->buffer;
        caddr_t         curr_page_addr = NULL;
-       int             pn;             /* current page number */
+       struct page **  page;
        int             slen;           /* string (name) length */
        int             elen;           /* estimated entry length in words */
        int             num_entry_words = 0;    /* actual number of words */
@@ -913,8 +915,9 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
        }
 
        /* determine which page in rq_respages[] we are currently filling */
-       for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
-               curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
+       for (page = cd->rqstp->rq_respages + 1;
+                               page < cd->rqstp->rq_next_page; page++) {
+               curr_page_addr = page_address(*page);
 
                if (((caddr_t)cd->buffer >= curr_page_addr) &&
                    ((caddr_t)cd->buffer <  curr_page_addr + PAGE_SIZE))
@@ -929,14 +932,14 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
                if (plus)
                        p = encode_entryplus_baggage(cd, p, name, namlen);
                num_entry_words = p - cd->buffer;
-       } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
+       } else if (*(page+1) != NULL) {
                /* temporarily encode entry into next page, then move back to
                 * current and next page in rq_respages[] */
                __be32 *p1, *tmp;
                int len1, len2;
 
                /* grab next page for temporary storage of entry */
-               p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
+               p1 = tmp = page_address(*(page+1));
 
                p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
 
@@ -1082,11 +1085,13 @@ int
 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_commitres *resp)
 {
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
        p = encode_wcc_data(rqstp, p, &resp->fh);
        /* Write verifier */
        if (resp->status == 0) {
-               *p++ = htonl(nfssvc_boot.tv_sec);
-               *p++ = htonl(nfssvc_boot.tv_usec);
+               *p++ = htonl(nn->nfssvc_boot.tv_sec);
+               *p++ = htonl(nn->nfssvc_boot.tv_usec);
        }
        return xdr_ressize_check(rqstp, p);
 }
index bdf29c96e4cdbed8eff6d25bb28022ead1e0122e..99bc85ff02179f3e28ed36f56872e1e48d190e21 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include "nfsd.h"
 #include "state.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -625,20 +626,46 @@ static const struct rpc_program cb_program = {
        .pipe_dir_name          = "nfsd4_cb",
 };
 
-static int max_cb_time(void)
+static int max_cb_time(struct net *net)
 {
-       return max(nfsd4_lease/10, (time_t)1) * HZ;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
 }
 
+static struct rpc_cred *callback_cred;
+
+int set_callback_cred(void)
+{
+       if (callback_cred)
+               return 0;
+       callback_cred = rpc_lookup_machine_cred("nfs");
+       if (!callback_cred)
+               return -ENOMEM;
+       return 0;
+}
+
+static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
+{
+       if (clp->cl_minorversion == 0) {
+               return get_rpccred(callback_cred);
+       } else {
+               struct rpc_auth *auth = client->cl_auth;
+               struct auth_cred acred = {};
+
+               acred.uid = ses->se_cb_sec.uid;
+               acred.gid = ses->se_cb_sec.gid;
+               return auth->au_ops->lookup_cred(client->cl_auth, &acred, 0);
+       }
+}
 
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
        struct rpc_timeout      timeparms = {
-               .to_initval     = max_cb_time(),
+               .to_initval     = max_cb_time(clp->net),
                .to_retries     = 0,
        };
        struct rpc_create_args args = {
-               .net            = &init_net,
+               .net            = clp->net,
                .address        = (struct sockaddr *) &conn->cb_addr,
                .addrsize       = conn->cb_addrlen,
                .saddress       = (struct sockaddr *) &conn->cb_saddr,
@@ -648,6 +675,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
        };
        struct rpc_clnt *client;
+       struct rpc_cred *cred;
 
        if (clp->cl_minorversion == 0) {
                if (!clp->cl_cred.cr_principal &&
@@ -666,7 +694,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                args.bc_xprt = conn->cb_xprt;
                args.prognumber = clp->cl_cb_session->se_cb_prog;
                args.protocol = XPRT_TRANSPORT_BC_TCP;
-               args.authflavor = RPC_AUTH_UNIX;
+               args.authflavor = ses->se_cb_sec.flavor;
        }
        /* Create RPC client */
        client = rpc_create(&args);
@@ -675,9 +703,14 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                        PTR_ERR(client));
                return PTR_ERR(client);
        }
+       cred = get_backchannel_cred(clp, client, ses);
+       if (IS_ERR(cred)) {
+               rpc_shutdown_client(client);
+               return PTR_ERR(cred);
+       }
        clp->cl_cb_client = client;
+       clp->cl_cb_cred = cred;
        return 0;
-
 }
 
 static void warn_no_callback_path(struct nfs4_client *clp, int reason)
@@ -714,18 +747,6 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
        .rpc_call_done = nfsd4_cb_probe_done,
 };
 
-static struct rpc_cred *callback_cred;
-
-int set_callback_cred(void)
-{
-       if (callback_cred)
-               return 0;
-       callback_cred = rpc_lookup_machine_cred("nfs");
-       if (!callback_cred)
-               return -ENOMEM;
-       return 0;
-}
-
 static struct workqueue_struct *callback_wq;
 
 static void run_nfsd4_cb(struct nfsd4_callback *cb)
@@ -743,7 +764,6 @@ static void do_probe_callback(struct nfs4_client *clp)
        cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
        cb->cb_msg.rpc_argp = NULL;
        cb->cb_msg.rpc_resp = NULL;
-       cb->cb_msg.rpc_cred = callback_cred;
 
        cb->cb_ops = &nfsd4_cb_probe_ops;
 
@@ -962,6 +982,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
        if (clp->cl_cb_client) {
                rpc_shutdown_client(clp->cl_cb_client);
                clp->cl_cb_client = NULL;
+               put_rpccred(clp->cl_cb_cred);
+               clp->cl_cb_cred = NULL;
        }
        if (clp->cl_cb_conn.cb_xprt) {
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
@@ -995,7 +1017,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
                run_nfsd4_cb(cb);
 }
 
-void nfsd4_do_callback_rpc(struct work_struct *w)
+static void nfsd4_do_callback_rpc(struct work_struct *w)
 {
        struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
        struct nfs4_client *clp = cb->cb_clp;
@@ -1010,10 +1032,16 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
                nfsd4_release_cb(cb);
                return;
        }
+       cb->cb_msg.rpc_cred = clp->cl_cb_cred;
        rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
                        cb->cb_ops, cb);
 }
 
+void nfsd4_init_callback(struct nfsd4_callback *cb)
+{
+       INIT_WORK(&cb->cb_work, nfsd4_do_callback_rpc);
+}
+
 void nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
        struct nfsd4_callback *cb = &dp->dl_recall;
@@ -1025,7 +1053,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
        cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
        cb->cb_msg.rpc_argp = cb;
        cb->cb_msg.rpc_resp = cb;
-       cb->cb_msg.rpc_cred = callback_cred;
 
        cb->cb_ops = &nfsd4_cb_recall_ops;
 
index 6c9a4b291dba2c7e44498a32dc46ab6973e922c9..9d1c5dba2bbb6625df90cebca48a364a29b9fe97 100644 (file)
@@ -40,6 +40,7 @@
 #include "xdr4.h"
 #include "vfs.h"
 #include "current_stateid.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY               NFSDDBG_PROC
 
@@ -194,6 +195,7 @@ static __be32
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
        struct svc_fh *resfh;
+       int accmode;
        __be32 status;
 
        resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
@@ -253,9 +255,10 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
        /* set reply cache */
        fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
                        &resfh->fh_handle);
-       if (!open->op_created)
-               status = do_open_permission(rqstp, resfh, open,
-                                           NFSD_MAY_NOP);
+       accmode = NFSD_MAY_NOP;
+       if (open->op_created)
+               accmode |= NFSD_MAY_OWNER_OVERRIDE;
+       status = do_open_permission(rqstp, resfh, open, accmode);
        set_change_info(&open->op_cinfo, current_fh);
        fh_dup2(current_fh, resfh);
 out:
@@ -304,6 +307,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        __be32 status;
        struct nfsd4_compoundres *resp;
+       struct net *net = SVC_NET(rqstp);
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
                (int)open->op_fname.len, open->op_fname.data,
@@ -331,7 +336,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        /* check seqid for replay. set nfs4_owner */
        resp = rqstp->rq_resp;
-       status = nfsd4_process_open1(&resp->cstate, open);
+       status = nfsd4_process_open1(&resp->cstate, open, nn);
        if (status == nfserr_replay_me) {
                struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
                fh_put(&cstate->current_fh);
@@ -354,10 +359,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        /* Openowner is now set, so sequence id will get bumped.  Now we need
         * these checks before we do any creates: */
        status = nfserr_grace;
-       if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+       if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
                goto out;
        status = nfserr_no_grace;
-       if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+       if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
                goto out;
 
        switch (open->op_claim_type) {
@@ -370,7 +375,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        break;
                case NFS4_OPEN_CLAIM_PREVIOUS:
                        open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
-                       status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
+                       status = nfs4_check_open_reclaim(&open->op_clientid,
+                                                        cstate->minorversion,
+                                                        nn);
                        if (status)
                                goto out;
                case NFS4_OPEN_CLAIM_FH:
@@ -490,12 +497,13 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                           &access->ac_supported);
 }
 
-static void gen_boot_verifier(nfs4_verifier *verifier)
+static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
 {
        __be32 verf[2];
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-       verf[0] = (__be32)nfssvc_boot.tv_sec;
-       verf[1] = (__be32)nfssvc_boot.tv_usec;
+       verf[0] = (__be32)nn->nfssvc_boot.tv_sec;
+       verf[1] = (__be32)nn->nfssvc_boot.tv_usec;
        memcpy(verifier->data, verf, sizeof(verifier->data));
 }
 
@@ -503,7 +511,7 @@ static __be32
 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
             struct nfsd4_commit *commit)
 {
-       gen_boot_verifier(&commit->co_verf);
+       gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp));
        return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
                             commit->co_count);
 }
@@ -684,6 +692,17 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (read->rd_offset >= OFFSET_MAX)
                return nfserr_inval;
 
+       /*
+        * If we do a zero copy read, then a client will see read data
+        * that reflects the state of the file *after* performing the
+        * following compound.
+        *
+        * To ensure proper ordering, we therefore turn off zero copy if
+        * the client wants us to do more in this compound:
+        */
+       if (!nfsd4_last_compound_op(rqstp))
+               rqstp->rq_splice_ok = false;
+
        nfs4_lock_state();
        /* check stateid */
        if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
@@ -876,6 +895,24 @@ out:
        return status;
 }
 
+static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
+{
+        int i = 1;
+        int buflen = write->wr_buflen;
+
+        vec[0].iov_base = write->wr_head.iov_base;
+        vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
+        buflen -= vec[0].iov_len;
+
+        while (buflen) {
+                vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
+                vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
+                buflen -= vec[i].iov_len;
+                i++;
+        }
+        return i;
+}
+
 static __be32
 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            struct nfsd4_write *write)
@@ -884,6 +921,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct file *filp = NULL;
        __be32 status = nfs_ok;
        unsigned long cnt;
+       int nvecs;
 
        /* no need to check permission - this will be done in nfsd_write() */
 
@@ -904,10 +942,13 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        cnt = write->wr_buflen;
        write->wr_how_written = write->wr_stable_how;
-       gen_boot_verifier(&write->wr_verifier);
+       gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
+
+       nvecs = fill_in_write_vector(rqstp->rq_vec, write);
+       WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
 
        status =  nfsd_write(rqstp, &cstate->current_fh, filp,
-                            write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+                            write->wr_offset, rqstp->rq_vec, nvecs,
                             &cnt, &write->wr_how_written);
        if (filp)
                fput(filp);
@@ -1666,6 +1707,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_name = "OP_EXCHANGE_ID",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize,
        },
+       [OP_BACKCHANNEL_CTL] = {
+               .op_func = (nfsd4op_func)nfsd4_backchannel_ctl,
+               .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
+               .op_name = "OP_BACKCHANNEL_CTL",
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
+       },
        [OP_BIND_CONN_TO_SESSION] = {
                .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
@@ -1719,6 +1766,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_func = (nfsd4op_func)nfsd4_free_stateid,
                .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
                .op_name = "OP_FREE_STATEID",
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid,
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
 };
index 43295d45cc2b553e2afda4d11d7b2d429b8676ef..ba6fdd4a0455d6c2f970e2bb33ec3a5e369dce8d 100644 (file)
@@ -58,13 +58,11 @@ struct nfsd4_client_tracking_ops {
        void (*create)(struct nfs4_client *);
        void (*remove)(struct nfs4_client *);
        int (*check)(struct nfs4_client *);
-       void (*grace_done)(struct net *, time_t);
+       void (*grace_done)(struct nfsd_net *, time_t);
 };
 
 /* Globals */
-static struct file *rec_file;
 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
-static struct nfsd4_client_tracking_ops *client_tracking_ops;
 
 static int
 nfs4_save_creds(const struct cred **original_creds)
@@ -102,33 +100,39 @@ md5_to_hex(char *out, char *md5)
        *out = '\0';
 }
 
-__be32
-nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+static int
+nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname)
 {
        struct xdr_netobj cksum;
        struct hash_desc desc;
        struct scatterlist sg;
-       __be32 status = nfserr_jukebox;
+       int status;
 
        dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
                        clname->len, clname->data);
        desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
        desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(desc.tfm))
+       if (IS_ERR(desc.tfm)) {
+               status = PTR_ERR(desc.tfm);
                goto out_no_tfm;
+       }
+
        cksum.len = crypto_hash_digestsize(desc.tfm);
        cksum.data = kmalloc(cksum.len, GFP_KERNEL);
-       if (cksum.data == NULL)
+       if (cksum.data == NULL) {
+               status = -ENOMEM;
                goto out;
+       }
 
        sg_init_one(&sg, clname->data, clname->len);
 
-       if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data))
+       status = crypto_hash_digest(&desc, &sg, sg.length, cksum.data);
+       if (status)
                goto out;
 
        md5_to_hex(dname, cksum.data);
 
-       status = nfs_ok;
+       status = 0;
 out:
        kfree(cksum.data);
        crypto_free_hash(desc.tfm);
@@ -136,29 +140,61 @@ out_no_tfm:
        return status;
 }
 
+/*
+ * If we had an error generating the recdir name for the legacy tracker
+ * then warn the admin. If the error doesn't appear to be transient,
+ * then disable recovery tracking.
+ */
+static void
+legacy_recdir_name_error(int error)
+{
+       printk(KERN_ERR "NFSD: unable to generate recoverydir "
+                       "name (%d).\n", error);
+
+       /*
+        * if the algorithm just doesn't exist, then disable the recovery
+        * tracker altogether. The crypto libs will generally return this if
+        * FIPS is enabled as well.
+        */
+       if (error == -ENOENT) {
+               printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
+                       "Reboot recovery will not function correctly!\n");
+
+               /* the argument is ignored by the legacy exit function */
+               nfsd4_client_tracking_exit(NULL);
+       }
+}
+
 static void
 nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
-       char *dname = clp->cl_recdir;
+       char dname[HEXDIR_LEN];
        struct dentry *dir, *dentry;
+       struct nfs4_client_reclaim *crp;
        int status;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
        dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
 
        if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return;
-       if (!rec_file)
+       if (!nn->rec_file)
                return;
+
+       status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+       if (status)
+               return legacy_recdir_name_error(status);
+
        status = nfs4_save_creds(&original_cred);
        if (status < 0)
                return;
 
-       status = mnt_want_write_file(rec_file);
+       status = mnt_want_write_file(nn->rec_file);
        if (status)
                return;
 
-       dir = rec_file->f_path.dentry;
+       dir = nn->rec_file->f_path.dentry;
        /* lock the parent */
        mutex_lock(&dir->d_inode->i_mutex);
 
@@ -182,18 +218,24 @@ out_put:
        dput(dentry);
 out_unlock:
        mutex_unlock(&dir->d_inode->i_mutex);
-       if (status == 0)
-               vfs_fsync(rec_file, 0);
-       else
+       if (status == 0) {
+               if (nn->in_grace) {
+                       crp = nfs4_client_to_reclaim(dname, nn);
+                       if (crp)
+                               crp->cr_clp = clp;
+               }
+               vfs_fsync(nn->rec_file, 0);
+       } else {
                printk(KERN_ERR "NFSD: failed to write recovery record"
                                " (err %d); please check that %s exists"
                                " and is writeable", status,
                                user_recovery_dirname);
-       mnt_drop_write_file(rec_file);
+       }
+       mnt_drop_write_file(nn->rec_file);
        nfs4_reset_creds(original_cred);
 }
 
-typedef int (recdir_func)(struct dentry *, struct dentry *);
+typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
 
 struct name_list {
        char name[HEXDIR_LEN];
@@ -219,10 +261,10 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
 }
 
 static int
-nfsd4_list_rec_dir(recdir_func *f)
+nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
 {
        const struct cred *original_cred;
-       struct dentry *dir = rec_file->f_path.dentry;
+       struct dentry *dir = nn->rec_file->f_path.dentry;
        LIST_HEAD(names);
        int status;
 
@@ -230,13 +272,13 @@ nfsd4_list_rec_dir(recdir_func *f)
        if (status < 0)
                return status;
 
-       status = vfs_llseek(rec_file, 0, SEEK_SET);
+       status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
        if (status < 0) {
                nfs4_reset_creds(original_cred);
                return status;
        }
 
-       status = vfs_readdir(rec_file, nfsd4_build_namelist, &names);
+       status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
        mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
        while (!list_empty(&names)) {
                struct name_list *entry;
@@ -248,7 +290,7 @@ nfsd4_list_rec_dir(recdir_func *f)
                                status = PTR_ERR(dentry);
                                break;
                        }
-                       status = f(dir, dentry);
+                       status = f(dir, dentry, nn);
                        dput(dentry);
                }
                list_del(&entry->list);
@@ -260,14 +302,14 @@ nfsd4_list_rec_dir(recdir_func *f)
 }
 
 static int
-nfsd4_unlink_clid_dir(char *name, int namlen)
+nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
 {
        struct dentry *dir, *dentry;
        int status;
 
        dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
 
-       dir = rec_file->f_path.dentry;
+       dir = nn->rec_file->f_path.dentry;
        mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
        dentry = lookup_one_len(name, dir, namlen);
        if (IS_ERR(dentry)) {
@@ -289,37 +331,52 @@ static void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
+       struct nfs4_client_reclaim *crp;
+       char dname[HEXDIR_LEN];
        int status;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-       if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+       if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return;
 
-       status = mnt_want_write_file(rec_file);
+       status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+       if (status)
+               return legacy_recdir_name_error(status);
+
+       status = mnt_want_write_file(nn->rec_file);
        if (status)
                goto out;
        clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
 
        status = nfs4_save_creds(&original_cred);
        if (status < 0)
-               goto out;
+               goto out_drop_write;
 
-       status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+       status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
        nfs4_reset_creds(original_cred);
-       if (status == 0)
-               vfs_fsync(rec_file, 0);
-       mnt_drop_write_file(rec_file);
+       if (status == 0) {
+               vfs_fsync(nn->rec_file, 0);
+               if (nn->in_grace) {
+                       /* remove reclaim record */
+                       crp = nfsd4_find_reclaim_client(dname, nn);
+                       if (crp)
+                               nfs4_remove_reclaim_record(crp, nn);
+               }
+       }
+out_drop_write:
+       mnt_drop_write_file(nn->rec_file);
 out:
        if (status)
                printk("NFSD: Failed to remove expired client state directory"
-                               " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+                               " %.*s\n", HEXDIR_LEN, dname);
 }
 
 static int
-purge_old(struct dentry *parent, struct dentry *child)
+purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
        int status;
 
-       if (nfs4_has_reclaimed_state(child->d_name.name, false))
+       if (nfs4_has_reclaimed_state(child->d_name.name, nn))
                return 0;
 
        status = vfs_rmdir(parent->d_inode, child);
@@ -331,27 +388,29 @@ purge_old(struct dentry *parent, struct dentry *child)
 }
 
 static void
-nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
+nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
 {
        int status;
 
-       if (!rec_file)
+       nn->in_grace = false;
+       if (!nn->rec_file)
                return;
-       status = mnt_want_write_file(rec_file);
+       status = mnt_want_write_file(nn->rec_file);
        if (status)
                goto out;
-       status = nfsd4_list_rec_dir(purge_old);
+       status = nfsd4_list_rec_dir(purge_old, nn);
        if (status == 0)
-               vfs_fsync(rec_file, 0);
-       mnt_drop_write_file(rec_file);
+               vfs_fsync(nn->rec_file, 0);
+       mnt_drop_write_file(nn->rec_file);
 out:
+       nfs4_release_reclaim(nn);
        if (status)
                printk("nfsd4: failed to purge old clients from recovery"
-                       " directory %s\n", rec_file->f_path.dentry->d_name.name);
+                       " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
 }
 
 static int
-load_recdir(struct dentry *parent, struct dentry *child)
+load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
        if (child->d_name.len != HEXDIR_LEN - 1) {
                printk("nfsd4: illegal name %s in recovery directory\n",
@@ -359,21 +418,22 @@ load_recdir(struct dentry *parent, struct dentry *child)
                /* Keep trying; maybe the others are OK: */
                return 0;
        }
-       nfs4_client_to_reclaim(child->d_name.name);
+       nfs4_client_to_reclaim(child->d_name.name, nn);
        return 0;
 }
 
 static int
-nfsd4_recdir_load(void) {
+nfsd4_recdir_load(struct net *net) {
        int status;
+       struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
 
-       if (!rec_file)
+       if (!nn->rec_file)
                return 0;
 
-       status = nfsd4_list_rec_dir(load_recdir);
+       status = nfsd4_list_rec_dir(load_recdir, nn);
        if (status)
                printk("nfsd4: failed loading clients from recovery"
-                       " directory %s\n", rec_file->f_path.dentry->d_name.name);
+                       " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
        return status;
 }
 
@@ -382,15 +442,16 @@ nfsd4_recdir_load(void) {
  */
 
 static int
-nfsd4_init_recdir(void)
+nfsd4_init_recdir(struct net *net)
 {
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        const struct cred *original_cred;
        int status;
 
        printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
                        user_recovery_dirname);
 
-       BUG_ON(rec_file);
+       BUG_ON(nn->rec_file);
 
        status = nfs4_save_creds(&original_cred);
        if (status < 0) {
@@ -400,23 +461,65 @@ nfsd4_init_recdir(void)
                return status;
        }
 
-       rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
-       if (IS_ERR(rec_file)) {
+       nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
+       if (IS_ERR(nn->rec_file)) {
                printk("NFSD: unable to find recovery directory %s\n",
                                user_recovery_dirname);
-               status = PTR_ERR(rec_file);
-               rec_file = NULL;
+               status = PTR_ERR(nn->rec_file);
+               nn->rec_file = NULL;
        }
 
        nfs4_reset_creds(original_cred);
+       if (!status)
+               nn->in_grace = true;
        return status;
 }
 
+
+static int
+nfs4_legacy_state_init(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int i;
+
+       nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
+                                         CLIENT_HASH_SIZE, GFP_KERNEL);
+       if (!nn->reclaim_str_hashtbl)
+               return -ENOMEM;
+
+       for (i = 0; i < CLIENT_HASH_SIZE; i++)
+               INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
+       nn->reclaim_str_hashtbl_size = 0;
+
+       return 0;
+}
+
+static void
+nfs4_legacy_state_shutdown(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       kfree(nn->reclaim_str_hashtbl);
+}
+
 static int
 nfsd4_load_reboot_recovery_data(struct net *net)
 {
        int status;
 
+       status = nfsd4_init_recdir(net);
+       if (!status)
+               status = nfsd4_recdir_load(net);
+       if (status)
+               printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+       return status;
+}
+
+static int
+nfsd4_legacy_tracking_init(struct net *net)
+{
+       int status;
+
        /* XXX: The legacy code won't work in a container */
        if (net != &init_net) {
                WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
@@ -424,30 +527,37 @@ nfsd4_load_reboot_recovery_data(struct net *net)
                return -EINVAL;
        }
 
-       nfs4_lock_state();
-       status = nfsd4_init_recdir();
-       if (!status)
-               status = nfsd4_recdir_load();
-       nfs4_unlock_state();
+       status = nfs4_legacy_state_init(net);
        if (status)
-               printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+               return status;
+
+       status = nfsd4_load_reboot_recovery_data(net);
+       if (status)
+               goto err;
+       return 0;
+
+err:
+       nfs4_legacy_state_shutdown(net);
        return status;
 }
 
 static void
-nfsd4_shutdown_recdir(void)
+nfsd4_shutdown_recdir(struct nfsd_net *nn)
 {
-       if (!rec_file)
+       if (!nn->rec_file)
                return;
-       fput(rec_file);
-       rec_file = NULL;
+       fput(nn->rec_file);
+       nn->rec_file = NULL;
 }
 
 static void
 nfsd4_legacy_tracking_exit(struct net *net)
 {
-       nfs4_release_reclaim();
-       nfsd4_shutdown_recdir();
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       nfs4_release_reclaim(nn);
+       nfsd4_shutdown_recdir(nn);
+       nfs4_legacy_state_shutdown(net);
 }
 
 /*
@@ -480,13 +590,26 @@ nfs4_recoverydir(void)
 static int
 nfsd4_check_legacy_client(struct nfs4_client *clp)
 {
+       int status;
+       char dname[HEXDIR_LEN];
+       struct nfs4_client_reclaim *crp;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
        /* did we already find that this client is stable? */
        if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return 0;
 
+       status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+       if (status) {
+               legacy_recdir_name_error(status);
+               return status;
+       }
+
        /* look for it in the reclaim hashtable otherwise */
-       if (nfsd4_find_reclaim_client(clp)) {
+       crp = nfsd4_find_reclaim_client(dname, nn);
+       if (crp) {
                set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+               crp->cr_clp = clp;
                return 0;
        }
 
@@ -494,7 +617,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
 }
 
 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
-       .init           = nfsd4_load_reboot_recovery_data,
+       .init           = nfsd4_legacy_tracking_init,
        .exit           = nfsd4_legacy_tracking_exit,
        .create         = nfsd4_create_clid_dir,
        .remove         = nfsd4_remove_clid_dir,
@@ -785,8 +908,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
 {
        int ret;
        struct cld_upcall *cup;
-       /* FIXME: determine net from clp */
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
        struct cld_net *cn = nn->cld_net;
 
        /* Don't upcall if it's already stored */
@@ -823,8 +945,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
 {
        int ret;
        struct cld_upcall *cup;
-       /* FIXME: determine net from clp */
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
        struct cld_net *cn = nn->cld_net;
 
        /* Don't upcall if it's already removed */
@@ -861,8 +982,7 @@ nfsd4_cld_check(struct nfs4_client *clp)
 {
        int ret;
        struct cld_upcall *cup;
-       /* FIXME: determine net from clp */
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
        struct cld_net *cn = nn->cld_net;
 
        /* Don't upcall if one was already stored during this grace pd */
@@ -892,11 +1012,10 @@ nfsd4_cld_check(struct nfs4_client *clp)
 }
 
 static void
-nfsd4_cld_grace_done(struct net *net, time_t boot_time)
+nfsd4_cld_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
        int ret;
        struct cld_upcall *cup;
-       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        struct cld_net *cn = nn->cld_net;
 
        cup = alloc_cld_upcall(cn);
@@ -926,28 +1045,261 @@ static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
        .grace_done     = nfsd4_cld_grace_done,
 };
 
+/* upcall via usermodehelper */
+static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
+module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
+                       S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
+
+static bool cltrack_legacy_disable;
+module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cltrack_legacy_disable,
+               "Disable legacy recoverydir conversion. Default: false");
+
+#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
+#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
+
+static char *
+nfsd4_cltrack_legacy_topdir(void)
+{
+       int copied;
+       size_t len;
+       char *result;
+
+       if (cltrack_legacy_disable)
+               return NULL;
+
+       len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
+               strlen(nfs4_recoverydir()) + 1;
+
+       result = kmalloc(len, GFP_KERNEL);
+       if (!result)
+               return result;
+
+       copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
+                               nfs4_recoverydir());
+       if (copied >= len) {
+               /* just return nothing if output was truncated */
+               kfree(result);
+               return NULL;
+       }
+
+       return result;
+}
+
+static char *
+nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
+{
+       int copied;
+       size_t len;
+       char *result;
+
+       if (cltrack_legacy_disable)
+               return NULL;
+
+       /* +1 is for '/' between "topdir" and "recdir" */
+       len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
+               strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
+
+       result = kmalloc(len, GFP_KERNEL);
+       if (!result)
+               return result;
+
+       copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/",
+                               nfs4_recoverydir());
+       if (copied > (len - HEXDIR_LEN)) {
+               /* just return nothing if output will be truncated */
+               kfree(result);
+               return NULL;
+       }
+
+       copied = nfs4_make_rec_clidname(result + copied, name);
+       if (copied) {
+               kfree(result);
+               return NULL;
+       }
+
+       return result;
+}
+
+static int
+nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy)
+{
+       char *envp[2];
+       char *argv[4];
+       int ret;
+
+       if (unlikely(!cltrack_prog[0])) {
+               dprintk("%s: cltrack_prog is disabled\n", __func__);
+               return -EACCES;
+       }
+
+       dprintk("%s: cmd: %s\n", __func__, cmd);
+       dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
+       dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)");
+
+       envp[0] = legacy;
+       envp[1] = NULL;
+
+       argv[0] = (char *)cltrack_prog;
+       argv[1] = cmd;
+       argv[2] = arg;
+       argv[3] = NULL;
+
+       ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+       /*
+        * Disable the upcall mechanism if we're getting an ENOENT or EACCES
+        * error. The admin can re-enable it on the fly by using sysfs
+        * once the problem has been fixed.
+        */
+       if (ret == -ENOENT || ret == -EACCES) {
+               dprintk("NFSD: %s was not found or isn't executable (%d). "
+                       "Setting cltrack_prog to blank string!",
+                       cltrack_prog, ret);
+               cltrack_prog[0] = '\0';
+       }
+       dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
+
+       return ret;
+}
+
+static char *
+bin_to_hex_dup(const unsigned char *src, int srclen)
+{
+       int i;
+       char *buf, *hex;
+
+       /* +1 for terminating NULL */
+       buf = kmalloc((srclen * 2) + 1, GFP_KERNEL);
+       if (!buf)
+               return buf;
+
+       hex = buf;
+       for (i = 0; i < srclen; i++) {
+               sprintf(hex, "%2.2x", *src++);
+               hex += 2;
+       }
+       return buf;
+}
+
+static int
+nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net)
+{
+       return nfsd4_umh_cltrack_upcall("init", NULL, NULL);
+}
+
+static void
+nfsd4_umh_cltrack_create(struct nfs4_client *clp)
+{
+       char *hexid;
+
+       hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+       if (!hexid) {
+               dprintk("%s: can't allocate memory for upcall!\n", __func__);
+               return;
+       }
+       nfsd4_umh_cltrack_upcall("create", hexid, NULL);
+       kfree(hexid);
+}
+
+static void
+nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
+{
+       char *hexid;
+
+       hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+       if (!hexid) {
+               dprintk("%s: can't allocate memory for upcall!\n", __func__);
+               return;
+       }
+       nfsd4_umh_cltrack_upcall("remove", hexid, NULL);
+       kfree(hexid);
+}
+
+static int
+nfsd4_umh_cltrack_check(struct nfs4_client *clp)
+{
+       int ret;
+       char *hexid, *legacy;
+
+       hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+       if (!hexid) {
+               dprintk("%s: can't allocate memory for upcall!\n", __func__);
+               return -ENOMEM;
+       }
+       legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
+       ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy);
+       kfree(legacy);
+       kfree(hexid);
+       return ret;
+}
+
+static void
+nfsd4_umh_cltrack_grace_done(struct nfsd_net __attribute__((unused)) *nn,
+                               time_t boot_time)
+{
+       char *legacy;
+       char timestr[22]; /* FIXME: better way to determine max size? */
+
+       sprintf(timestr, "%ld", boot_time);
+       legacy = nfsd4_cltrack_legacy_topdir();
+       nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy);
+       kfree(legacy);
+}
+
+static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
+       .init           = nfsd4_umh_cltrack_init,
+       .exit           = NULL,
+       .create         = nfsd4_umh_cltrack_create,
+       .remove         = nfsd4_umh_cltrack_remove,
+       .check          = nfsd4_umh_cltrack_check,
+       .grace_done     = nfsd4_umh_cltrack_grace_done,
+};
+
 int
 nfsd4_client_tracking_init(struct net *net)
 {
        int status;
        struct path path;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-       if (!client_tracking_ops) {
-               client_tracking_ops = &nfsd4_cld_tracking_ops;
-               status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
-               if (!status) {
-                       if (S_ISDIR(path.dentry->d_inode->i_mode))
-                               client_tracking_ops =
-                                               &nfsd4_legacy_tracking_ops;
-                       path_put(&path);
-               }
+       /* just run the init if it the method is already decided */
+       if (nn->client_tracking_ops)
+               goto do_init;
+
+       /*
+        * First, try a UMH upcall. It should succeed or fail quickly, so
+        * there's little harm in trying that first.
+        */
+       nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
+       status = nn->client_tracking_ops->init(net);
+       if (!status)
+               return status;
+
+       /*
+        * See if the recoverydir exists and is a directory. If it is,
+        * then use the legacy ops.
+        */
+       nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
+       status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
+       if (!status) {
+               status = S_ISDIR(path.dentry->d_inode->i_mode);
+               path_put(&path);
+               if (status)
+                       goto do_init;
        }
 
-       status = client_tracking_ops->init(net);
+       /* Finally, try to use nfsdcld */
+       nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
+       printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be "
+                       "removed in 3.10. Please transition to using "
+                       "nfsdcltrack.\n");
+do_init:
+       status = nn->client_tracking_ops->init(net);
        if (status) {
                printk(KERN_WARNING "NFSD: Unable to initialize client "
                                    "recovery tracking! (%d)\n", status);
-               client_tracking_ops = NULL;
+               nn->client_tracking_ops = NULL;
        }
        return status;
 }
@@ -955,40 +1307,49 @@ nfsd4_client_tracking_init(struct net *net)
 void
 nfsd4_client_tracking_exit(struct net *net)
 {
-       if (client_tracking_ops) {
-               client_tracking_ops->exit(net);
-               client_tracking_ops = NULL;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       if (nn->client_tracking_ops) {
+               if (nn->client_tracking_ops->exit)
+                       nn->client_tracking_ops->exit(net);
+               nn->client_tracking_ops = NULL;
        }
 }
 
 void
 nfsd4_client_record_create(struct nfs4_client *clp)
 {
-       if (client_tracking_ops)
-               client_tracking_ops->create(clp);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (nn->client_tracking_ops)
+               nn->client_tracking_ops->create(clp);
 }
 
 void
 nfsd4_client_record_remove(struct nfs4_client *clp)
 {
-       if (client_tracking_ops)
-               client_tracking_ops->remove(clp);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (nn->client_tracking_ops)
+               nn->client_tracking_ops->remove(clp);
 }
 
 int
 nfsd4_client_record_check(struct nfs4_client *clp)
 {
-       if (client_tracking_ops)
-               return client_tracking_ops->check(clp);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (nn->client_tracking_ops)
+               return nn->client_tracking_ops->check(clp);
 
        return -EOPNOTSUPP;
 }
 
 void
-nfsd4_record_grace_done(struct net *net, time_t boot_time)
+nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
-       if (client_tracking_ops)
-               client_tracking_ops->grace_done(net, boot_time);
+       if (nn->client_tracking_ops)
+               nn->client_tracking_ops->grace_done(nn, boot_time);
 }
 
 static int
index d0237f872cc4e1fe49060120d725f729783dc245..ac8ed96c41994467512a632db89c8bed9bff6b27 100644 (file)
 #include "xdr4.h"
 #include "vfs.h"
 #include "current_stateid.h"
-#include "fault_inject.h"
 
 #include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
-/* Globals */
-time_t nfsd4_lease = 90;     /* default lease time */
-time_t nfsd4_grace = 90;
-
 #define all_ones {{~0,~0},~0}
 static const stateid_t one_stateid = {
        .si_generation = ~0,
@@ -176,8 +171,6 @@ static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
        return ret & OWNER_HASH_MASK;
 }
 
-static struct list_head        ownerstr_hashtbl[OWNER_HASH_SIZE];
-
 /* hash table for nfs4_file */
 #define FILE_HASH_BITS                   8
 #define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
@@ -192,7 +185,7 @@ static struct list_head file_hashtbl[FILE_HASH_SIZE];
 
 static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
 {
-       BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
+       WARN_ON_ONCE(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
        atomic_inc(&fp->fi_access[oflag]);
 }
 
@@ -251,7 +244,7 @@ static inline int get_new_stid(struct nfs4_stid *stid)
         * preallocations that can exist at a time, but the state lock
         * prevents anyone from using ours before we get here:
         */
-       BUG_ON(error);
+       WARN_ON_ONCE(error);
        /*
         * It shouldn't be a problem to reuse an opaque stateid value.
         * I don't think it is for 4.1.  But with 4.0 I worry that, for
@@ -340,7 +333,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
        fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
        dp->dl_time = 0;
        atomic_set(&dp->dl_count, 1);
-       INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
+       nfsd4_init_callback(&dp->dl_recall);
        return dp;
 }
 
@@ -390,14 +383,6 @@ unhash_delegation(struct nfs4_delegation *dp)
  * SETCLIENTID state 
  */
 
-/* client_lock protects the client lru list and session hash table */
-static DEFINE_SPINLOCK(client_lock);
-
-/* Hash tables for nfs4_clientid state */
-#define CLIENT_HASH_BITS                 4
-#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
-#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
-
 static unsigned int clientid_hashval(u32 id)
 {
        return id & CLIENT_HASH_MASK;
@@ -408,31 +393,6 @@ static unsigned int clientstr_hashval(const char *name)
        return opaque_hashval(name, 8) & CLIENT_HASH_MASK;
 }
 
-/*
- * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
- * used in reboot/reset lease grace period processing
- *
- * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
- * setclientid_confirmed info. 
- *
- * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
- * setclientid info.
- *
- * client_lru holds client queue ordered by nfs4_client.cl_time
- * for lease renewal.
- *
- * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
- * for last close replay.
- */
-static struct list_head        reclaim_str_hashtbl[CLIENT_HASH_SIZE];
-static int reclaim_str_hashtbl_size = 0;
-static struct list_head        conf_id_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head        conf_str_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head        unconf_str_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head        unconf_id_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head client_lru;
-static struct list_head close_lru;
-
 /*
  * We store the NONE, READ, WRITE, and BOTH bits separately in the
  * st_{access,deny}_bmap field of the stateid, in order to track not
@@ -526,7 +486,8 @@ static int nfs4_access_to_omode(u32 access)
        case NFS4_SHARE_ACCESS_BOTH:
                return O_RDWR;
        }
-       BUG();
+       WARN_ON_ONCE(1);
+       return O_RDONLY;
 }
 
 /* release all access and file references for a given stateid */
@@ -652,9 +613,6 @@ static void release_openowner(struct nfs4_openowner *oo)
        nfs4_free_openowner(oo);
 }
 
-#define SESSION_HASH_SIZE      512
-static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
-
 static inline int
 hash_sessionid(struct nfs4_sessionid *sessionid)
 {
@@ -785,9 +743,12 @@ out_free:
        return NULL;
 }
 
-static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize)
+static void init_forechannel_attrs(struct nfsd4_channel_attrs *new,
+                                  struct nfsd4_channel_attrs *req,
+                                  int numslots, int slotsize,
+                                  struct nfsd_net *nn)
 {
-       u32 maxrpc = nfsd_serv->sv_max_mesg;
+       u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
 
        new->maxreqs = numslots;
        new->maxresp_cached = min_t(u32, req->maxresp_cached,
@@ -906,21 +867,27 @@ static void __free_session(struct nfsd4_session *ses)
 static void free_session(struct kref *kref)
 {
        struct nfsd4_session *ses;
+       struct nfsd_net *nn;
 
-       lockdep_assert_held(&client_lock);
        ses = container_of(kref, struct nfsd4_session, se_ref);
+       nn = net_generic(ses->se_client->net, nfsd_net_id);
+
+       lockdep_assert_held(&nn->client_lock);
        nfsd4_del_conns(ses);
        __free_session(ses);
 }
 
 void nfsd4_put_session(struct nfsd4_session *ses)
 {
-       spin_lock(&client_lock);
+       struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
+
+       spin_lock(&nn->client_lock);
        nfsd4_put_session_locked(ses);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 }
 
-static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
+static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
+                                          struct nfsd_net *nn)
 {
        struct nfsd4_session *new;
        int numslots, slotsize;
@@ -941,13 +908,14 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
                nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
                return NULL;
        }
-       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
+       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
        return new;
 }
 
-static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
 {
        int idx;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        new->se_client = clp;
        gen_sessionid(new);
@@ -957,14 +925,15 @@ static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_s
        new->se_cb_seq_nr = 1;
        new->se_flags = cses->flags;
        new->se_cb_prog = cses->callback_prog;
+       new->se_cb_sec = cses->cb_sec;
        kref_init(&new->se_ref);
        idx = hash_sessionid(&new->se_sessionid);
-       spin_lock(&client_lock);
-       list_add(&new->se_hash, &sessionid_hashtbl[idx]);
+       spin_lock(&nn->client_lock);
+       list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
        spin_lock(&clp->cl_lock);
        list_add(&new->se_perclnt, &clp->cl_sessions);
        spin_unlock(&clp->cl_lock);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 
        if (cses->flags & SESSION4_BACK_CHAN) {
                struct sockaddr *sa = svc_addr(rqstp);
@@ -978,20 +947,20 @@ static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_s
                rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
                clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
        }
-       return new;
 }
 
 /* caller must hold client_lock */
 static struct nfsd4_session *
-find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
+find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
 {
        struct nfsd4_session *elem;
        int idx;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        dump_sessionid(__func__, sessionid);
        idx = hash_sessionid(sessionid);
        /* Search in the appropriate list */
-       list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
+       list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
                if (!memcmp(elem->se_sessionid.data, sessionid->data,
                            NFS4_MAX_SESSIONID_LEN)) {
                        return elem;
@@ -1016,6 +985,8 @@ unhash_session(struct nfsd4_session *ses)
 static inline void
 renew_client_locked(struct nfs4_client *clp)
 {
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
        if (is_client_expired(clp)) {
                WARN_ON(1);
                printk("%s: client (clientid %08x/%08x) already expired\n",
@@ -1028,16 +999,18 @@ renew_client_locked(struct nfs4_client *clp)
        dprintk("renewing client (clientid %08x/%08x)\n", 
                        clp->cl_clientid.cl_boot, 
                        clp->cl_clientid.cl_id);
-       list_move_tail(&clp->cl_lru, &client_lru);
+       list_move_tail(&clp->cl_lru, &nn->client_lru);
        clp->cl_time = get_seconds();
 }
 
 static inline void
 renew_client(struct nfs4_client *clp)
 {
-       spin_lock(&client_lock);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       spin_lock(&nn->client_lock);
        renew_client_locked(clp);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 }
 
 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
@@ -1075,7 +1048,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 static inline void
 free_client(struct nfs4_client *clp)
 {
-       lockdep_assert_held(&client_lock);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       lockdep_assert_held(&nn->client_lock);
        while (!list_empty(&clp->cl_sessions)) {
                struct nfsd4_session *ses;
                ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
@@ -1092,15 +1067,16 @@ void
 release_session_client(struct nfsd4_session *session)
 {
        struct nfs4_client *clp = session->se_client;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-       if (!atomic_dec_and_lock(&clp->cl_refcount, &client_lock))
+       if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
                return;
        if (is_client_expired(clp)) {
                free_client(clp);
                session->se_client = NULL;
        } else
                renew_client_locked(clp);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 }
 
 /* must be called under the client_lock */
@@ -1123,6 +1099,7 @@ destroy_client(struct nfs4_client *clp)
        struct nfs4_openowner *oo;
        struct nfs4_delegation *dp;
        struct list_head reaplist;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&recall_lock);
@@ -1144,12 +1121,15 @@ destroy_client(struct nfs4_client *clp)
        if (clp->cl_cb_conn.cb_xprt)
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
        list_del(&clp->cl_idhash);
-       list_del(&clp->cl_strhash);
-       spin_lock(&client_lock);
+       if (test_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags))
+               rb_erase(&clp->cl_namenode, &nn->conf_name_tree);
+       else
+               rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
+       spin_lock(&nn->client_lock);
        unhash_client_locked(clp);
        if (atomic_read(&clp->cl_refcount) == 0)
                free_client(clp);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 }
 
 static void expire_client(struct nfs4_client *clp)
@@ -1187,6 +1167,17 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
        return 0;
 }
 
+static long long
+compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
+{
+       long long res;
+
+       res = o1->len - o2->len;
+       if (res)
+               return res;
+       return (long long)memcmp(o1->data, o2->data, o1->len);
+}
+
 static int same_name(const char *n1, const char *n2)
 {
        return 0 == memcmp(n1, n2, HEXDIR_LEN);
@@ -1247,10 +1238,9 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
        return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
 }
 
-static void gen_clid(struct nfs4_client *clp)
+static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
 {
        static u32 current_clientid = 1;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
        clp->cl_clientid.cl_boot = nn->boot_time;
        clp->cl_clientid.cl_id = current_clientid++; 
@@ -1283,12 +1273,14 @@ static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t
        return NULL;
 }
 
-static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+static struct nfs4_client *create_client(struct xdr_netobj name,
                struct svc_rqst *rqstp, nfs4_verifier *verf)
 {
        struct nfs4_client *clp;
        struct sockaddr *sa = svc_addr(rqstp);
        int ret;
+       struct net *net = SVC_NET(rqstp);
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        clp = alloc_client(name);
        if (clp == NULL)
@@ -1297,23 +1289,21 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        INIT_LIST_HEAD(&clp->cl_sessions);
        ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred);
        if (ret) {
-               spin_lock(&client_lock);
+               spin_lock(&nn->client_lock);
                free_client(clp);
-               spin_unlock(&client_lock);
+               spin_unlock(&nn->client_lock);
                return NULL;
        }
        idr_init(&clp->cl_stateids);
-       memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
        atomic_set(&clp->cl_refcount, 0);
        clp->cl_cb_state = NFSD4_CB_UNKNOWN;
        INIT_LIST_HEAD(&clp->cl_idhash);
-       INIT_LIST_HEAD(&clp->cl_strhash);
        INIT_LIST_HEAD(&clp->cl_openowners);
        INIT_LIST_HEAD(&clp->cl_delegations);
        INIT_LIST_HEAD(&clp->cl_lru);
        INIT_LIST_HEAD(&clp->cl_callbacks);
        spin_lock_init(&clp->cl_lock);
-       INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
+       nfsd4_init_callback(&clp->cl_cb_null);
        clp->cl_time = get_seconds();
        clear_bit(0, &clp->cl_cb_slot_busy);
        rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
@@ -1321,17 +1311,60 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
        gen_confirm(clp);
        clp->cl_cb_session = NULL;
+       clp->net = net;
        return clp;
 }
 
 static void
-add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
+add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root)
+{
+       struct rb_node **new = &(root->rb_node), *parent = NULL;
+       struct nfs4_client *clp;
+
+       while (*new) {
+               clp = rb_entry(*new, struct nfs4_client, cl_namenode);
+               parent = *new;
+
+               if (compare_blob(&clp->cl_name, &new_clp->cl_name) > 0)
+                       new = &((*new)->rb_left);
+               else
+                       new = &((*new)->rb_right);
+       }
+
+       rb_link_node(&new_clp->cl_namenode, parent, new);
+       rb_insert_color(&new_clp->cl_namenode, root);
+}
+
+static struct nfs4_client *
+find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root)
+{
+       long long cmp;
+       struct rb_node *node = root->rb_node;
+       struct nfs4_client *clp;
+
+       while (node) {
+               clp = rb_entry(node, struct nfs4_client, cl_namenode);
+               cmp = compare_blob(&clp->cl_name, name);
+               if (cmp > 0)
+                       node = node->rb_left;
+               else if (cmp < 0)
+                       node = node->rb_right;
+               else
+                       return clp;
+       }
+       return NULL;
+}
+
+static void
+add_to_unconfirmed(struct nfs4_client *clp)
 {
        unsigned int idhashval;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-       list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
+       clear_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
+       add_clp_to_name_tree(clp, &nn->unconf_name_tree);
        idhashval = clientid_hashval(clp->cl_clientid.cl_id);
-       list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
+       list_add(&clp->cl_idhash, &nn->unconf_id_hashtbl[idhashval]);
        renew_client(clp);
 }
 
@@ -1339,22 +1372,23 @@ static void
 move_to_confirmed(struct nfs4_client *clp)
 {
        unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
-       unsigned int strhashval;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
        dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
-       list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
-       strhashval = clientstr_hashval(clp->cl_recdir);
-       list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
+       list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
+       rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
+       add_clp_to_name_tree(clp, &nn->conf_name_tree);
+       set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
        renew_client(clp);
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid, bool sessions)
+find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
        struct nfs4_client *clp;
        unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-       list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
+       list_for_each_entry(clp, &nn->conf_id_hashtbl[idhashval], cl_idhash) {
                if (same_clid(&clp->cl_clientid, clid)) {
                        if ((bool)clp->cl_minorversion != sessions)
                                return NULL;
@@ -1366,12 +1400,12 @@ find_confirmed_client(clientid_t *clid, bool sessions)
 }
 
 static struct nfs4_client *
-find_unconfirmed_client(clientid_t *clid, bool sessions)
+find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
        struct nfs4_client *clp;
        unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-       list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+       list_for_each_entry(clp, &nn->unconf_id_hashtbl[idhashval], cl_idhash) {
                if (same_clid(&clp->cl_clientid, clid)) {
                        if ((bool)clp->cl_minorversion != sessions)
                                return NULL;
@@ -1387,27 +1421,15 @@ static bool clp_used_exchangeid(struct nfs4_client *clp)
 } 
 
 static struct nfs4_client *
-find_confirmed_client_by_str(const char *dname, unsigned int hashval)
+find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
 {
-       struct nfs4_client *clp;
-
-       list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
-               if (same_name(clp->cl_recdir, dname))
-                       return clp;
-       }
-       return NULL;
+       return find_clp_in_name_tree(name, &nn->conf_name_tree);
 }
 
 static struct nfs4_client *
-find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
+find_unconfirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
 {
-       struct nfs4_client *clp;
-
-       list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
-               if (same_name(clp->cl_recdir, dname))
-                       return clp;
-       }
-       return NULL;
+       return find_clp_in_name_tree(name, &nn->unconf_name_tree);
 }
 
 static void
@@ -1428,7 +1450,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_r
        else
                goto out_err;
 
-       conn->cb_addrlen = rpc_uaddr2sockaddr(&init_net, se->se_callback_addr_val,
+       conn->cb_addrlen = rpc_uaddr2sockaddr(clp->net, se->se_callback_addr_val,
                                            se->se_callback_addr_len,
                                            (struct sockaddr *)&conn->cb_addr,
                                            sizeof(conn->cb_addr));
@@ -1572,12 +1594,11 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 {
        struct nfs4_client *unconf, *conf, *new;
        __be32 status;
-       unsigned int            strhashval;
-       char                    dname[HEXDIR_LEN];
        char                    addr_str[INET6_ADDRSTRLEN];
        nfs4_verifier           verf = exid->verifier;
        struct sockaddr         *sa = svc_addr(rqstp);
        bool    update = exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A;
+       struct nfsd_net         *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        rpc_ntop(sa, addr_str, sizeof(addr_str));
        dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
@@ -1592,24 +1613,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
        switch (exid->spa_how) {
        case SP4_NONE:
                break;
+       default:                                /* checked by xdr code */
+               WARN_ON_ONCE(1);
        case SP4_SSV:
-               return nfserr_serverfault;
-       default:
-               BUG();                          /* checked by xdr code */
        case SP4_MACH_CRED:
                return nfserr_serverfault;      /* no excuse :-/ */
        }
 
-       status = nfs4_make_rec_clidname(dname, &exid->clname);
-
-       if (status)
-               return status;
-
-       strhashval = clientstr_hashval(dname);
-
        /* Cases below refer to rfc 5661 section 18.35.4: */
        nfs4_lock_state();
-       conf = find_confirmed_client_by_str(dname, strhashval);
+       conf = find_confirmed_client_by_name(&exid->clname, nn);
        if (conf) {
                bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
                bool verfs_match = same_verf(&verf, &conf->cl_verifier);
@@ -1654,21 +1667,21 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
                goto out;
        }
 
-       unconf  = find_unconfirmed_client_by_str(dname, strhashval);
+       unconf  = find_unconfirmed_client_by_name(&exid->clname, nn);
        if (unconf) /* case 4, possible retry or client restart */
                expire_client(unconf);
 
        /* case 1 (normal case) */
 out_new:
-       new = create_client(exid->clname, dname, rqstp, &verf);
+       new = create_client(exid->clname, rqstp, &verf);
        if (new == NULL) {
                status = nfserr_jukebox;
                goto out;
        }
        new->cl_minorversion = 1;
 
-       gen_clid(new);
-       add_to_unconfirmed(new, strhashval);
+       gen_clid(new, nn);
+       add_to_unconfirmed(new);
 out_copy:
        exid->clientid.cl_boot = new->cl_clientid.cl_boot;
        exid->clientid.cl_id = new->cl_clientid.cl_id;
@@ -1761,12 +1774,13 @@ nfsd4_create_session(struct svc_rqst *rqstp,
        struct nfsd4_conn *conn;
        struct nfsd4_clid_slot *cs_slot = NULL;
        __be32 status = 0;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
                return nfserr_inval;
        if (check_forechannel_attrs(cr_ses->fore_channel))
                return nfserr_toosmall;
-       new = alloc_session(&cr_ses->fore_channel);
+       new = alloc_session(&cr_ses->fore_channel, nn);
        if (!new)
                return nfserr_jukebox;
        status = nfserr_jukebox;
@@ -1775,8 +1789,8 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                goto out_free_session;
 
        nfs4_lock_state();
-       unconf = find_unconfirmed_client(&cr_ses->clientid, true);
-       conf = find_confirmed_client(&cr_ses->clientid, true);
+       unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
+       conf = find_confirmed_client(&cr_ses->clientid, true, nn);
 
        if (conf) {
                cs_slot = &conf->cl_cs_slot;
@@ -1789,7 +1803,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                        goto out_free_conn;
                }
        } else if (unconf) {
-               unsigned int hash;
                struct nfs4_client *old;
                if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
                    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
@@ -1803,8 +1816,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                        status = nfserr_seq_misordered;
                        goto out_free_conn;
                }
-               hash = clientstr_hashval(unconf->cl_recdir);
-               old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+               old = find_confirmed_client_by_name(&unconf->cl_name, nn);
                if (old)
                        expire_client(old);
                move_to_confirmed(unconf);
@@ -1843,14 +1855,6 @@ out_free_session:
        goto out;
 }
 
-static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
-{
-       struct nfsd4_compoundres *resp = rqstp->rq_resp;
-       struct nfsd4_compoundargs *argp = rqstp->rq_argp;
-
-       return argp->opcnt == resp->opcnt;
-}
-
 static __be32 nfsd4_map_bcts_dir(u32 *dir)
 {
        switch (*dir) {
@@ -1865,24 +1869,40 @@ static __be32 nfsd4_map_bcts_dir(u32 *dir)
        return nfserr_inval;
 }
 
+__be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_backchannel_ctl *bc)
+{
+       struct nfsd4_session *session = cstate->session;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
+       spin_lock(&nn->client_lock);
+       session->se_cb_prog = bc->bc_cb_program;
+       session->se_cb_sec = bc->bc_cb_sec;
+       spin_unlock(&nn->client_lock);
+
+       nfsd4_probe_callback(session->se_client);
+
+       return nfs_ok;
+}
+
 __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
                     struct nfsd4_compound_state *cstate,
                     struct nfsd4_bind_conn_to_session *bcts)
 {
        __be32 status;
        struct nfsd4_conn *conn;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (!nfsd4_last_compound_op(rqstp))
                return nfserr_not_only_op;
-       spin_lock(&client_lock);
-       cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid);
+       spin_lock(&nn->client_lock);
+       cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
        /* Sorta weird: we only need the refcnt'ing because new_conn acquires
         * client_lock iself: */
        if (cstate->session) {
                nfsd4_get_session(cstate->session);
                atomic_inc(&cstate->session->se_client->cl_refcount);
        }
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
        if (!cstate->session)
                return nfserr_badsession;
 
@@ -1910,6 +1930,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
 {
        struct nfsd4_session *ses;
        __be32 status = nfserr_badsession;
+       struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
 
        /* Notes:
         * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid
@@ -1923,24 +1944,24 @@ nfsd4_destroy_session(struct svc_rqst *r,
                        return nfserr_not_only_op;
        }
        dump_sessionid(__func__, &sessionid->sessionid);
-       spin_lock(&client_lock);
-       ses = find_in_sessionid_hashtbl(&sessionid->sessionid);
+       spin_lock(&nn->client_lock);
+       ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
        if (!ses) {
-               spin_unlock(&client_lock);
+               spin_unlock(&nn->client_lock);
                goto out;
        }
 
        unhash_session(ses);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
 
        nfs4_lock_state();
        nfsd4_probe_callback_sync(ses->se_client);
        nfs4_unlock_state();
 
-       spin_lock(&client_lock);
+       spin_lock(&nn->client_lock);
        nfsd4_del_conns(ses);
        nfsd4_put_session_locked(ses);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
        status = nfs_ok;
 out:
        dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -2006,6 +2027,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        struct nfsd4_slot *slot;
        struct nfsd4_conn *conn;
        __be32 status;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (resp->opcnt != 1)
                return nfserr_sequence_pos;
@@ -2018,9 +2040,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        if (!conn)
                return nfserr_jukebox;
 
-       spin_lock(&client_lock);
+       spin_lock(&nn->client_lock);
        status = nfserr_badsession;
-       session = find_in_sessionid_hashtbl(&seq->sessionid);
+       session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
        if (!session)
                goto out;
 
@@ -2094,7 +2116,7 @@ out:
                }
        }
        kfree(conn);
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
        dprintk("%s: return %d\n", __func__, ntohl(status));
        return status;
 }
@@ -2104,10 +2126,11 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 {
        struct nfs4_client *conf, *unconf, *clp;
        __be32 status = 0;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        nfs4_lock_state();
-       unconf = find_unconfirmed_client(&dc->clientid, true);
-       conf = find_confirmed_client(&dc->clientid, true);
+       unconf = find_unconfirmed_client(&dc->clientid, true, nn);
+       conf = find_confirmed_client(&dc->clientid, true, nn);
 
        if (conf) {
                clp = conf;
@@ -2181,20 +2204,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        struct xdr_netobj       clname = setclid->se_name;
        nfs4_verifier           clverifier = setclid->se_verf;
-       unsigned int            strhashval;
        struct nfs4_client      *conf, *unconf, *new;
        __be32                  status;
-       char                    dname[HEXDIR_LEN];
-       
-       status = nfs4_make_rec_clidname(dname, &clname);
-       if (status)
-               return status;
-
-       strhashval = clientstr_hashval(dname);
+       struct nfsd_net         *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        /* Cases below refer to rfc 3530 section 14.2.33: */
        nfs4_lock_state();
-       conf = find_confirmed_client_by_str(dname, strhashval);
+       conf = find_confirmed_client_by_name(&clname, nn);
        if (conf) {
                /* case 0: */
                status = nfserr_clid_inuse;
@@ -2209,21 +2225,21 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        goto out;
                }
        }
-       unconf = find_unconfirmed_client_by_str(dname, strhashval);
+       unconf = find_unconfirmed_client_by_name(&clname, nn);
        if (unconf)
                expire_client(unconf);
        status = nfserr_jukebox;
-       new = create_client(clname, dname, rqstp, &clverifier);
+       new = create_client(clname, rqstp, &clverifier);
        if (new == NULL)
                goto out;
        if (conf && same_verf(&conf->cl_verifier, &clverifier))
                /* case 1: probable callback update */
                copy_clid(new, conf);
        else /* case 4 (new client) or cases 2, 3 (client reboot): */
-               gen_clid(new);
+               gen_clid(new, nn);
        new->cl_minorversion = 0;
        gen_callback(new, setclid, rqstp);
-       add_to_unconfirmed(new, strhashval);
+       add_to_unconfirmed(new);
        setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
        setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
        memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
@@ -2243,14 +2259,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
        nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
        clientid_t * clid = &setclientid_confirm->sc_clientid;
        __be32 status;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (STALE_CLIENTID(clid, nn))
                return nfserr_stale_clientid;
        nfs4_lock_state();
 
-       conf = find_confirmed_client(clid, false);
-       unconf = find_unconfirmed_client(clid, false);
+       conf = find_confirmed_client(clid, false, nn);
+       unconf = find_unconfirmed_client(clid, false, nn);
        /*
         * We try hard to give out unique clientid's, so if we get an
         * attempt to confirm the same clientid with a different cred,
@@ -2276,9 +2292,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                nfsd4_probe_callback(conf);
                expire_client(unconf);
        } else { /* case 3: normal case; new or rebooted client */
-               unsigned int hash = clientstr_hashval(unconf->cl_recdir);
-
-               conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+               conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
                if (conf)
                        expire_client(conf);
                move_to_confirmed(unconf);
@@ -2340,7 +2354,7 @@ nfsd4_init_slabs(void)
        if (openowner_slab == NULL)
                goto out_nomem;
        lockowner_slab = kmem_cache_create("nfsd4_lockowners",
-                       sizeof(struct nfs4_openowner), 0, 0, NULL);
+                       sizeof(struct nfs4_lockowner), 0, 0, NULL);
        if (lockowner_slab == NULL)
                goto out_nomem;
        file_slab = kmem_cache_create("nfsd4_files",
@@ -2404,7 +2418,9 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
 
 static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
 {
-       list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
        list_add(&oo->oo_perclient, &clp->cl_openowners);
 }
 
@@ -2444,11 +2460,13 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
 }
 
 static void
-move_to_close_lru(struct nfs4_openowner *oo)
+move_to_close_lru(struct nfs4_openowner *oo, struct net *net)
 {
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
        dprintk("NFSD: move_to_close_lru nfs4_openowner %p\n", oo);
 
-       list_move_tail(&oo->oo_close_lru, &close_lru);
+       list_move_tail(&oo->oo_close_lru, &nn->close_lru);
        oo->oo_time = get_seconds();
 }
 
@@ -2462,13 +2480,14 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
 }
 
 static struct nfs4_openowner *
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open,
+                       bool sessions, struct nfsd_net *nn)
 {
        struct nfs4_stateowner *so;
        struct nfs4_openowner *oo;
        struct nfs4_client *clp;
 
-       list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+       list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) {
                if (!so->so_is_open_owner)
                        continue;
                if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
@@ -2555,9 +2574,14 @@ static void nfsd_break_deleg_cb(struct file_lock *fl)
        struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;
        struct nfs4_delegation *dp;
 
-       BUG_ON(!fp);
-       /* We assume break_lease is only called once per lease: */
-       BUG_ON(fp->fi_had_conflict);
+       if (!fp) {
+               WARN(1, "(%p)->fl_owner NULL\n", fl);
+               return;
+       }
+       if (fp->fi_had_conflict) {
+               WARN(1, "duplicate break on %p\n", fp);
+               return;
+       }
        /*
         * We don't want the locks code to timeout the lease for us;
         * we'll remove it ourself if a delegation isn't returned
@@ -2599,14 +2623,13 @@ static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4
 
 __be32
 nfsd4_process_open1(struct nfsd4_compound_state *cstate,
-                   struct nfsd4_open *open)
+                   struct nfsd4_open *open, struct nfsd_net *nn)
 {
        clientid_t *clientid = &open->op_clientid;
        struct nfs4_client *clp = NULL;
        unsigned int strhashval;
        struct nfs4_openowner *oo = NULL;
        __be32 status;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
        if (STALE_CLIENTID(&open->op_clientid, nn))
                return nfserr_stale_clientid;
@@ -2619,10 +2642,11 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
                return nfserr_jukebox;
 
        strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
-       oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
+       oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn);
        open->op_openowner = oo;
        if (!oo) {
-               clp = find_confirmed_client(clientid, cstate->minorversion);
+               clp = find_confirmed_client(clientid, cstate->minorversion,
+                                           nn);
                if (clp == NULL)
                        return nfserr_expired;
                goto new_owner;
@@ -2891,7 +2915,7 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
                        open->op_why_no_deleg = WND4_CANCELLED;
                        break;
                case NFS4_SHARE_WANT_NO_DELEG:
-                       BUG();  /* not supposed to get here */
+                       WARN_ON_ONCE(1);
                }
        }
 }
@@ -2959,6 +2983,7 @@ out:
        }
        return;
 out_free:
+       unhash_stid(&dp->dl_stid);
        nfs4_put_delegation(dp);
 out_no_deleg:
        flag = NFS4_OPEN_DELEGATE_NONE;
@@ -3104,27 +3129,32 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
                free_generic_stateid(open->op_stp);
 }
 
+static __be32 lookup_clientid(clientid_t *clid, bool session, struct nfsd_net *nn, struct nfs4_client **clp)
+{
+       struct nfs4_client *found;
+
+       if (STALE_CLIENTID(clid, nn))
+               return nfserr_stale_clientid;
+       found = find_confirmed_client(clid, session, nn);
+       if (clp)
+               *clp = found;
+       return found ? nfs_ok : nfserr_expired;
+}
+
 __be32
 nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            clientid_t *clid)
 {
        struct nfs4_client *clp;
        __be32 status;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        nfs4_lock_state();
        dprintk("process_renew(%08x/%08x): starting\n", 
                        clid->cl_boot, clid->cl_id);
-       status = nfserr_stale_clientid;
-       if (STALE_CLIENTID(clid, nn))
-               goto out;
-       clp = find_confirmed_client(clid, cstate->minorversion);
-       status = nfserr_expired;
-       if (clp == NULL) {
-               /* We assume the client took too long to RENEW. */
-               dprintk("nfsd4_renew: clientid not found!\n");
+       status = lookup_clientid(clid, cstate->minorversion, nn, &clp);
+       if (status)
                goto out;
-       }
        status = nfserr_cb_path_down;
        if (!list_empty(&clp->cl_delegations)
                        && clp->cl_cb_state != NFSD4_CB_UP)
@@ -3136,44 +3166,42 @@ out:
 }
 
 static void
-nfsd4_end_grace(struct net *net)
+nfsd4_end_grace(struct nfsd_net *nn)
 {
-       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-
        /* do nothing if grace period already ended */
        if (nn->grace_ended)
                return;
 
        dprintk("NFSD: end of grace period\n");
        nn->grace_ended = true;
-       nfsd4_record_grace_done(net, nn->boot_time);
+       nfsd4_record_grace_done(nn, nn->boot_time);
        locks_end_grace(&nn->nfsd4_manager);
        /*
         * Now that every NFSv4 client has had the chance to recover and
         * to see the (possibly new, possibly shorter) lease time, we
         * can safely set the next grace time to the current lease time:
         */
-       nfsd4_grace = nfsd4_lease;
+       nn->nfsd4_grace = nn->nfsd4_lease;
 }
 
 static time_t
-nfs4_laundromat(void)
+nfs4_laundromat(struct nfsd_net *nn)
 {
        struct nfs4_client *clp;
        struct nfs4_openowner *oo;
        struct nfs4_delegation *dp;
        struct list_head *pos, *next, reaplist;
-       time_t cutoff = get_seconds() - nfsd4_lease;
-       time_t t, clientid_val = nfsd4_lease;
-       time_t u, test_val = nfsd4_lease;
+       time_t cutoff = get_seconds() - nn->nfsd4_lease;
+       time_t t, clientid_val = nn->nfsd4_lease;
+       time_t u, test_val = nn->nfsd4_lease;
 
        nfs4_lock_state();
 
        dprintk("NFSD: laundromat service - starting\n");
-       nfsd4_end_grace(&init_net);
+       nfsd4_end_grace(nn);
        INIT_LIST_HEAD(&reaplist);
-       spin_lock(&client_lock);
-       list_for_each_safe(pos, next, &client_lru) {
+       spin_lock(&nn->client_lock);
+       list_for_each_safe(pos, next, &nn->client_lru) {
                clp = list_entry(pos, struct nfs4_client, cl_lru);
                if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
                        t = clp->cl_time - cutoff;
@@ -3189,7 +3217,7 @@ nfs4_laundromat(void)
                unhash_client_locked(clp);
                list_add(&clp->cl_lru, &reaplist);
        }
-       spin_unlock(&client_lock);
+       spin_unlock(&nn->client_lock);
        list_for_each_safe(pos, next, &reaplist) {
                clp = list_entry(pos, struct nfs4_client, cl_lru);
                dprintk("NFSD: purging unused client (clientid %08x)\n",
@@ -3199,6 +3227,8 @@ nfs4_laundromat(void)
        spin_lock(&recall_lock);
        list_for_each_safe(pos, next, &del_recall_lru) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+               if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn)
+                       continue;
                if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
                        u = dp->dl_time - cutoff;
                        if (test_val > u)
@@ -3212,8 +3242,8 @@ nfs4_laundromat(void)
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
                unhash_delegation(dp);
        }
-       test_val = nfsd4_lease;
-       list_for_each_safe(pos, next, &close_lru) {
+       test_val = nn->nfsd4_lease;
+       list_for_each_safe(pos, next, &nn->close_lru) {
                oo = container_of(pos, struct nfs4_openowner, oo_close_lru);
                if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) {
                        u = oo->oo_time - cutoff;
@@ -3231,16 +3261,19 @@ nfs4_laundromat(void)
 
 static struct workqueue_struct *laundry_wq;
 static void laundromat_main(struct work_struct *);
-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
 
 static void
-laundromat_main(struct work_struct *not_used)
+laundromat_main(struct work_struct *laundry)
 {
        time_t t;
+       struct delayed_work *dwork = container_of(laundry, struct delayed_work,
+                                                 work);
+       struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+                                          laundromat_work);
 
-       t = nfs4_laundromat();
+       t = nfs4_laundromat(nn);
        dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
-       queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
+       queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
 }
 
 static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
@@ -3385,16 +3418,17 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
        return nfs_ok;
 }
 
-static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
+static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
+                                  struct nfs4_stid **s, bool sessions,
+                                  struct nfsd_net *nn)
 {
        struct nfs4_client *cl;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
                return nfserr_bad_stateid;
        if (STALE_STATEID(stateid, nn))
                return nfserr_stale_stateid;
-       cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
+       cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions, nn);
        if (!cl)
                return nfserr_expired;
        *s = find_stateid_by_type(cl, stateid, typemask);
@@ -3416,6 +3450,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
        struct nfs4_delegation *dp = NULL;
        struct svc_fh *current_fh = &cstate->current_fh;
        struct inode *ino = current_fh->fh_dentry->d_inode;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        __be32 status;
 
        if (filpp)
@@ -3427,7 +3462,8 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
                return check_special_stateids(net, current_fh, stateid, flags);
 
-       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
+       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
+                                     &s, cstate->minorversion, nn);
        if (status)
                return status;
        status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3441,7 +3477,11 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
                        goto out;
                if (filpp) {
                        *filpp = dp->dl_file->fi_deleg_file;
-                       BUG_ON(!*filpp);
+                       if (!*filpp) {
+                               WARN_ON_ONCE(1);
+                               status = nfserr_serverfault;
+                               goto out;
+                       }
                }
                break;
        case NFS4_OPEN_STID:
@@ -3568,7 +3608,8 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
 static __be32
 nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                         stateid_t *stateid, char typemask,
-                        struct nfs4_ol_stateid **stpp)
+                        struct nfs4_ol_stateid **stpp,
+                        struct nfsd_net *nn)
 {
        __be32 status;
        struct nfs4_stid *s;
@@ -3577,7 +3618,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                seqid, STATEID_VAL(stateid));
 
        *stpp = NULL;
-       status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
+       status = nfsd4_lookup_stateid(stateid, typemask, &s,
+                                     cstate->minorversion, nn);
        if (status)
                return status;
        *stpp = openlockstateid(s);
@@ -3586,13 +3628,14 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
        return nfs4_seqid_op_checks(cstate, stateid, seqid, *stpp);
 }
 
-static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, stateid_t *stateid, struct nfs4_ol_stateid **stpp)
+static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
+                                                stateid_t *stateid, struct nfs4_ol_stateid **stpp, struct nfsd_net *nn)
 {
        __be32 status;
        struct nfs4_openowner *oo;
 
        status = nfs4_preprocess_seqid_op(cstate, seqid, stateid,
-                                               NFS4_OPEN_STID, stpp);
+                                               NFS4_OPEN_STID, stpp, nn);
        if (status)
                return status;
        oo = openowner((*stpp)->st_stateowner);
@@ -3608,6 +3651,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        __be32 status;
        struct nfs4_openowner *oo;
        struct nfs4_ol_stateid *stp;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
                        (int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3621,7 +3665,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        status = nfs4_preprocess_seqid_op(cstate,
                                        oc->oc_seqid, &oc->oc_req_stateid,
-                                       NFS4_OPEN_STID, &stp);
+                                       NFS4_OPEN_STID, &stp, nn);
        if (status)
                goto out;
        oo = openowner(stp->st_stateowner);
@@ -3664,7 +3708,7 @@ static inline void nfs4_stateid_downgrade(struct nfs4_ol_stateid *stp, u32 to_ac
        case NFS4_SHARE_ACCESS_BOTH:
                break;
        default:
-               BUG();
+               WARN_ON_ONCE(1);
        }
 }
 
@@ -3685,6 +3729,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 {
        __be32 status;
        struct nfs4_ol_stateid *stp;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
                        (int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3697,7 +3742,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 
        nfs4_lock_state();
        status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
-                                       &od->od_stateid, &stp);
+                                       &od->od_stateid, &stp, nn);
        if (status)
                goto out; 
        status = nfserr_inval;
@@ -3760,6 +3805,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        __be32 status;
        struct nfs4_openowner *oo;
        struct nfs4_ol_stateid *stp;
+       struct net *net = SVC_NET(rqstp);
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        dprintk("NFSD: nfsd4_close on file %.*s\n", 
                        (int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3769,7 +3816,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
                                        &close->cl_stateid,
                                        NFS4_OPEN_STID|NFS4_CLOSED_STID,
-                                       &stp);
+                                       &stp, nn);
        if (status)
                goto out; 
        oo = openowner(stp->st_stateowner);
@@ -3791,7 +3838,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                         * little while to handle CLOSE replay.
                         */
                        if (list_empty(&oo->oo_owner.so_stateids))
-                               move_to_close_lru(oo);
+                               move_to_close_lru(oo, SVC_NET(rqstp));
                }
        }
 out:
@@ -3807,15 +3854,15 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct nfs4_delegation *dp;
        stateid_t *stateid = &dr->dr_stateid;
        struct nfs4_stid *s;
-       struct inode *inode;
        __be32 status;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
                return status;
-       inode = cstate->current_fh.fh_dentry->d_inode;
 
        nfs4_lock_state();
-       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
+       status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s,
+                                     cstate->minorversion, nn);
        if (status)
                goto out;
        dp = delegstateid(s);
@@ -3833,8 +3880,6 @@ out:
 
 #define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))
 
-#define LOCKOWNER_INO_HASH_BITS 8
-#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS)
 #define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1)
 
 static inline u64
@@ -3852,7 +3897,7 @@ last_byte_offset(u64 start, u64 len)
 {
        u64 end;
 
-       BUG_ON(!len);
+       WARN_ON_ONCE(!len);
        end = start + len;
        return end > start ? end - 1: NFS4_MAX_UINT64;
 }
@@ -3864,8 +3909,6 @@ static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct
                & LOCKOWNER_INO_HASH_MASK;
 }
 
-static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE];
-
 /*
  * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
  * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
@@ -3931,12 +3974,12 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
 
 static struct nfs4_lockowner *
 find_lockowner_str(struct inode *inode, clientid_t *clid,
-               struct xdr_netobj *owner)
+                  struct xdr_netobj *owner, struct nfsd_net *nn)
 {
        unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner);
        struct nfs4_lockowner *lo;
 
-       list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
+       list_for_each_entry(lo, &nn->lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
                if (same_lockowner_ino(lo, inode, clid, owner))
                        return lo;
        }
@@ -3948,9 +3991,10 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
        struct inode *inode = open_stp->st_file->fi_inode;
        unsigned int inohash = lockowner_ino_hashval(inode,
                        clp->cl_clientid.cl_id, &lo->lo_owner.so_owner);
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-       list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
-       list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]);
+       list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
+       list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]);
        list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
 }
 
@@ -4024,8 +4068,10 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s
        struct nfs4_client *cl = oo->oo_owner.so_client;
        struct nfs4_lockowner *lo;
        unsigned int strhashval;
+       struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id);
 
-       lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner);
+       lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid,
+                               &lock->v.new.owner, nn);
        if (lo) {
                if (!cstate->minorversion)
                        return nfserr_bad_seqid;
@@ -4065,7 +4111,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        bool new_state = false;
        int lkflg;
        int err;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct net *net = SVC_NET(rqstp);
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
                (long long) lock->lk_offset,
@@ -4099,7 +4146,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfs4_preprocess_confirmed_seqid_op(cstate,
                                        lock->lk_new_open_seqid,
                                        &lock->lk_new_open_stateid,
-                                       &open_stp);
+                                       &open_stp, nn);
                if (status)
                        goto out;
                open_sop = openowner(open_stp->st_stateowner);
@@ -4113,7 +4160,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfs4_preprocess_seqid_op(cstate,
                                       lock->lk_old_lock_seqid,
                                       &lock->lk_old_lock_stateid,
-                                      NFS4_LOCK_STID, &lock_stp);
+                                      NFS4_LOCK_STID, &lock_stp, nn);
        if (status)
                goto out;
        lock_sop = lockowner(lock_stp->st_stateowner);
@@ -4124,10 +4171,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                goto out;
 
        status = nfserr_grace;
-       if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
+       if (locks_in_grace(net) && !lock->lk_reclaim)
                goto out;
        status = nfserr_no_grace;
-       if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
+       if (!locks_in_grace(net) && lock->lk_reclaim)
                goto out;
 
        file_lock = locks_alloc_lock();
@@ -4238,7 +4285,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct file_lock *file_lock = NULL;
        struct nfs4_lockowner *lo;
        __be32 status;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (locks_in_grace(SVC_NET(rqstp)))
                return nfserr_grace;
@@ -4248,9 +4295,11 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        nfs4_lock_state();
 
-       status = nfserr_stale_clientid;
-       if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn))
-               goto out;
+       if (!nfsd4_has_session(cstate)) {
+               status = lookup_clientid(&lockt->lt_clientid, false, nn, NULL);
+               if (status)
+                       goto out;
+       }
 
        if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
                goto out;
@@ -4278,7 +4327,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                goto out;
        }
 
-       lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
+       lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner, nn);
        if (lo)
                file_lock->fl_owner = (fl_owner_t)lo;
        file_lock->fl_pid = current->tgid;
@@ -4313,7 +4362,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct file_lock *file_lock = NULL;
        __be32 status;
        int err;
-                                                       
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
        dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
                (long long) locku->lu_offset,
                (long long) locku->lu_length);
@@ -4324,7 +4374,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        nfs4_lock_state();
                                                                                
        status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid,
-                                       &locku->lu_stateid, NFS4_LOCK_STID, &stp);
+                                       &locku->lu_stateid, NFS4_LOCK_STID,
+                                       &stp, nn);
        if (status)
                goto out;
        filp = find_any_file(stp->st_file);
@@ -4414,23 +4465,21 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
        struct list_head matches;
        unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
        __be32 status;
-       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
                clid->cl_boot, clid->cl_id);
 
-       /* XXX check for lease expiration */
-
-       status = nfserr_stale_clientid;
-       if (STALE_CLIENTID(clid, nn))
-               return status;
-
        nfs4_lock_state();
 
+       status = lookup_clientid(clid, cstate->minorversion, nn, NULL);
+       if (status)
+               goto out;
+
        status = nfserr_locks_held;
        INIT_LIST_HEAD(&matches);
 
-       list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) {
+       list_for_each_entry(sop, &nn->ownerstr_hashtbl[hashval], so_strhash) {
                if (sop->so_is_open_owner)
                        continue;
                if (!same_owner_str(sop, owner, clid))
@@ -4466,73 +4515,74 @@ alloc_reclaim(void)
        return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
 }
 
-int
-nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
+bool
+nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
 {
-       unsigned int strhashval = clientstr_hashval(name);
-       struct nfs4_client *clp;
+       struct nfs4_client_reclaim *crp;
 
-       clp = find_confirmed_client_by_str(name, strhashval);
-       if (!clp)
-               return 0;
-       return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+       crp = nfsd4_find_reclaim_client(name, nn);
+       return (crp && crp->cr_clp);
 }
 
 /*
  * failure => all reset bets are off, nfserr_no_grace...
  */
-int
-nfs4_client_to_reclaim(const char *name)
+struct nfs4_client_reclaim *
+nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
 {
        unsigned int strhashval;
-       struct nfs4_client_reclaim *crp = NULL;
+       struct nfs4_client_reclaim *crp;
 
        dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
        crp = alloc_reclaim();
-       if (!crp)
-               return 0;
-       strhashval = clientstr_hashval(name);
-       INIT_LIST_HEAD(&crp->cr_strhash);
-       list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
-       memcpy(crp->cr_recdir, name, HEXDIR_LEN);
-       reclaim_str_hashtbl_size++;
-       return 1;
+       if (crp) {
+               strhashval = clientstr_hashval(name);
+               INIT_LIST_HEAD(&crp->cr_strhash);
+               list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
+               memcpy(crp->cr_recdir, name, HEXDIR_LEN);
+               crp->cr_clp = NULL;
+               nn->reclaim_str_hashtbl_size++;
+       }
+       return crp;
+}
+
+void
+nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
+{
+       list_del(&crp->cr_strhash);
+       kfree(crp);
+       nn->reclaim_str_hashtbl_size--;
 }
 
 void
-nfs4_release_reclaim(void)
+nfs4_release_reclaim(struct nfsd_net *nn)
 {
        struct nfs4_client_reclaim *crp = NULL;
        int i;
 
        for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-               while (!list_empty(&reclaim_str_hashtbl[i])) {
-                       crp = list_entry(reclaim_str_hashtbl[i].next,
+               while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
+                       crp = list_entry(nn->reclaim_str_hashtbl[i].next,
                                        struct nfs4_client_reclaim, cr_strhash);
-                       list_del(&crp->cr_strhash);
-                       kfree(crp);
-                       reclaim_str_hashtbl_size--;
+                       nfs4_remove_reclaim_record(crp, nn);
                }
        }
-       BUG_ON(reclaim_str_hashtbl_size);
+       WARN_ON_ONCE(nn->reclaim_str_hashtbl_size);
 }
 
 /*
  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
 struct nfs4_client_reclaim *
-nfsd4_find_reclaim_client(struct nfs4_client *clp)
+nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn)
 {
        unsigned int strhashval;
        struct nfs4_client_reclaim *crp = NULL;
 
-       dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
-                           clp->cl_name.len, clp->cl_name.data,
-                           clp->cl_recdir);
+       dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir);
 
-       /* find clp->cl_name in reclaim_str_hashtbl */
-       strhashval = clientstr_hashval(clp->cl_recdir);
-       list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-               if (same_name(crp->cr_recdir, clp->cl_recdir)) {
+       strhashval = clientstr_hashval(recdir);
+       list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
+               if (same_name(crp->cr_recdir, recdir)) {
                        return crp;
                }
        }
@@ -4543,12 +4593,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 * Called from OPEN. Look for clientid in reclaim list.
 */
 __be32
-nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
+nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
        struct nfs4_client *clp;
 
        /* find clientid in conf_id_hashtbl */
-       clp = find_confirmed_client(clid, sessions);
+       clp = find_confirmed_client(clid, sessions, nn);
        if (clp == NULL)
                return nfserr_reclaim_bad;
 
@@ -4557,124 +4607,177 @@ nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
 
 #ifdef CONFIG_NFSD_FAULT_INJECTION
 
-void nfsd_forget_clients(u64 num)
+u64 nfsd_forget_client(struct nfs4_client *clp, u64 max)
 {
-       struct nfs4_client *clp, *next;
-       int count = 0;
-
-       nfs4_lock_state();
-       list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
-               expire_client(clp);
-               if (++count == num)
-                       break;
-       }
-       nfs4_unlock_state();
-
-       printk(KERN_INFO "NFSD: Forgot %d clients", count);
+       expire_client(clp);
+       return 1;
 }
 
-static void release_lockowner_sop(struct nfs4_stateowner *sop)
+u64 nfsd_print_client(struct nfs4_client *clp, u64 num)
 {
-       release_lockowner(lockowner(sop));
+       char buf[INET6_ADDRSTRLEN];
+       rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
+       printk(KERN_INFO "NFS Client: %s\n", buf);
+       return 1;
 }
 
-static void release_openowner_sop(struct nfs4_stateowner *sop)
+static void nfsd_print_count(struct nfs4_client *clp, unsigned int count,
+                            const char *type)
 {
-       release_openowner(openowner(sop));
+       char buf[INET6_ADDRSTRLEN];
+       rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
+       printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type);
 }
 
-static int nfsd_release_n_owners(u64 num, bool is_open_owner,
-                               void (*release_sop)(struct nfs4_stateowner *))
+static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_lockowner *))
 {
-       int i, count = 0;
-       struct nfs4_stateowner *sop, *next;
+       struct nfs4_openowner *oop;
+       struct nfs4_lockowner *lop, *lo_next;
+       struct nfs4_ol_stateid *stp, *st_next;
+       u64 count = 0;
 
-       for (i = 0; i < OWNER_HASH_SIZE; i++) {
-               list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) {
-                       if (sop->so_is_open_owner != is_open_owner)
-                               continue;
-                       release_sop(sop);
-                       if (++count == num)
-                               return count;
+       list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) {
+               list_for_each_entry_safe(stp, st_next, &oop->oo_owner.so_stateids, st_perstateowner) {
+                       list_for_each_entry_safe(lop, lo_next, &stp->st_lockowners, lo_perstateid) {
+                               if (func)
+                                       func(lop);
+                               if (++count == max)
+                                       return count;
+                       }
                }
        }
+
        return count;
 }
 
-void nfsd_forget_locks(u64 num)
+u64 nfsd_forget_client_locks(struct nfs4_client *clp, u64 max)
 {
-       int count;
-
-       nfs4_lock_state();
-       count = nfsd_release_n_owners(num, false, release_lockowner_sop);
-       nfs4_unlock_state();
+       return nfsd_foreach_client_lock(clp, max, release_lockowner);
+}
 
-       printk(KERN_INFO "NFSD: Forgot %d locks", count);
+u64 nfsd_print_client_locks(struct nfs4_client *clp, u64 max)
+{
+       u64 count = nfsd_foreach_client_lock(clp, max, NULL);
+       nfsd_print_count(clp, count, "locked files");
+       return count;
 }
 
-void nfsd_forget_openowners(u64 num)
+static u64 nfsd_foreach_client_open(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_openowner *))
 {
-       int count;
+       struct nfs4_openowner *oop, *next;
+       u64 count = 0;
 
-       nfs4_lock_state();
-       count = nfsd_release_n_owners(num, true, release_openowner_sop);
-       nfs4_unlock_state();
+       list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) {
+               if (func)
+                       func(oop);
+               if (++count == max)
+                       break;
+       }
 
-       printk(KERN_INFO "NFSD: Forgot %d open owners", count);
+       return count;
 }
 
-static int nfsd_process_n_delegations(u64 num, struct list_head *list)
+u64 nfsd_forget_client_openowners(struct nfs4_client *clp, u64 max)
 {
-       int i, count = 0;
-       struct nfs4_file *fp, *fnext;
-       struct nfs4_delegation *dp, *dnext;
+       return nfsd_foreach_client_open(clp, max, release_openowner);
+}
 
-       for (i = 0; i < FILE_HASH_SIZE; i++) {
-               list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) {
-                       list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) {
-                               list_move(&dp->dl_recall_lru, list);
-                               if (++count == num)
-                                       return count;
-                       }
-               }
-       }
+u64 nfsd_print_client_openowners(struct nfs4_client *clp, u64 max)
+{
+       u64 count = nfsd_foreach_client_open(clp, max, NULL);
+       nfsd_print_count(clp, count, "open files");
+       return count;
+}
+
+static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
+                                    struct list_head *victims)
+{
+       struct nfs4_delegation *dp, *next;
+       u64 count = 0;
 
+       list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) {
+               if (victims)
+                       list_move(&dp->dl_recall_lru, victims);
+               if (++count == max)
+                       break;
+       }
        return count;
 }
 
-void nfsd_forget_delegations(u64 num)
+u64 nfsd_forget_client_delegations(struct nfs4_client *clp, u64 max)
 {
-       unsigned int count;
+       struct nfs4_delegation *dp, *next;
        LIST_HEAD(victims);
-       struct nfs4_delegation *dp, *dnext;
+       u64 count;
 
        spin_lock(&recall_lock);
-       count = nfsd_process_n_delegations(num, &victims);
+       count = nfsd_find_all_delegations(clp, max, &victims);
        spin_unlock(&recall_lock);
 
-       nfs4_lock_state();
-       list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru)
+       list_for_each_entry_safe(dp, next, &victims, dl_recall_lru)
                unhash_delegation(dp);
-       nfs4_unlock_state();
 
-       printk(KERN_INFO "NFSD: Forgot %d delegations", count);
+       return count;
 }
 
-void nfsd_recall_delegations(u64 num)
+u64 nfsd_recall_client_delegations(struct nfs4_client *clp, u64 max)
 {
-       unsigned int count;
+       struct nfs4_delegation *dp, *next;
        LIST_HEAD(victims);
-       struct nfs4_delegation *dp, *dnext;
+       u64 count;
 
        spin_lock(&recall_lock);
-       count = nfsd_process_n_delegations(num, &victims);
-       list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) {
-               list_del(&dp->dl_recall_lru);
+       count = nfsd_find_all_delegations(clp, max, &victims);
+       list_for_each_entry_safe(dp, next, &victims, dl_recall_lru)
                nfsd_break_one_deleg(dp);
-       }
        spin_unlock(&recall_lock);
 
-       printk(KERN_INFO "NFSD: Recalled %d delegations", count);
+       return count;
+}
+
+u64 nfsd_print_client_delegations(struct nfs4_client *clp, u64 max)
+{
+       u64 count = 0;
+
+       spin_lock(&recall_lock);
+       count = nfsd_find_all_delegations(clp, max, NULL);
+       spin_unlock(&recall_lock);
+
+       nfsd_print_count(clp, count, "delegations");
+       return count;
+}
+
+u64 nfsd_for_n_state(u64 max, u64 (*func)(struct nfs4_client *, u64))
+{
+       struct nfs4_client *clp, *next;
+       u64 count = 0;
+       struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
+
+       if (!nfsd_netns_ready(nn))
+               return 0;
+
+       list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
+               count += func(clp, max - count);
+               if ((max != 0) && (count >= max))
+                       break;
+       }
+
+       return count;
+}
+
+struct nfs4_client *nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size)
+{
+       struct nfs4_client *clp;
+       struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
+
+       if (!nfsd_netns_ready(nn))
+               return NULL;
+
+       list_for_each_entry(clp, &nn->client_lru, cl_lru) {
+               if (memcmp(&clp->cl_addr, addr, addr_size) == 0)
+                       return clp;
+       }
+       return NULL;
 }
 
 #endif /* CONFIG_NFSD_FAULT_INJECTION */
@@ -4686,27 +4789,10 @@ nfs4_state_init(void)
 {
        int i;
 
-       for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-               INIT_LIST_HEAD(&conf_id_hashtbl[i]);
-               INIT_LIST_HEAD(&conf_str_hashtbl[i]);
-               INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
-               INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
-               INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
-       }
-       for (i = 0; i < SESSION_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&sessionid_hashtbl[i]);
        for (i = 0; i < FILE_HASH_SIZE; i++) {
                INIT_LIST_HEAD(&file_hashtbl[i]);
        }
-       for (i = 0; i < OWNER_HASH_SIZE; i++) {
-               INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
-       }
-       for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]);
-       INIT_LIST_HEAD(&close_lru);
-       INIT_LIST_HEAD(&client_lru);
        INIT_LIST_HEAD(&del_recall_lru);
-       reclaim_str_hashtbl_size = 0;
 }
 
 /*
@@ -4730,12 +4816,100 @@ set_max_delegations(void)
        max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
 }
 
-/* initialization to perform when the nfsd service is started: */
+static int nfs4_state_create_net(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int i;
+
+       nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+                       CLIENT_HASH_SIZE, GFP_KERNEL);
+       if (!nn->conf_id_hashtbl)
+               goto err;
+       nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+                       CLIENT_HASH_SIZE, GFP_KERNEL);
+       if (!nn->unconf_id_hashtbl)
+               goto err_unconf_id;
+       nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
+                       OWNER_HASH_SIZE, GFP_KERNEL);
+       if (!nn->ownerstr_hashtbl)
+               goto err_ownerstr;
+       nn->lockowner_ino_hashtbl = kmalloc(sizeof(struct list_head) *
+                       LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
+       if (!nn->lockowner_ino_hashtbl)
+               goto err_lockowner_ino;
+       nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
+                       SESSION_HASH_SIZE, GFP_KERNEL);
+       if (!nn->sessionid_hashtbl)
+               goto err_sessionid;
+
+       for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+               INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+               INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
+       }
+       for (i = 0; i < OWNER_HASH_SIZE; i++)
+               INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
+       for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
+               INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
+       for (i = 0; i < SESSION_HASH_SIZE; i++)
+               INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
+       nn->conf_name_tree = RB_ROOT;
+       nn->unconf_name_tree = RB_ROOT;
+       INIT_LIST_HEAD(&nn->client_lru);
+       INIT_LIST_HEAD(&nn->close_lru);
+       spin_lock_init(&nn->client_lock);
+
+       INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
+       get_net(net);
+
+       return 0;
+
+err_sessionid:
+       kfree(nn->lockowner_ino_hashtbl);
+err_lockowner_ino:
+       kfree(nn->ownerstr_hashtbl);
+err_ownerstr:
+       kfree(nn->unconf_id_hashtbl);
+err_unconf_id:
+       kfree(nn->conf_id_hashtbl);
+err:
+       return -ENOMEM;
+}
+
+static void
+nfs4_state_destroy_net(struct net *net)
+{
+       int i;
+       struct nfs4_client *clp = NULL;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct rb_node *node, *tmp;
+
+       for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+               while (!list_empty(&nn->conf_id_hashtbl[i])) {
+                       clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
+                       destroy_client(clp);
+               }
+       }
+
+       node = rb_first(&nn->unconf_name_tree);
+       while (node != NULL) {
+               tmp = node;
+               node = rb_next(tmp);
+               clp = rb_entry(tmp, struct nfs4_client, cl_namenode);
+               rb_erase(tmp, &nn->unconf_name_tree);
+               destroy_client(clp);
+       }
+
+       kfree(nn->sessionid_hashtbl);
+       kfree(nn->lockowner_ino_hashtbl);
+       kfree(nn->ownerstr_hashtbl);
+       kfree(nn->unconf_id_hashtbl);
+       kfree(nn->conf_id_hashtbl);
+       put_net(net);
+}
 
 int
-nfs4_state_start(void)
+nfs4_state_start_net(struct net *net)
 {
-       struct net *net = &init_net;
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        int ret;
 
@@ -4746,18 +4920,32 @@ nfs4_state_start(void)
         * to that instead and then do most of the rest of this on a per-net
         * basis.
         */
-       get_net(net);
+       if (net != &init_net)
+               return -EINVAL;
+
+       ret = nfs4_state_create_net(net);
+       if (ret)
+               return ret;
        nfsd4_client_tracking_init(net);
        nn->boot_time = get_seconds();
        locks_start_grace(net, &nn->nfsd4_manager);
        nn->grace_ended = false;
-       printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
-              nfsd4_grace);
+       printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
+              nn->nfsd4_grace, net);
+       queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
+       return 0;
+}
+
+/* initialization to perform when the nfsd service is started: */
+
+int
+nfs4_state_start(void)
+{
+       int ret;
+
        ret = set_callback_cred();
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_recovery;
-       }
+       if (ret)
+               return -ENOMEM;
        laundry_wq = create_singlethread_workqueue("nfsd4");
        if (laundry_wq == NULL) {
                ret = -ENOMEM;
@@ -4766,39 +4954,34 @@ nfs4_state_start(void)
        ret = nfsd4_create_callback_queue();
        if (ret)
                goto out_free_laundry;
-       queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
+
        set_max_delegations();
+
        return 0;
+
 out_free_laundry:
        destroy_workqueue(laundry_wq);
 out_recovery:
-       nfsd4_client_tracking_exit(net);
-       put_net(net);
        return ret;
 }
 
-static void
-__nfs4_state_shutdown(void)
+/* should be called with the state lock held */
+void
+nfs4_state_shutdown_net(struct net *net)
 {
-       int i;
-       struct nfs4_client *clp = NULL;
        struct nfs4_delegation *dp = NULL;
        struct list_head *pos, *next, reaplist;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       cancel_delayed_work_sync(&nn->laundromat_work);
+       locks_end_grace(&nn->nfsd4_manager);
 
-       for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-               while (!list_empty(&conf_id_hashtbl[i])) {
-                       clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
-                       destroy_client(clp);
-               }
-               while (!list_empty(&unconf_str_hashtbl[i])) {
-                       clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
-                       destroy_client(clp);
-               }
-       }
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&recall_lock);
        list_for_each_safe(pos, next, &del_recall_lru) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+               if (dp->dl_stid.sc_client->net != net)
+                       continue;
                list_move(&dp->dl_recall_lru, &reaplist);
        }
        spin_unlock(&recall_lock);
@@ -4807,22 +4990,14 @@ __nfs4_state_shutdown(void)
                unhash_delegation(dp);
        }
 
-       nfsd4_client_tracking_exit(&init_net);
-       put_net(&init_net);
+       nfsd4_client_tracking_exit(net);
+       nfs4_state_destroy_net(net);
 }
 
 void
 nfs4_state_shutdown(void)
 {
-       struct net *net = &init_net;
-       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-
-       cancel_delayed_work_sync(&laundromat_work);
        destroy_workqueue(laundry_wq);
-       locks_end_grace(&nn->nfsd4_manager);
-       nfs4_lock_state();
-       __nfs4_state_shutdown();
-       nfs4_unlock_state();
        nfsd4_destroy_callback_queue();
 }
 
index fd548d1550882a78abb7cbe3e632bff6021f6030..0dc11586682fd7d93c85790af67bd8d83f6f9002 100644 (file)
@@ -53,6 +53,7 @@
 #include "vfs.h"
 #include "state.h"
 #include "cache.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY               NFSDDBG_XDR
 
 #define NFS4_REFERRAL_FSID_MINOR       0x8000000ULL
 
 static __be32
-check_filename(char *str, int len, __be32 err)
+check_filename(char *str, int len)
 {
        int i;
 
        if (len == 0)
                return nfserr_inval;
        if (isdotent(str, len))
-               return err;
+               return nfserr_badname;
        for (i = 0; i < len; i++)
                if (str[i] == '/')
-                       return err;
+                       return nfserr_badname;
        return 0;
 }
 
@@ -422,6 +423,86 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
        DECODE_TAIL;
 }
 
+static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
+{
+       DECODE_HEAD;
+       u32 dummy, uid, gid;
+       char *machine_name;
+       int i;
+       int nr_secflavs;
+
+       /* callback_sec_params4 */
+       READ_BUF(4);
+       READ32(nr_secflavs);
+       cbs->flavor = (u32)(-1);
+       for (i = 0; i < nr_secflavs; ++i) {
+               READ_BUF(4);
+               READ32(dummy);
+               switch (dummy) {
+               case RPC_AUTH_NULL:
+                       /* Nothing to read */
+                       if (cbs->flavor == (u32)(-1))
+                               cbs->flavor = RPC_AUTH_NULL;
+                       break;
+               case RPC_AUTH_UNIX:
+                       READ_BUF(8);
+                       /* stamp */
+                       READ32(dummy);
+
+                       /* machine name */
+                       READ32(dummy);
+                       READ_BUF(dummy);
+                       SAVEMEM(machine_name, dummy);
+
+                       /* uid, gid */
+                       READ_BUF(8);
+                       READ32(uid);
+                       READ32(gid);
+
+                       /* more gids */
+                       READ_BUF(4);
+                       READ32(dummy);
+                       READ_BUF(dummy * 4);
+                       if (cbs->flavor == (u32)(-1)) {
+                               cbs->uid = uid;
+                               cbs->gid = gid;
+                               cbs->flavor = RPC_AUTH_UNIX;
+                       }
+                       break;
+               case RPC_AUTH_GSS:
+                       dprintk("RPC_AUTH_GSS callback secflavor "
+                               "not supported!\n");
+                       READ_BUF(8);
+                       /* gcbp_service */
+                       READ32(dummy);
+                       /* gcbp_handle_from_server */
+                       READ32(dummy);
+                       READ_BUF(dummy);
+                       p += XDR_QUADLEN(dummy);
+                       /* gcbp_handle_from_client */
+                       READ_BUF(4);
+                       READ32(dummy);
+                       READ_BUF(dummy);
+                       break;
+               default:
+                       dprintk("Illegal callback secflavor\n");
+                       return nfserr_inval;
+               }
+       }
+       DECODE_TAIL;
+}
+
+static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
+{
+       DECODE_HEAD;
+
+       READ_BUF(4);
+       READ32(bc->bc_cb_program);
+       nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
+
+       DECODE_TAIL;
+}
+
 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
 {
        DECODE_HEAD;
@@ -490,7 +571,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
        READ32(create->cr_namelen);
        READ_BUF(create->cr_namelen);
        SAVEMEM(create->cr_name, create->cr_namelen);
-       if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
+       if ((status = check_filename(create->cr_name, create->cr_namelen)))
                return status;
 
        status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
@@ -522,7 +603,7 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
        READ32(link->li_namelen);
        READ_BUF(link->li_namelen);
        SAVEMEM(link->li_name, link->li_namelen);
-       if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
+       if ((status = check_filename(link->li_name, link->li_namelen)))
                return status;
 
        DECODE_TAIL;
@@ -616,7 +697,7 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
        READ32(lookup->lo_len);
        READ_BUF(lookup->lo_len);
        SAVEMEM(lookup->lo_name, lookup->lo_len);
-       if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
+       if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
                return status;
 
        DECODE_TAIL;
@@ -780,7 +861,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
                READ32(open->op_fname.len);
                READ_BUF(open->op_fname.len);
                SAVEMEM(open->op_fname.data, open->op_fname.len);
-               if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
+               if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
                        return status;
                break;
        case NFS4_OPEN_CLAIM_PREVIOUS:
@@ -795,7 +876,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
                READ32(open->op_fname.len);
                READ_BUF(open->op_fname.len);
                SAVEMEM(open->op_fname.data, open->op_fname.len);
-               if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
+               if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
                        return status;
                break;
        case NFS4_OPEN_CLAIM_FH:
@@ -907,7 +988,7 @@ nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove
        READ32(remove->rm_namelen);
        READ_BUF(remove->rm_namelen);
        SAVEMEM(remove->rm_name, remove->rm_namelen);
-       if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
+       if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
                return status;
 
        DECODE_TAIL;
@@ -925,9 +1006,9 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename
        READ32(rename->rn_tnamelen);
        READ_BUF(rename->rn_tnamelen);
        SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
-       if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
+       if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
                return status;
-       if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
+       if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
                return status;
 
        DECODE_TAIL;
@@ -954,8 +1035,7 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
        READ32(secinfo->si_namelen);
        READ_BUF(secinfo->si_namelen);
        SAVEMEM(secinfo->si_name, secinfo->si_namelen);
-       status = check_filename(secinfo->si_name, secinfo->si_namelen,
-                                                               nfserr_noent);
+       status = check_filename(secinfo->si_name, secinfo->si_namelen);
        if (status)
                return status;
        DECODE_TAIL;
@@ -1026,31 +1106,14 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
 static __be32
 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
 {
-#if 0
-       struct nfsd4_compoundargs save = {
-               .p = argp->p,
-               .end = argp->end,
-               .rqstp = argp->rqstp,
-       };
-       u32             ve_bmval[2];
-       struct iattr    ve_iattr;           /* request */
-       struct nfs4_acl *ve_acl;            /* request */
-#endif
        DECODE_HEAD;
 
        if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
                goto out;
 
        /* For convenience's sake, we compare raw xdr'd attributes in
-        * nfsd4_proc_verify; however we still decode here just to return
-        * correct error in case of bad xdr. */
-#if 0
-       status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
-       if (status == nfserr_inval) {
-               status = nfserrno(status);
-               goto out;
-       }
-#endif
+        * nfsd4_proc_verify */
+
        READ_BUF(4);
        READ32(verify->ve_attrlen);
        READ_BUF(verify->ve_attrlen);
@@ -1063,7 +1126,6 @@ static __be32
 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
        int avail;
-       int v;
        int len;
        DECODE_HEAD;
 
@@ -1087,27 +1149,26 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
                                __FILE__, __LINE__);
                goto xdr_error;
        }
-       argp->rqstp->rq_vec[0].iov_base = p;
-       argp->rqstp->rq_vec[0].iov_len = avail;
-       v = 0;
-       len = write->wr_buflen;
-       while (len > argp->rqstp->rq_vec[v].iov_len) {
-               len -= argp->rqstp->rq_vec[v].iov_len;
-               v++;
-               argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]);
-               argp->pagelist++;
-               if (argp->pagelen >= PAGE_SIZE) {
-                       argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE;
-                       argp->pagelen -= PAGE_SIZE;
-               } else {
-                       argp->rqstp->rq_vec[v].iov_len = argp->pagelen;
-                       argp->pagelen -= len;
-               }
+       write->wr_head.iov_base = p;
+       write->wr_head.iov_len = avail;
+       WARN_ON(avail != (XDR_QUADLEN(avail) << 2));
+       write->wr_pagelist = argp->pagelist;
+
+       len = XDR_QUADLEN(write->wr_buflen) << 2;
+       if (len >= avail) {
+               int pages;
+
+               len -= avail;
+
+               pages = len >> PAGE_SHIFT;
+               argp->pagelist += pages;
+               argp->pagelen -= pages * PAGE_SIZE;
+               len -= pages * PAGE_SIZE;
+
+               argp->p = (__be32 *)page_address(argp->pagelist[0]);
+               argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
        }
-       argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
-       argp->p = (__be32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
-       argp->rqstp->rq_vec[v].iov_len = len;
-       write->wr_vlen = v+1;
+       argp->p += XDR_QUADLEN(len);
 
        DECODE_TAIL;
 }
@@ -1237,11 +1298,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
                            struct nfsd4_create_session *sess)
 {
        DECODE_HEAD;
-
        u32 dummy;
-       char *machine_name;
-       int i;
-       int nr_secflavs;
 
        READ_BUF(16);
        COPYMEM(&sess->clientid, 8);
@@ -1282,58 +1339,9 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
                goto xdr_error;
        }
 
-       READ_BUF(8);
+       READ_BUF(4);
        READ32(sess->callback_prog);
-
-       /* callback_sec_params4 */
-       READ32(nr_secflavs);
-       for (i = 0; i < nr_secflavs; ++i) {
-               READ_BUF(4);
-               READ32(dummy);
-               switch (dummy) {
-               case RPC_AUTH_NULL:
-                       /* Nothing to read */
-                       break;
-               case RPC_AUTH_UNIX:
-                       READ_BUF(8);
-                       /* stamp */
-                       READ32(dummy);
-
-                       /* machine name */
-                       READ32(dummy);
-                       READ_BUF(dummy);
-                       SAVEMEM(machine_name, dummy);
-
-                       /* uid, gid */
-                       READ_BUF(8);
-                       READ32(sess->uid);
-                       READ32(sess->gid);
-
-                       /* more gids */
-                       READ_BUF(4);
-                       READ32(dummy);
-                       READ_BUF(dummy * 4);
-                       break;
-               case RPC_AUTH_GSS:
-                       dprintk("RPC_AUTH_GSS callback secflavor "
-                               "not supported!\n");
-                       READ_BUF(8);
-                       /* gcbp_service */
-                       READ32(dummy);
-                       /* gcbp_handle_from_server */
-                       READ32(dummy);
-                       READ_BUF(dummy);
-                       p += XDR_QUADLEN(dummy);
-                       /* gcbp_handle_from_client */
-                       READ_BUF(4);
-                       READ32(dummy);
-                       READ_BUF(dummy);
-                       break;
-               default:
-                       dprintk("Illegal callback secflavor\n");
-                       return nfserr_inval;
-               }
-       }
+       nfsd4_decode_cb_sec(argp, &sess->cb_sec);
        DECODE_TAIL;
 }
 
@@ -1528,7 +1536,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
        [OP_RELEASE_LOCKOWNER]  = (nfsd4_dec)nfsd4_decode_notsupp,
 
        /* new operations for NFSv4.1 */
-       [OP_BACKCHANNEL_CTL]    = (nfsd4_dec)nfsd4_decode_notsupp,
+       [OP_BACKCHANNEL_CTL]    = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
        [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
        [OP_EXCHANGE_ID]        = (nfsd4_dec)nfsd4_decode_exchange_id,
        [OP_CREATE_SESSION]     = (nfsd4_dec)nfsd4_decode_create_session,
@@ -1568,12 +1576,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
        bool cachethis = false;
        int i;
 
-       /*
-        * XXX: According to spec, we should check the tag
-        * for UTF-8 compliance.  I'm postponing this for
-        * now because it seems that some clients do use
-        * binary tags.
-        */
        READ_BUF(4);
        READ32(argp->taglen);
        READ_BUF(argp->taglen + 8);
@@ -1603,38 +1605,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
                op = &argp->ops[i];
                op->replay = NULL;
 
-               /*
-                * We can't use READ_BUF() here because we need to handle
-                * a missing opcode as an OP_WRITE + 1. So we need to check
-                * to see if we're truly at the end of our buffer or if there
-                * is another page we need to flip to.
-                */
-
-               if (argp->p == argp->end) {
-                       if (argp->pagelen < 4) {
-                               /* There isn't an opcode still on the wire */
-                               op->opnum = OP_WRITE + 1;
-                               op->status = nfserr_bad_xdr;
-                               argp->opcnt = i+1;
-                               break;
-                       }
-
-                       /*
-                        * False alarm. We just hit a page boundary, but there
-                        * is still data available.  Move pointer across page
-                        * boundary.  *snip from READ_BUF*
-                        */
-                       argp->p = page_address(argp->pagelist[0]);
-                       argp->pagelist++;
-                       if (argp->pagelen < PAGE_SIZE) {
-                               argp->end = argp->p + (argp->pagelen>>2);
-                               argp->pagelen = 0;
-                       } else {
-                               argp->end = argp->p + (PAGE_SIZE>>2);
-                               argp->pagelen -= PAGE_SIZE;
-                       }
-               }
-               op->opnum = ntohl(*argp->p++);
+               READ_BUF(4);
+               READ32(op->opnum);
 
                if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
                        op->status = ops->decoders[op->opnum](argp, &op->u);
@@ -2014,6 +1986,22 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
        return 0;
 }
 
+
+static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
+{
+       struct path path = exp->ex_path;
+       int err;
+
+       path_get(&path);
+       while (follow_up(&path)) {
+               if (path.dentry != path.mnt->mnt_root)
+                       break;
+       }
+       err = vfs_getattr(path.mnt, path.dentry, stat);
+       path_put(&path);
+       return err;
+}
+
 /*
  * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
  * ourselves.
@@ -2048,6 +2036,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                .mnt    = exp->ex_path.mnt,
                .dentry = dentry,
        };
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
        BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
@@ -2208,7 +2197,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
        if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
                if ((buflen -= 4) < 0)
                        goto out_resource;
-               WRITE32(nfsd4_lease);
+               WRITE32(nn->nfsd4_lease);
        }
        if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
                if ((buflen -= 4) < 0)
@@ -2430,18 +2419,8 @@ out_acl:
                 * and this is the root of a cross-mounted filesystem.
                 */
                if (ignore_crossmnt == 0 &&
-                   dentry == exp->ex_path.mnt->mnt_root) {
-                       struct path path = exp->ex_path;
-                       path_get(&path);
-                       while (follow_up(&path)) {
-                               if (path.dentry != path.mnt->mnt_root)
-                                       break;
-                       }
-                       err = vfs_getattr(path.mnt, path.dentry, &stat);
-                       path_put(&path);
-                       if (err)
-                               goto out_nfserr;
-               }
+                   dentry == exp->ex_path.mnt->mnt_root)
+                       get_parent_attributes(exp, &stat);
                WRITE64(stat.ino);
        }
        if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
@@ -2927,7 +2906,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
                  struct nfsd4_read *read)
 {
        u32 eof;
-       int v, pn;
+       int v;
+       struct page *page;
        unsigned long maxcount; 
        long len;
        __be32 *p;
@@ -2946,11 +2926,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
        len = maxcount;
        v = 0;
        while (len > 0) {
-               pn = resp->rqstp->rq_resused++;
-               resp->rqstp->rq_vec[v].iov_base =
-                       page_address(resp->rqstp->rq_respages[pn]);
+               page = *(resp->rqstp->rq_next_page);
+               if (!page) { /* ran out of pages */
+                       maxcount -= len;
+                       break;
+               }
+               resp->rqstp->rq_vec[v].iov_base = page_address(page);
                resp->rqstp->rq_vec[v].iov_len =
                        len < PAGE_SIZE ? len : PAGE_SIZE;
+               resp->rqstp->rq_next_page++;
                v++;
                len -= PAGE_SIZE;
        }
@@ -2996,8 +2980,10 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
                return nfserr;
        if (resp->xbuf->page_len)
                return nfserr_resource;
+       if (!*resp->rqstp->rq_next_page)
+               return nfserr_resource;
 
-       page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
+       page = page_address(*(resp->rqstp->rq_next_page++));
 
        maxcount = PAGE_SIZE;
        RESERVE_SPACE(4);
@@ -3045,6 +3031,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
                return nfserr;
        if (resp->xbuf->page_len)
                return nfserr_resource;
+       if (!*resp->rqstp->rq_next_page)
+               return nfserr_resource;
 
        RESERVE_SPACE(NFS4_VERIFIER_SIZE);
        savep = p;
@@ -3071,7 +3059,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
                goto err_no_verf;
        }
 
-       page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
+       page = page_address(*(resp->rqstp->rq_next_page++));
        readdir->common.err = 0;
        readdir->buflen = maxcount;
        readdir->buffer = page;
@@ -3094,8 +3082,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
        p = readdir->buffer;
        *p++ = 0;       /* no more entries */
        *p++ = htonl(readdir->common.err == nfserr_eof);
-       resp->xbuf->page_len = ((char*)p) - (char*)page_address(
-               resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
+       resp->xbuf->page_len = ((char*)p) -
+               (char*)page_address(*(resp->rqstp->rq_next_page-1));
 
        /* Use rest of head for padding and remaining ops: */
        resp->xbuf->tail[0].iov_base = tailbase;
index dab350dfc376e48435817b2b136129bfb92de799..74934284d9a7b27433a172231d88647b4a414aec 100644 (file)
@@ -19,7 +19,7 @@
 #include "idmap.h"
 #include "nfsd.h"
 #include "cache.h"
-#include "fault_inject.h"
+#include "state.h"
 #include "netns.h"
 
 /*
@@ -186,9 +186,6 @@ static struct file_operations supported_enctypes_ops = {
 };
 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
 
-extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
-extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
-
 static const struct file_operations pool_stats_operations = {
        .open           = nfsd_pool_stats_open,
        .read           = seq_read,
@@ -399,6 +396,8 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
 {
        char *mesg = buf;
        int rv;
+       struct net *net = &init_net;
+
        if (size > 0) {
                int newthreads;
                rv = get_int(&mesg, &newthreads);
@@ -406,11 +405,11 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
                        return rv;
                if (newthreads < 0)
                        return -EINVAL;
-               rv = nfsd_svc(newthreads);
+               rv = nfsd_svc(newthreads, net);
                if (rv < 0)
                        return rv;
        } else
-               rv = nfsd_nrthreads();
+               rv = nfsd_nrthreads(net);
 
        return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
 }
@@ -448,9 +447,10 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
        int len;
        int npools;
        int *nthreads;
+       struct net *net = &init_net;
 
        mutex_lock(&nfsd_mutex);
-       npools = nfsd_nrpools();
+       npools = nfsd_nrpools(net);
        if (npools == 0) {
                /*
                 * NFS is shut down.  The admin can start it by
@@ -478,12 +478,12 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
                        if (nthreads[i] < 0)
                                goto out_free;
                }
-               rv = nfsd_set_nrthreads(i, nthreads);
+               rv = nfsd_set_nrthreads(i, nthreads, net);
                if (rv)
                        goto out_free;
        }
 
-       rv = nfsd_get_nrthreads(npools, nthreads);
+       rv = nfsd_get_nrthreads(npools, nthreads, net);
        if (rv)
                goto out_free;
 
@@ -510,11 +510,13 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
        unsigned minor;
        ssize_t tlen = 0;
        char *sep;
+       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        if (size>0) {
-               if (nfsd_serv)
+               if (nn->nfsd_serv)
                        /* Cannot change versions without updating
-                        * nfsd_serv->sv_xdrsize, and reallocing
+                        * nn->nfsd_serv->sv_xdrsize, and reallocing
                         * rq_argp and rq_resp
                         */
                        return -EBUSY;
@@ -645,11 +647,13 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
  * Zero-length write.  Return a list of NFSD's current listener
  * transports.
  */
-static ssize_t __write_ports_names(char *buf)
+static ssize_t __write_ports_names(char *buf, struct net *net)
 {
-       if (nfsd_serv == NULL)
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       if (nn->nfsd_serv == NULL)
                return 0;
-       return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
+       return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
 }
 
 /*
@@ -657,28 +661,28 @@ static ssize_t __write_ports_names(char *buf)
  * a socket of a supported family/protocol, and we use it as an
  * nfsd listener.
  */
-static ssize_t __write_ports_addfd(char *buf)
+static ssize_t __write_ports_addfd(char *buf, struct net *net)
 {
        char *mesg = buf;
        int fd, err;
-       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        err = get_int(&mesg, &fd);
        if (err != 0 || fd < 0)
                return -EINVAL;
 
-       err = nfsd_create_serv();
+       err = nfsd_create_serv(net);
        if (err != 0)
                return err;
 
-       err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
+       err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
        if (err < 0) {
                nfsd_destroy(net);
                return err;
        }
 
        /* Decrease the count, but don't shut down the service */
-       nfsd_serv->sv_nrthreads--;
+       nn->nfsd_serv->sv_nrthreads--;
        return err;
 }
 
@@ -686,12 +690,12 @@ static ssize_t __write_ports_addfd(char *buf)
  * A transport listener is added by writing it's transport name and
  * a port number.
  */
-static ssize_t __write_ports_addxprt(char *buf)
+static ssize_t __write_ports_addxprt(char *buf, struct net *net)
 {
        char transport[16];
        struct svc_xprt *xprt;
        int port, err;
-       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        if (sscanf(buf, "%15s %5u", transport, &port) != 2)
                return -EINVAL;
@@ -699,25 +703,25 @@ static ssize_t __write_ports_addxprt(char *buf)
        if (port < 1 || port > USHRT_MAX)
                return -EINVAL;
 
-       err = nfsd_create_serv();
+       err = nfsd_create_serv(net);
        if (err != 0)
                return err;
 
-       err = svc_create_xprt(nfsd_serv, transport, net,
+       err = svc_create_xprt(nn->nfsd_serv, transport, net,
                                PF_INET, port, SVC_SOCK_ANONYMOUS);
        if (err < 0)
                goto out_err;
 
-       err = svc_create_xprt(nfsd_serv, transport, net,
+       err = svc_create_xprt(nn->nfsd_serv, transport, net,
                                PF_INET6, port, SVC_SOCK_ANONYMOUS);
        if (err < 0 && err != -EAFNOSUPPORT)
                goto out_close;
 
        /* Decrease the count, but don't shut down the service */
-       nfsd_serv->sv_nrthreads--;
+       nn->nfsd_serv->sv_nrthreads--;
        return 0;
 out_close:
-       xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port);
+       xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
        if (xprt != NULL) {
                svc_close_xprt(xprt);
                svc_xprt_put(xprt);
@@ -727,16 +731,17 @@ out_err:
        return err;
 }
 
-static ssize_t __write_ports(struct file *file, char *buf, size_t size)
+static ssize_t __write_ports(struct file *file, char *buf, size_t size,
+                            struct net *net)
 {
        if (size == 0)
-               return __write_ports_names(buf);
+               return __write_ports_names(buf, net);
 
        if (isdigit(buf[0]))
-               return __write_ports_addfd(buf);
+               return __write_ports_addfd(buf, net);
 
        if (isalpha(buf[0]))
-               return __write_ports_addxprt(buf);
+               return __write_ports_addxprt(buf, net);
 
        return -EINVAL;
 }
@@ -787,9 +792,10 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
 static ssize_t write_ports(struct file *file, char *buf, size_t size)
 {
        ssize_t rv;
+       struct net *net = &init_net;
 
        mutex_lock(&nfsd_mutex);
-       rv = __write_ports(file, buf, size);
+       rv = __write_ports(file, buf, size, net);
        mutex_unlock(&nfsd_mutex);
        return rv;
 }
@@ -821,6 +827,9 @@ int nfsd_max_blksize;
 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
 {
        char *mesg = buf;
+       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
        if (size > 0) {
                int bsize;
                int rv = get_int(&mesg, &bsize);
@@ -835,7 +844,7 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
                        bsize = NFSSVC_MAXBLKSIZE;
                bsize &= ~(1024-1);
                mutex_lock(&nfsd_mutex);
-               if (nfsd_serv) {
+               if (nn->nfsd_serv) {
                        mutex_unlock(&nfsd_mutex);
                        return -EBUSY;
                }
@@ -848,13 +857,14 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
 }
 
 #ifdef CONFIG_NFSD_V4
-static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
+static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
+                                 time_t *time, struct nfsd_net *nn)
 {
        char *mesg = buf;
        int rv, i;
 
        if (size > 0) {
-               if (nfsd_serv)
+               if (nn->nfsd_serv)
                        return -EBUSY;
                rv = get_int(&mesg, &i);
                if (rv)
@@ -879,12 +889,13 @@ static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, tim
        return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
 }
 
-static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
+static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
+                               time_t *time, struct nfsd_net *nn)
 {
        ssize_t rv;
 
        mutex_lock(&nfsd_mutex);
-       rv = __nfsd4_write_time(file, buf, size, time);
+       rv = __nfsd4_write_time(file, buf, size, time, nn);
        mutex_unlock(&nfsd_mutex);
        return rv;
 }
@@ -912,7 +923,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-       return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
 }
 
 /**
@@ -927,17 +939,19 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  */
 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
 {
-       return nfsd4_write_time(file, buf, size, &nfsd4_grace);
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
 }
 
-static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
+static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
+                                  struct nfsd_net *nn)
 {
        char *mesg = buf;
        char *recdir;
        int len, status;
 
        if (size > 0) {
-               if (nfsd_serv)
+               if (nn->nfsd_serv)
                        return -EBUSY;
                if (size > PATH_MAX || buf[size-1] != '\n')
                        return -EINVAL;
@@ -981,9 +995,10 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
 {
        ssize_t rv;
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
        mutex_lock(&nfsd_mutex);
-       rv = __write_recoverydir(file, buf, size);
+       rv = __write_recoverydir(file, buf, size, nn);
        mutex_unlock(&nfsd_mutex);
        return rv;
 }
@@ -1063,6 +1078,7 @@ int nfsd_net_id;
 static __net_init int nfsd_init_net(struct net *net)
 {
        int retval;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        retval = nfsd_export_init(net);
        if (retval)
@@ -1070,6 +1086,8 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
+       nn->nfsd4_lease = 90;   /* default lease time */
+       nn->nfsd4_grace = 90;
        return 0;
 
 out_idmap_error:
index 80d5ce40aadb02f024316c90f6460fef7ef406ec..de23db255c69c1314b1f6f15cc753463324b2237 100644 (file)
@@ -55,7 +55,6 @@ extern struct svc_version     nfsd_version2, nfsd_version3,
                                nfsd_version4;
 extern u32                     nfsd_supported_minorversion;
 extern struct mutex            nfsd_mutex;
-extern struct svc_serv         *nfsd_serv;
 extern spinlock_t              nfsd_drc_lock;
 extern unsigned int            nfsd_drc_max_mem;
 extern unsigned int            nfsd_drc_mem_used;
@@ -65,26 +64,17 @@ extern const struct seq_operations nfs_exports_op;
 /*
  * Function prototypes.
  */
-int            nfsd_svc(int nrservs);
+int            nfsd_svc(int nrservs, struct net *net);
 int            nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
 
-int            nfsd_nrthreads(void);
-int            nfsd_nrpools(void);
-int            nfsd_get_nrthreads(int n, int *);
-int            nfsd_set_nrthreads(int n, int *);
+int            nfsd_nrthreads(struct net *);
+int            nfsd_nrpools(struct net *);
+int            nfsd_get_nrthreads(int n, int *, struct net *);
+int            nfsd_set_nrthreads(int n, int *, struct net *);
 int            nfsd_pool_stats_open(struct inode *, struct file *);
 int            nfsd_pool_stats_release(struct inode *, struct file *);
 
-static inline void nfsd_destroy(struct net *net)
-{
-       int destroy = (nfsd_serv->sv_nrthreads == 1);
-
-       if (destroy)
-               svc_shutdown_net(nfsd_serv, net);
-       svc_destroy(nfsd_serv);
-       if (destroy)
-               nfsd_serv = NULL;
-}
+void           nfsd_destroy(struct net *net);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 #ifdef CONFIG_NFSD_V2_ACL
@@ -103,7 +93,7 @@ enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
 int nfsd_vers(int vers, enum vers_op change);
 int nfsd_minorversion(u32 minorversion, enum vers_op change);
 void nfsd_reset_versions(void);
-int nfsd_create_serv(void);
+int nfsd_create_serv(struct net *net);
 
 extern int nfsd_max_blksize;
 
@@ -121,7 +111,9 @@ void nfs4_state_init(void);
 int nfsd4_init_slabs(void);
 void nfsd4_free_slabs(void);
 int nfs4_state_start(void);
+int nfs4_state_start_net(struct net *net);
 void nfs4_state_shutdown(void);
+void nfs4_state_shutdown_net(struct net *net);
 void nfs4_reset_lease(time_t leasetime);
 int nfs4_reset_recoverydir(char *recdir);
 char * nfs4_recoverydir(void);
@@ -130,7 +122,9 @@ static inline void nfs4_state_init(void) { }
 static inline int nfsd4_init_slabs(void) { return 0; }
 static inline void nfsd4_free_slabs(void) { }
 static inline int nfs4_state_start(void) { return 0; }
+static inline int nfs4_state_start_net(struct net *net) { return 0; }
 static inline void nfs4_state_shutdown(void) { }
+static inline void nfs4_state_shutdown_net(struct net *net) { }
 static inline void nfs4_reset_lease(time_t leasetime) { }
 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
 static inline char * nfs4_recoverydir(void) {return NULL; }
@@ -265,16 +259,8 @@ void               nfsd_lockd_shutdown(void);
 /* Check for dir entries '.' and '..' */
 #define isdotent(n, l) (l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
 
-/*
- * Time of server startup
- */
-extern struct timeval  nfssvc_boot;
-
 #ifdef CONFIG_NFSD_V4
 
-extern time_t nfsd4_lease;
-extern time_t nfsd4_grace;
-
 /* before processing a COMPOUND operation, we have to check that there
  * is enough space in the buffer for XDR encode to succeed.  otherwise,
  * we might process an operation with side effects, and be unable to
index 032af381b3aa4bd1298b084c57d3c4022293668c..814afaa4458a9285fc3168c47d1df6a1f8164c12 100644 (file)
@@ -572,7 +572,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
 
                if (inode)
                        _fh_update(fhp, exp, dentry);
-               if (fhp->fh_handle.fh_fileid_type == 255) {
+               if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
                        fh_put(fhp);
                        return nfserr_opnotsupp;
                }
@@ -603,7 +603,7 @@ fh_update(struct svc_fh *fhp)
                        goto out;
 
                _fh_update(fhp, fhp->fh_export, dentry);
-               if (fhp->fh_handle.fh_fileid_type == 255)
+               if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
                        return nfserr_opnotsupp;
        }
 out:
index 2013aa001dab620e2e631872c57497b1cdef7afd..cee62ab9d4a30f84fe05d871409f064f24350b07 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/fs_struct.h>
 #include <linux/swap.h>
-#include <linux/nsproxy.h>
 
 #include <linux/sunrpc/stats.h>
 #include <linux/sunrpc/svcsock.h>
 #include "nfsd.h"
 #include "cache.h"
 #include "vfs.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY       NFSDDBG_SVC
 
 extern struct svc_program      nfsd_program;
 static int                     nfsd(void *vrqstp);
-struct timeval                 nfssvc_boot;
 
 /*
- * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
+ * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
  * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
  * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
  *
- * If (out side the lock) nfsd_serv is non-NULL, then it must point to a
+ * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
  * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
  * of nfsd threads must exist and each must listed in ->sp_all_threads in each
  * entry of ->sv_pools[].
@@ -52,7 +51,6 @@ struct timeval                        nfssvc_boot;
  *     nfsd_versions
  */
 DEFINE_MUTEX(nfsd_mutex);
-struct svc_serv                *nfsd_serv;
 
 /*
  * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
@@ -173,28 +171,32 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change)
  */
 #define        NFSD_MAXSERVS           8192
 
-int nfsd_nrthreads(void)
+int nfsd_nrthreads(struct net *net)
 {
        int rv = 0;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
        mutex_lock(&nfsd_mutex);
-       if (nfsd_serv)
-               rv = nfsd_serv->sv_nrthreads;
+       if (nn->nfsd_serv)
+               rv = nn->nfsd_serv->sv_nrthreads;
        mutex_unlock(&nfsd_mutex);
        return rv;
 }
 
-static int nfsd_init_socks(void)
+static int nfsd_init_socks(struct net *net)
 {
        int error;
-       if (!list_empty(&nfsd_serv->sv_permsocks))
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       if (!list_empty(&nn->nfsd_serv->sv_permsocks))
                return 0;
 
-       error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT,
+       error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
 
-       error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT,
+       error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
@@ -202,14 +204,15 @@ static int nfsd_init_socks(void)
        return 0;
 }
 
-static bool nfsd_up = false;
+static int nfsd_users = 0;
 
-static int nfsd_startup(int nrservs)
+static int nfsd_startup_generic(int nrservs)
 {
        int ret;
 
-       if (nfsd_up)
+       if (nfsd_users++)
                return 0;
+
        /*
         * Readahead param cache - will no-op if it already exists.
         * (Note therefore results will be suboptimal if number of
@@ -218,43 +221,79 @@ static int nfsd_startup(int nrservs)
        ret = nfsd_racache_init(2*nrservs);
        if (ret)
                return ret;
-       ret = nfsd_init_socks();
+       ret = nfs4_state_start();
        if (ret)
                goto out_racache;
-       ret = lockd_up(&init_net);
+       return 0;
+
+out_racache:
+       nfsd_racache_shutdown();
+       return ret;
+}
+
+static void nfsd_shutdown_generic(void)
+{
+       if (--nfsd_users)
+               return;
+
+       nfs4_state_shutdown();
+       nfsd_racache_shutdown();
+}
+
+static int nfsd_startup_net(int nrservs, struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int ret;
+
+       if (nn->nfsd_net_up)
+               return 0;
+
+       ret = nfsd_startup_generic(nrservs);
        if (ret)
-               goto out_racache;
-       ret = nfs4_state_start();
+               return ret;
+       ret = nfsd_init_socks(net);
+       if (ret)
+               goto out_socks;
+       ret = lockd_up(net);
+       if (ret)
+               goto out_socks;
+       ret = nfs4_state_start_net(net);
        if (ret)
                goto out_lockd;
-       nfsd_up = true;
+
+       nn->nfsd_net_up = true;
        return 0;
+
 out_lockd:
-       lockd_down(&init_net);
-out_racache:
-       nfsd_racache_shutdown();
+       lockd_down(net);
+out_socks:
+       nfsd_shutdown_generic();
        return ret;
 }
 
-static void nfsd_shutdown(void)
+static void nfsd_shutdown_net(struct net *net)
 {
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       nfs4_state_shutdown_net(net);
+       lockd_down(net);
+       nn->nfsd_net_up = false;
+       nfsd_shutdown_generic();
+}
+
+static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
        /*
         * write_ports can create the server without actually starting
         * any threads--if we get shut down before any threads are
         * started, then nfsd_last_thread will be run before any of this
         * other initialization has been done.
         */
-       if (!nfsd_up)
+       if (!nn->nfsd_net_up)
                return;
-       nfs4_state_shutdown();
-       lockd_down(&init_net);
-       nfsd_racache_shutdown();
-       nfsd_up = false;
-}
-
-static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
-{
-       nfsd_shutdown();
+       nfsd_shutdown_net(net);
 
        svc_rpcb_cleanup(serv, net);
 
@@ -327,69 +366,84 @@ static int nfsd_get_default_max_blksize(void)
        return ret;
 }
 
-int nfsd_create_serv(void)
+int nfsd_create_serv(struct net *net)
 {
        int error;
-       struct net *net = current->nsproxy->net_ns;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        WARN_ON(!mutex_is_locked(&nfsd_mutex));
-       if (nfsd_serv) {
-               svc_get(nfsd_serv);
+       if (nn->nfsd_serv) {
+               svc_get(nn->nfsd_serv);
                return 0;
        }
        if (nfsd_max_blksize == 0)
                nfsd_max_blksize = nfsd_get_default_max_blksize();
        nfsd_reset_versions();
-       nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
+       nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
                                      nfsd_last_thread, nfsd, THIS_MODULE);
-       if (nfsd_serv == NULL)
+       if (nn->nfsd_serv == NULL)
                return -ENOMEM;
 
-       error = svc_bind(nfsd_serv, net);
+       error = svc_bind(nn->nfsd_serv, net);
        if (error < 0) {
-               svc_destroy(nfsd_serv);
+               svc_destroy(nn->nfsd_serv);
                return error;
        }
 
        set_max_drc();
-       do_gettimeofday(&nfssvc_boot);          /* record boot time */
+       do_gettimeofday(&nn->nfssvc_boot);              /* record boot time */
        return 0;
 }
 
-int nfsd_nrpools(void)
+int nfsd_nrpools(struct net *net)
 {
-       if (nfsd_serv == NULL)
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       if (nn->nfsd_serv == NULL)
                return 0;
        else
-               return nfsd_serv->sv_nrpools;
+               return nn->nfsd_serv->sv_nrpools;
 }
 
-int nfsd_get_nrthreads(int n, int *nthreads)
+int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
 {
        int i = 0;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-       if (nfsd_serv != NULL) {
-               for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++)
-                       nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads;
+       if (nn->nfsd_serv != NULL) {
+               for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
+                       nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
        }
 
        return 0;
 }
 
-int nfsd_set_nrthreads(int n, int *nthreads)
+void nfsd_destroy(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
+
+       if (destroy)
+               svc_shutdown_net(nn->nfsd_serv, net);
+       svc_destroy(nn->nfsd_serv);
+       if (destroy)
+               nn->nfsd_serv = NULL;
+}
+
+int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
 {
        int i = 0;
        int tot = 0;
        int err = 0;
-       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        WARN_ON(!mutex_is_locked(&nfsd_mutex));
 
-       if (nfsd_serv == NULL || n <= 0)
+       if (nn->nfsd_serv == NULL || n <= 0)
                return 0;
 
-       if (n > nfsd_serv->sv_nrpools)
-               n = nfsd_serv->sv_nrpools;
+       if (n > nn->nfsd_serv->sv_nrpools)
+               n = nn->nfsd_serv->sv_nrpools;
 
        /* enforce a global maximum number of threads */
        tot = 0;
@@ -419,9 +473,9 @@ int nfsd_set_nrthreads(int n, int *nthreads)
                nthreads[0] = 1;
 
        /* apply the new numbers */
-       svc_get(nfsd_serv);
+       svc_get(nn->nfsd_serv);
        for (i = 0; i < n; i++) {
-               err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
+               err = svc_set_num_threads(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i],
                                          nthreads[i]);
                if (err)
                        break;
@@ -436,11 +490,11 @@ int nfsd_set_nrthreads(int n, int *nthreads)
  * this is the first time nrservs is nonzero.
  */
 int
-nfsd_svc(int nrservs)
+nfsd_svc(int nrservs, struct net *net)
 {
        int     error;
        bool    nfsd_up_before;
-       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        mutex_lock(&nfsd_mutex);
        dprintk("nfsd: creating service\n");
@@ -449,29 +503,29 @@ nfsd_svc(int nrservs)
        if (nrservs > NFSD_MAXSERVS)
                nrservs = NFSD_MAXSERVS;
        error = 0;
-       if (nrservs == 0 && nfsd_serv == NULL)
+       if (nrservs == 0 && nn->nfsd_serv == NULL)
                goto out;
 
-       error = nfsd_create_serv();
+       error = nfsd_create_serv(net);
        if (error)
                goto out;
 
-       nfsd_up_before = nfsd_up;
+       nfsd_up_before = nn->nfsd_net_up;
 
-       error = nfsd_startup(nrservs);
+       error = nfsd_startup_net(nrservs, net);
        if (error)
                goto out_destroy;
-       error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
+       error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs);
        if (error)
                goto out_shutdown;
-       /* We are holding a reference to nfsd_serv which
+       /* We are holding a reference to nn->nfsd_serv which
         * we don't want to count in the return value,
         * so subtract 1
         */
-       error = nfsd_serv->sv_nrthreads - 1;
+       error = nn->nfsd_serv->sv_nrthreads - 1;
 out_shutdown:
        if (error < 0 && !nfsd_up_before)
-               nfsd_shutdown();
+               nfsd_shutdown_net(net);
 out_destroy:
        nfsd_destroy(net);              /* Release server */
 out:
@@ -487,6 +541,8 @@ static int
 nfsd(void *vrqstp)
 {
        struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
+       struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
+       struct net *net = perm_sock->xpt_net;
        int err;
 
        /* Lock module and set up kernel thread */
@@ -551,7 +607,7 @@ out:
        /* Release the thread */
        svc_exit_thread(rqstp);
 
-       nfsd_destroy(&init_net);
+       nfsd_destroy(net);
 
        /* Release module */
        mutex_unlock(&nfsd_mutex);
@@ -640,21 +696,24 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
        }
 
        /* Store reply in cache. */
-       nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
+       nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
        return 1;
 }
 
 int nfsd_pool_stats_open(struct inode *inode, struct file *file)
 {
        int ret;
+       struct net *net = &init_net;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
        mutex_lock(&nfsd_mutex);
-       if (nfsd_serv == NULL) {
+       if (nn->nfsd_serv == NULL) {
                mutex_unlock(&nfsd_mutex);
                return -ENODEV;
        }
        /* bump up the psudo refcount while traversing */
-       svc_get(nfsd_serv);
-       ret = svc_pool_stats_open(nfsd_serv, file);
+       svc_get(nn->nfsd_serv);
+       ret = svc_pool_stats_open(nn->nfsd_serv, file);
        mutex_unlock(&nfsd_mutex);
        return ret;
 }
index 65ec595e2226c0aa4e1f051abef5ef995f1d9fce..979b421069792abe517a5c210dd47d4418723b11 100644 (file)
@@ -246,7 +246,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd_readargs *args)
 {
        unsigned int len;
-       int v,pn;
+       int v;
        if (!(p = decode_fh(p, &args->fh)))
                return 0;
 
@@ -262,8 +262,9 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
         */
        v=0;
        while (len > 0) {
-               pn = rqstp->rq_resused++;
-               rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
+               struct page *p = *(rqstp->rq_next_page++);
+
+               rqstp->rq_vec[v].iov_base = page_address(p);
                rqstp->rq_vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE;
                len -= rqstp->rq_vec[v].iov_len;
                v++;
@@ -355,7 +356,7 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readli
 {
        if (!(p = decode_fh(p, &args->fh)))
                return 0;
-       args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
+       args->buffer = page_address(*(rqstp->rq_next_page++));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -396,7 +397,7 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        if (args->count > PAGE_SIZE)
                args->count = PAGE_SIZE;
 
-       args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
+       args->buffer = page_address(*(rqstp->rq_next_page++));
 
        return xdr_argsize_check(rqstp, p);
 }
index e036894bce57edad09d6a57cf2a69dcb5efb0890..d1c229feed52c129402655ad32f294054f296206 100644 (file)
@@ -150,6 +150,12 @@ struct nfsd4_channel_attrs {
        u32             rdma_attrs;
 };
 
+struct nfsd4_cb_sec {
+       u32     flavor; /* (u32)(-1) used to mean "no valid flavor" */
+       u32     uid;
+       u32     gid;
+};
+
 struct nfsd4_create_session {
        clientid_t                      clientid;
        struct nfs4_sessionid           sessionid;
@@ -158,8 +164,12 @@ struct nfsd4_create_session {
        struct nfsd4_channel_attrs      fore_channel;
        struct nfsd4_channel_attrs      back_channel;
        u32                             callback_prog;
-       u32                             uid;
-       u32                             gid;
+       struct nfsd4_cb_sec             cb_sec;
+};
+
+struct nfsd4_backchannel_ctl {
+       u32     bc_cb_program;
+       struct nfsd4_cb_sec             bc_cb_sec;
 };
 
 struct nfsd4_bind_conn_to_session {
@@ -192,6 +202,7 @@ struct nfsd4_session {
        struct nfs4_sessionid   se_sessionid;
        struct nfsd4_channel_attrs se_fchannel;
        struct nfsd4_channel_attrs se_bchannel;
+       struct nfsd4_cb_sec     se_cb_sec;
        struct list_head        se_conns;
        u32                     se_cb_prog;
        u32                     se_cb_seq_nr;
@@ -221,13 +232,12 @@ struct nfsd4_sessionid {
  */
 struct nfs4_client {
        struct list_head        cl_idhash;      /* hash by cl_clientid.id */
-       struct list_head        cl_strhash;     /* hash by cl_name */
+       struct rb_node          cl_namenode;    /* link into by-name trees */
        struct list_head        cl_openowners;
        struct idr              cl_stateids;    /* stateid lookup */
        struct list_head        cl_delegations;
        struct list_head        cl_lru;         /* tail queue */
        struct xdr_netobj       cl_name;        /* id generated by client */
-       char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
        nfs4_verifier           cl_verifier;    /* generated by client */
        time_t                  cl_time;        /* time of last lease renewal */
        struct sockaddr_storage cl_addr;        /* client ipaddress */
@@ -242,9 +252,11 @@ struct nfs4_client {
 #define NFSD4_CLIENT_CB_KILL           (1)
 #define NFSD4_CLIENT_STABLE            (2)     /* client on stable storage */
 #define NFSD4_CLIENT_RECLAIM_COMPLETE  (3)     /* reclaim_complete done */
+#define NFSD4_CLIENT_CONFIRMED         (4)     /* client is confirmed */
 #define NFSD4_CLIENT_CB_FLAG_MASK      (1 << NFSD4_CLIENT_CB_UPDATE | \
                                         1 << NFSD4_CLIENT_CB_KILL)
        unsigned long           cl_flags;
+       struct rpc_cred         *cl_cb_cred;
        struct rpc_clnt         *cl_cb_client;
        u32                     cl_cb_ident;
 #define NFSD4_CB_UP            0
@@ -271,6 +283,7 @@ struct nfs4_client {
        unsigned long           cl_cb_slot_busy;
        struct rpc_wait_queue   cl_cb_waitq;    /* backchannel callers may */
                                                /* wait here for slots */
+       struct net              *net;
 };
 
 static inline void
@@ -292,6 +305,7 @@ is_client_expired(struct nfs4_client *clp)
  */
 struct nfs4_client_reclaim {
        struct list_head        cr_strhash;     /* hash by cr_name */
+       struct nfs4_client      *cr_clp;        /* pointer to associated clp */
        char                    cr_recdir[HEXDIR_LEN]; /* recover dir */
 };
 
@@ -452,25 +466,26 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
                stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
-extern int nfs4_in_grace(void);
-extern void nfs4_release_reclaim(void);
-extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
-extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
+void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
+extern void nfs4_release_reclaim(struct nfsd_net *);
+extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
+                                                       struct nfsd_net *nn);
+extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
 extern int set_callback_cred(void);
+extern void nfsd4_init_callback(struct nfsd4_callback *);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
 extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
-extern void nfsd4_do_callback_rpc(struct work_struct *);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
-extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
-extern int nfs4_client_to_reclaim(const char *name);
-extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
+extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
+                                                       struct nfsd_net *nn);
+extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
 extern void release_session_client(struct nfsd4_session *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
@@ -480,5 +495,28 @@ extern void nfsd4_client_tracking_exit(struct net *net);
 extern void nfsd4_client_record_create(struct nfs4_client *clp);
 extern void nfsd4_client_record_remove(struct nfs4_client *clp);
 extern int nfsd4_client_record_check(struct nfs4_client *clp);
-extern void nfsd4_record_grace_done(struct net *net, time_t boot_time);
+extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time);
+
+/* nfs fault injection functions */
+#ifdef CONFIG_NFSD_FAULT_INJECTION
+int nfsd_fault_inject_init(void);
+void nfsd_fault_inject_cleanup(void);
+u64 nfsd_for_n_state(u64, u64 (*)(struct nfs4_client *, u64));
+struct nfs4_client *nfsd_find_client(struct sockaddr_storage *, size_t);
+
+u64 nfsd_forget_client(struct nfs4_client *, u64);
+u64 nfsd_forget_client_locks(struct nfs4_client*, u64);
+u64 nfsd_forget_client_openowners(struct nfs4_client *, u64);
+u64 nfsd_forget_client_delegations(struct nfs4_client *, u64);
+u64 nfsd_recall_client_delegations(struct nfs4_client *, u64);
+
+u64 nfsd_print_client(struct nfs4_client *, u64);
+u64 nfsd_print_client_locks(struct nfs4_client *, u64);
+u64 nfsd_print_client_openowners(struct nfs4_client *, u64);
+u64 nfsd_print_client_delegations(struct nfs4_client *, u64);
+#else /* CONFIG_NFSD_FAULT_INJECTION */
+static inline int nfsd_fault_inject_init(void) { return 0; }
+static inline void nfsd_fault_inject_cleanup(void) {}
+#endif /* CONFIG_NFSD_FAULT_INJECTION */
+
 #endif   /* NFSD4_STATE_H */
index c120b48ec305bed3b15aec207b1dd2dac57e952b..d586117fa94a74f07105055bc053746bfa90bdfb 100644 (file)
@@ -886,7 +886,7 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
                  struct splice_desc *sd)
 {
        struct svc_rqst *rqstp = sd->u.data;
-       struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
+       struct page **pp = rqstp->rq_next_page;
        struct page *page = buf->page;
        size_t size;
 
@@ -894,17 +894,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 
        if (rqstp->rq_res.page_len == 0) {
                get_page(page);
-               put_page(*pp);
-               *pp = page;
-               rqstp->rq_resused++;
+               put_page(*rqstp->rq_next_page);
+               *(rqstp->rq_next_page++) = page;
                rqstp->rq_res.page_base = buf->offset;
                rqstp->rq_res.page_len = size;
        } else if (page != pp[-1]) {
                get_page(page);
-               if (*pp)
-                       put_page(*pp);
-               *pp = page;
-               rqstp->rq_resused++;
+               if (*rqstp->rq_next_page)
+                       put_page(*rqstp->rq_next_page);
+               *(rqstp->rq_next_page++) = page;
                rqstp->rq_res.page_len += size;
        } else
                rqstp->rq_res.page_len += size;
@@ -936,7 +934,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
                        .u.data         = rqstp,
                };
 
-               rqstp->rq_resused = 1;
+               rqstp->rq_next_page = rqstp->rq_respages + 1;
                host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
        } else {
                oldfs = get_fs();
@@ -1020,28 +1018,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        inode = dentry->d_inode;
        exp   = fhp->fh_export;
 
-       /*
-        * Request sync writes if
-        *  -   the sync export option has been set, or
-        *  -   the client requested O_SYNC behavior (NFSv3 feature).
-        *  -   The file system doesn't support fsync().
-        * When NFSv2 gathered writes have been configured for this volume,
-        * flushing the data to disk is handled separately below.
-        */
        use_wgather = (rqstp->rq_vers == 2) && EX_WGATHER(exp);
 
-       if (!file->f_op->fsync) {/* COMMIT3 cannot work */
-              stable = 2;
-              *stablep = 2; /* FILE_SYNC */
-       }
-
        if (!EX_ISSYNC(exp))
                stable = 0;
-       if (stable && !use_wgather) {
-               spin_lock(&file->f_lock);
-               file->f_flags |= O_SYNC;
-               spin_unlock(&file->f_lock);
-       }
 
        /* Write the data. */
        oldfs = get_fs(); set_fs(KERNEL_DS);
@@ -1057,8 +1037,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        if (inode->i_mode & (S_ISUID | S_ISGID))
                kill_suid(dentry);
 
-       if (stable && use_wgather)
-               host_err = wait_for_concurrent_writes(file);
+       if (stable) {
+               if (use_wgather)
+                       host_err = wait_for_concurrent_writes(file);
+               else
+                       host_err = vfs_fsync_range(file, offset, offset+*cnt, 0);
+       }
 
 out_nfserr:
        dprintk("nfsd: write complete host_err=%d\n", host_err);
@@ -1485,13 +1469,19 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                case NFS3_CREATE_EXCLUSIVE:
                        if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
                            && dchild->d_inode->i_atime.tv_sec == v_atime
-                           && dchild->d_inode->i_size  == 0 )
+                           && dchild->d_inode->i_size  == 0 ) {
+                               if (created)
+                                       *created = 1;
                                break;
+                       }
                case NFS4_CREATE_EXCLUSIVE4_1:
                        if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
                            && dchild->d_inode->i_atime.tv_sec == v_atime
-                           && dchild->d_inode->i_size  == 0 )
+                           && dchild->d_inode->i_size  == 0 ) {
+                               if (created)
+                                       *created = 1;
                                goto set_attr;
+                       }
                         /* fallthru */
                case NFS3_CREATE_GUARDED:
                        err = nfserr_exist;
index acd127d4ee821660e71fe1e38ef1c804962f6508..0889bfb43dc9ac83bcf6d05c47c5752dbec5e280 100644 (file)
@@ -385,7 +385,8 @@ struct nfsd4_write {
        u64             wr_offset;          /* request */
        u32             wr_stable_how;      /* request */
        u32             wr_buflen;          /* request */
-       int             wr_vlen;
+       struct kvec     wr_head;
+       struct page **  wr_pagelist;        /* request */
 
        u32             wr_bytes_written;   /* response */
        u32             wr_how_written;     /* response */
@@ -462,6 +463,7 @@ struct nfsd4_op {
 
                /* NFSv4.1 */
                struct nfsd4_exchange_id        exchange_id;
+               struct nfsd4_backchannel_ctl    backchannel_ctl;
                struct nfsd4_bind_conn_to_session bind_conn_to_session;
                struct nfsd4_create_session     create_session;
                struct nfsd4_destroy_session    destroy_session;
@@ -526,6 +528,14 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
                || nfsd4_is_solo_sequence(resp);
 }
 
+static inline bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
+{
+       struct nfsd4_compoundres *resp = rqstp->rq_resp;
+       struct nfsd4_compoundargs *argp = rqstp->rq_argp;
+
+       return argp->opcnt == resp->opcnt;
+}
+
 #define NFS4_SVC_XDRSIZE               sizeof(struct nfsd4_compoundargs)
 
 static inline void
@@ -566,6 +576,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
                struct nfsd4_sequence *seq);
 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
                struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
+extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *);
 extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
 extern __be32 nfsd4_create_session(struct svc_rqst *,
                struct nfsd4_compound_state *,
@@ -579,7 +590,7 @@ extern __be32 nfsd4_destroy_session(struct svc_rqst *,
 extern __be32 nfsd4_destroy_clientid(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_destroy_clientid *);
 __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *);
 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
-               struct nfsd4_open *open);
+               struct nfsd4_open *open, struct nfsd_net *nn);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
                struct svc_fh *current_fh, struct nfsd4_open *open);
 extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status);
index 16f35f7423c58e741b0e59d985e244e1048c41fe..61946883025ce60727811aed90211a3bb20e456f 100644 (file)
@@ -167,7 +167,6 @@ const struct file_operations nilfs_file_operations = {
 };
 
 const struct inode_operations nilfs_file_inode_operations = {
-       .truncate       = nilfs_truncate,
        .setattr        = nilfs_setattr,
        .permission     = nilfs_permission,
        .fiemap         = nilfs_fiemap,
index 4d31d2cca7fdc3eaff7643cb67f620bce1cfd069..6b49f14eac8cdadf4bebc9f4ff9c1869b5107f12 100644 (file)
@@ -213,6 +213,16 @@ static int nilfs_set_page_dirty(struct page *page)
        return ret;
 }
 
+void nilfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               nilfs_truncate(inode);
+       }
+}
+
 static int nilfs_write_begin(struct file *file, struct address_space *mapping,
                             loff_t pos, unsigned len, unsigned flags,
                             struct page **pagep, void **fsdata)
@@ -227,10 +237,7 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
        err = block_write_begin(mapping, pos, len, flags, pagep,
                                nilfs_get_block);
        if (unlikely(err)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-
+               nilfs_write_failed(mapping, pos + len);
                nilfs_transaction_abort(inode->i_sb);
        }
        return err;
@@ -259,6 +266,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
        struct inode *inode = file->f_mapping->host;
        ssize_t size;
 
@@ -278,7 +286,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                loff_t end = offset + iov_length(iov, nr_segs);
 
                if (end > isize)
-                       vmtruncate(inode, isize);
+                       nilfs_write_failed(mapping, end);
        }
 
        return size;
@@ -786,10 +794,8 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
        if ((iattr->ia_valid & ATTR_SIZE) &&
            iattr->ia_size != i_size_read(inode)) {
                inode_dio_wait(inode);
-
-               err = vmtruncate(inode, iattr->ia_size);
-               if (unlikely(err))
-                       goto out_err;
+               truncate_setsize(inode, iattr->ia_size);
+               nilfs_truncate(inode);
        }
 
        setattr_copy(inode, iattr);
index fdb180769485f95c78a0a5b5f33d5752baf0590f..f3859354e41a97afcdb1c4f8fdec4d9e46f09666 100644 (file)
@@ -664,8 +664,11 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
        if (ret < 0)
                printk(KERN_ERR "NILFS: GC failed during preparation: "
                        "cannot read source blocks: err=%d\n", ret);
-       else
+       else {
+               if (nilfs_sb_need_update(nilfs))
+                       set_nilfs_discontinued(nilfs);
                ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
+       }
 
        nilfs_remove_all_gcinodes(nilfs);
        clear_nilfs_gc_running(nilfs);
index 74cece80e9a32c302e8a7f433234d4b196914adf..9bc72dec3fa69afb83bc4d0d952be494d4af2f23 100644 (file)
@@ -277,6 +277,7 @@ extern void nilfs_update_inode(struct inode *, struct buffer_head *);
 extern void nilfs_truncate(struct inode *);
 extern void nilfs_evict_inode(struct inode *);
 extern int nilfs_setattr(struct dentry *, struct iattr *);
+extern void nilfs_write_failed(struct address_space *mapping, loff_t to);
 int nilfs_permission(struct inode *inode, int mask);
 int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh);
 extern int nilfs_inode_dirty(struct inode *);
index f1626f5011c50d53c77bf478577ed98d30cc0ead..ff00a0b7acb927ee18a9dba898aac5cf55b2def5 100644 (file)
@@ -527,7 +527,8 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
                if (unlikely(err)) {
                        loff_t isize = inode->i_size;
                        if (pos + blocksize > isize)
-                               vmtruncate(inode, isize);
+                               nilfs_write_failed(inode->i_mapping,
+                                                       pos + blocksize);
                        goto failed_inode;
                }
 
index 3344bdd5506e3f06259efb7f176e0263764fc2dd..08b886f119ce49cd0232f954b775be71e76ae736 100644 (file)
@@ -201,7 +201,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
 
        /* nothing else could have found us thanks to the dnotify_mark_mutex */
        if (dn_mark->dn == NULL)
-               fsnotify_destroy_mark(fsn_mark);
+               fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
        mutex_unlock(&dnotify_mark_mutex);
 
@@ -385,7 +385,7 @@ out:
        spin_unlock(&fsn_mark->lock);
 
        if (destroy)
-               fsnotify_destroy_mark(fsn_mark);
+               fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
        mutex_unlock(&dnotify_mark_mutex);
        fsnotify_put_mark(fsn_mark);
index a50636025364214176fe7cec0cb80757ddc27171..0c2f9122b262da54392c8ed90a5a9d94ea22719c 100644 (file)
@@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
            old->tgid == new->tgid) {
                switch (old->data_type) {
                case (FSNOTIFY_EVENT_PATH):
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+                       /* dont merge two permission events */
+                       if ((old->mask & FAN_ALL_PERM_EVENTS) &&
+                           (new->mask & FAN_ALL_PERM_EVENTS))
+                               return false;
+#endif
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
index a5cd9bba022f4619021ddc0ef659e59b4a88e656..9ff4a5ee6e208fcccac9f3dc6393be18ffac3e1b 100644 (file)
@@ -397,8 +397,12 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        wake_up(&group->fanotify_data.access_waitq);
 #endif
+
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
+
        /* matches the fanotify_init->fsnotify_alloc_group */
-       fsnotify_put_group(group);
+       fsnotify_destroy_group(group);
 
        return 0;
 }
@@ -493,7 +497,8 @@ out:
 
 static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
                                            __u32 mask,
-                                           unsigned int flags)
+                                           unsigned int flags,
+                                           int *destroy)
 {
        __u32 oldmask;
 
@@ -507,8 +512,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
        }
        spin_unlock(&fsn_mark->lock);
 
-       if (!(oldmask & ~mask))
-               fsnotify_destroy_mark(fsn_mark);
+       *destroy = !(oldmask & ~mask);
 
        return mask & oldmask;
 }
@@ -519,12 +523,17 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
+       int destroy_mark;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+                                                &destroy_mark);
+       if (destroy_mark)
+               fsnotify_destroy_mark(fsn_mark, group);
+
        fsnotify_put_mark(fsn_mark);
        if (removed & real_mount(mnt)->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
@@ -538,12 +547,16 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
+       int destroy_mark;
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+                                                &destroy_mark);
+       if (destroy_mark)
+               fsnotify_destroy_mark(fsn_mark, group);
        /* matches the fsnotify_find_inode_mark() */
        fsnotify_put_mark(fsn_mark);
        if (removed & inode->i_fsnotify_mask)
@@ -710,13 +723,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
                break;
        default:
                fd = -EINVAL;
-               goto out_put_group;
+               goto out_destroy_group;
        }
 
        if (flags & FAN_UNLIMITED_QUEUE) {
                fd = -EPERM;
                if (!capable(CAP_SYS_ADMIN))
-                       goto out_put_group;
+                       goto out_destroy_group;
                group->max_events = UINT_MAX;
        } else {
                group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
@@ -725,7 +738,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        if (flags & FAN_UNLIMITED_MARKS) {
                fd = -EPERM;
                if (!capable(CAP_SYS_ADMIN))
-                       goto out_put_group;
+                       goto out_destroy_group;
                group->fanotify_data.max_marks = UINT_MAX;
        } else {
                group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
@@ -733,12 +746,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
        if (fd < 0)
-               goto out_put_group;
+               goto out_destroy_group;
 
        return fd;
 
-out_put_group:
-       fsnotify_put_group(group);
+out_destroy_group:
+       fsnotify_destroy_group(group);
        return fd;
 }
 
index 514c4b81483d618adda933b5e63b93bb9e529324..238a5930cb3c7d16e1c76952e66c6bf24f5299ae 100644 (file)
@@ -27,13 +27,13 @@ static int show_fdinfo(struct seq_file *m, struct file *f,
        struct fsnotify_mark *mark;
        int ret = 0;
 
-       spin_lock(&group->mark_lock);
+       mutex_lock(&group->mark_mutex);
        list_for_each_entry(mark, &group->marks_list, g_list) {
                ret = show(m, mark);
                if (ret)
                        break;
        }
-       spin_unlock(&group->mark_lock);
+       mutex_unlock(&group->mark_mutex);
        return ret;
 }
 
index 63fc294a469268d06d9ae1cc9f3d19f3ba95f695..bd2625bd88b47a7b2961ec0d43b77f5675a80ad6 100644 (file)
@@ -33,9 +33,6 @@
  */
 void fsnotify_final_destroy_group(struct fsnotify_group *group)
 {
-       /* clear the notification queue of all events */
-       fsnotify_flush_notify(group);
-
        if (group->ops->free_group_priv)
                group->ops->free_group_priv(group);
 
@@ -43,23 +40,30 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group)
 }
 
 /*
- * Trying to get rid of a group.  We need to first get rid of any outstanding
- * allocations and then free the group.  Remember that fsnotify_clear_marks_by_group
- * could miss marks that are being freed by inode and those marks could still
- * hold a reference to this group (via group->num_marks)  If we get into that
- * situtation, the fsnotify_final_destroy_group will get called when that final
- * mark is freed.
+ * Trying to get rid of a group. Remove all marks, flush all events and release
+ * the group reference.
+ * Note that another thread calling fsnotify_clear_marks_by_group() may still
+ * hold a ref to the group.
  */
-static void fsnotify_destroy_group(struct fsnotify_group *group)
+void fsnotify_destroy_group(struct fsnotify_group *group)
 {
        /* clear all inode marks for this group */
        fsnotify_clear_marks_by_group(group);
 
        synchronize_srcu(&fsnotify_mark_srcu);
 
-       /* past the point of no return, matches the initial value of 1 */
-       if (atomic_dec_and_test(&group->num_marks))
-               fsnotify_final_destroy_group(group);
+       /* clear the notification queue of all events */
+       fsnotify_flush_notify(group);
+
+       fsnotify_put_group(group);
+}
+
+/*
+ * Get reference to a group.
+ */
+void fsnotify_get_group(struct fsnotify_group *group)
+{
+       atomic_inc(&group->refcnt);
 }
 
 /*
@@ -68,7 +72,7 @@ static void fsnotify_destroy_group(struct fsnotify_group *group)
 void fsnotify_put_group(struct fsnotify_group *group)
 {
        if (atomic_dec_and_test(&group->refcnt))
-               fsnotify_destroy_group(group);
+               fsnotify_final_destroy_group(group);
 }
 
 /*
@@ -84,21 +88,24 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 
        /* set to 0 when there a no external references to this group */
        atomic_set(&group->refcnt, 1);
-       /*
-        * hits 0 when there are no external references AND no marks for
-        * this group
-        */
-       atomic_set(&group->num_marks, 1);
+       atomic_set(&group->num_marks, 0);
 
        mutex_init(&group->notification_mutex);
        INIT_LIST_HEAD(&group->notification_list);
        init_waitqueue_head(&group->notification_waitq);
        group->max_events = UINT_MAX;
 
-       spin_lock_init(&group->mark_lock);
+       mutex_init(&group->mark_mutex);
        INIT_LIST_HEAD(&group->marks_list);
 
        group->ops = ops;
 
        return group;
 }
+
+int fsnotify_fasync(int fd, struct file *file, int on)
+{
+       struct fsnotify_group *group = file->private_data;
+
+       return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
+}
index f3035691f528db31f41eb8b6db034525b6619aaa..f31e90fc050d1edb282be6194f91812f66eeb3fa 100644 (file)
@@ -63,8 +63,8 @@ void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
 {
        struct inode *inode = mark->i.inode;
 
+       BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&mark->group->mark_lock);
 
        spin_lock(&inode->i_lock);
 
@@ -99,8 +99,16 @@ void fsnotify_clear_marks_by_inode(struct inode *inode)
        spin_unlock(&inode->i_lock);
 
        list_for_each_entry_safe(mark, lmark, &free_list, i.free_i_list) {
-               fsnotify_destroy_mark(mark);
+               struct fsnotify_group *group;
+
+               spin_lock(&mark->lock);
+               fsnotify_get_group(mark->group);
+               group = mark->group;
+               spin_unlock(&mark->lock);
+
+               fsnotify_destroy_mark(mark, group);
                fsnotify_put_mark(mark);
+               fsnotify_put_group(group);
        }
 }
 
@@ -192,8 +200,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 
        mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
 
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&group->mark_lock);
 
        spin_lock(&inode->i_lock);
 
index e3cbd746f64a5eb4ac9359cf8a3f271a6da8a332..871569c7d609360688c229e1357d3610e44841d0 100644 (file)
@@ -118,6 +118,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
 
        fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+       fsnotify_get_group(group);
        fsn_event_priv->group = group;
        event_priv->wd = wd;
 
@@ -131,7 +132,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
        }
 
        if (inode_mark->mask & IN_ONESHOT)
-               fsnotify_destroy_mark(inode_mark);
+               fsnotify_destroy_mark(inode_mark, group);
 
        return ret;
 }
@@ -210,6 +211,7 @@ void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
        event_priv = container_of(fsn_event_priv, struct inotify_event_private_data,
                                  fsnotify_event_priv_data);
 
+       fsnotify_put_group(fsn_event_priv->group);
        kmem_cache_free(event_priv_cachep, event_priv);
 }
 
index 36cb013c7c13e7972405c2f7df81120770c3fdd0..228a2c2ad8d7e4abb953dd9f094fb762d97d6668 100644 (file)
@@ -265,7 +265,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
                ret = -EAGAIN;
                if (file->f_flags & O_NONBLOCK)
                        break;
-               ret = -EINTR;
+               ret = -ERESTARTSYS;
                if (signal_pending(current))
                        break;
 
@@ -281,23 +281,17 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static int inotify_fasync(int fd, struct file *file, int on)
-{
-       struct fsnotify_group *group = file->private_data;
-
-       return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
-}
-
 static int inotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
 
        pr_debug("%s: group=%p\n", __func__, group);
 
-       fsnotify_clear_marks_by_group(group);
+       if (file->f_flags & FASYNC)
+               fsnotify_fasync(-1, file, 0);
 
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
-       fsnotify_put_group(group);
+       fsnotify_destroy_group(group);
 
        return 0;
 }
@@ -339,7 +333,7 @@ static const struct file_operations inotify_fops = {
        .show_fdinfo    = inotify_show_fdinfo,
        .poll           = inotify_poll,
        .read           = inotify_read,
-       .fasync         = inotify_fasync,
+       .fasync         = fsnotify_fasync,
        .release        = inotify_release,
        .unlocked_ioctl = inotify_ioctl,
        .compat_ioctl   = inotify_ioctl,
@@ -521,13 +515,13 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
        struct fsnotify_event_private_data *fsn_event_priv;
        int ret;
 
+       i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+
        ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
                                              FSNOTIFY_EVENT_NONE, NULL, 0,
                                              GFP_NOFS);
        if (!ignored_event)
-               return;
-
-       i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+               goto skip_send_ignore;
 
        event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS);
        if (unlikely(!event_priv))
@@ -535,6 +529,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
        fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+       fsnotify_get_group(group);
        fsn_event_priv->group = group;
        event_priv->wd = i_mark->wd;
 
@@ -548,9 +543,9 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
        }
 
 skip_send_ignore:
-
        /* matches the reference taken when the event was created */
-       fsnotify_put_event(ignored_event);
+       if (ignored_event)
+               fsnotify_put_event(ignored_event);
 
        /* remove this mark from the idr */
        inotify_remove_from_idr(group, i_mark);
@@ -709,12 +704,11 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
        spin_lock_init(&group->inotify_data.idr_lock);
        idr_init(&group->inotify_data.idr);
        group->inotify_data.last_wd = 0;
-       group->inotify_data.fa = NULL;
        group->inotify_data.user = get_current_user();
 
        if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
            inotify_max_user_instances) {
-               fsnotify_put_group(group);
+               fsnotify_destroy_group(group);
                return ERR_PTR(-EMFILE);
        }
 
@@ -743,7 +737,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        ret = anon_inode_getfd("inotify", &inotify_fops, group,
                                  O_RDONLY | flags);
        if (ret < 0)
-               fsnotify_put_group(group);
+               fsnotify_destroy_group(group);
 
        return ret;
 }
@@ -819,7 +813,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
 
        ret = 0;
 
-       fsnotify_destroy_mark(&i_mark->fsn_mark);
+       fsnotify_destroy_mark(&i_mark->fsn_mark, group);
 
        /* match ref taken by inotify_idr_find */
        fsnotify_put_mark(&i_mark->fsn_mark);
index f104d565b6823aa75ab39c5c0717e9e3fd9382f3..fc6b49bf73600c2aad93e802865512b692a7cc24 100644 (file)
@@ -109,8 +109,11 @@ void fsnotify_get_mark(struct fsnotify_mark *mark)
 
 void fsnotify_put_mark(struct fsnotify_mark *mark)
 {
-       if (atomic_dec_and_test(&mark->refcnt))
+       if (atomic_dec_and_test(&mark->refcnt)) {
+               if (mark->group)
+                       fsnotify_put_group(mark->group);
                mark->free_mark(mark);
+       }
 }
 
 /*
@@ -118,14 +121,14 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
  * The caller had better be holding a reference to this mark so we don't actually
  * do the final put under the mark->lock
  */
-void fsnotify_destroy_mark(struct fsnotify_mark *mark)
+void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+                                 struct fsnotify_group *group)
 {
-       struct fsnotify_group *group;
        struct inode *inode = NULL;
 
-       spin_lock(&mark->lock);
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
-       group = mark->group;
+       spin_lock(&mark->lock);
 
        /* something else already called this function on this mark */
        if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
@@ -135,8 +138,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
        mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
 
-       spin_lock(&group->mark_lock);
-
        if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
                inode = mark->i.inode;
                fsnotify_destroy_inode_mark(mark);
@@ -147,13 +148,22 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
        list_del_init(&mark->g_list);
 
-       spin_unlock(&group->mark_lock);
        spin_unlock(&mark->lock);
 
+       if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
+               iput(inode);
+       /* release lock temporarily */
+       mutex_unlock(&group->mark_mutex);
+
        spin_lock(&destroy_lock);
        list_add(&mark->destroy_list, &destroy_list);
        spin_unlock(&destroy_lock);
        wake_up(&destroy_waitq);
+       /*
+        * We don't necessarily have a ref on mark from caller so the above destroy
+        * may have actually freed it, unless this group provides a 'freeing_mark'
+        * function which must be holding a reference.
+        */
 
        /*
         * Some groups like to know that marks are being freed.  This is a
@@ -175,21 +185,17 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
         * is just a lazy update (and could be a perf win...)
         */
 
-       if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
-               iput(inode);
+       atomic_dec(&group->num_marks);
 
-       /*
-        * We don't necessarily have a ref on mark from caller so the above iput
-        * may have already destroyed it.  Don't touch from now on.
-        */
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+}
 
-       /*
-        * it's possible that this group tried to destroy itself, but this
-        * this mark was simultaneously being freed by inode.  If that's the
-        * case, we finish freeing the group here.
-        */
-       if (unlikely(atomic_dec_and_test(&group->num_marks)))
-               fsnotify_final_destroy_group(group);
+void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+                          struct fsnotify_group *group)
+{
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+       fsnotify_destroy_mark_locked(mark, group);
+       mutex_unlock(&group->mark_mutex);
 }
 
 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
@@ -214,26 +220,26 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas
  * These marks may be used for the fsnotify backend to determine which
  * event types should be delivered to which group.
  */
-int fsnotify_add_mark(struct fsnotify_mark *mark,
-                     struct fsnotify_group *group, struct inode *inode,
-                     struct vfsmount *mnt, int allow_dups)
+int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
+                            struct fsnotify_group *group, struct inode *inode,
+                            struct vfsmount *mnt, int allow_dups)
 {
        int ret = 0;
 
        BUG_ON(inode && mnt);
        BUG_ON(!inode && !mnt);
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
        /*
         * LOCKING ORDER!!!!
+        * group->mark_mutex
         * mark->lock
-        * group->mark_lock
         * inode->i_lock
         */
        spin_lock(&mark->lock);
-       spin_lock(&group->mark_lock);
-
        mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
 
+       fsnotify_get_group(group);
        mark->group = group;
        list_add(&mark->g_list, &group->marks_list);
        atomic_inc(&group->num_marks);
@@ -251,11 +257,8 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
                BUG();
        }
 
-       spin_unlock(&group->mark_lock);
-
        /* this will pin the object if appropriate */
        fsnotify_set_mark_mask_locked(mark, mark->mask);
-
        spin_unlock(&mark->lock);
 
        if (inode)
@@ -265,10 +268,10 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 err:
        mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
        list_del_init(&mark->g_list);
+       fsnotify_put_group(group);
        mark->group = NULL;
        atomic_dec(&group->num_marks);
 
-       spin_unlock(&group->mark_lock);
        spin_unlock(&mark->lock);
 
        spin_lock(&destroy_lock);
@@ -279,6 +282,16 @@ err:
        return ret;
 }
 
+int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
+                     struct inode *inode, struct vfsmount *mnt, int allow_dups)
+{
+       int ret;
+       mutex_lock(&group->mark_mutex);
+       ret = fsnotify_add_mark_locked(mark, group, inode, mnt, allow_dups);
+       mutex_unlock(&group->mark_mutex);
+       return ret;
+}
+
 /*
  * clear any marks in a group in which mark->flags & flags is true
  */
@@ -286,22 +299,16 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
                                         unsigned int flags)
 {
        struct fsnotify_mark *lmark, *mark;
-       LIST_HEAD(free_list);
 
-       spin_lock(&group->mark_lock);
+       mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
        list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
                if (mark->flags & flags) {
-                       list_add(&mark->free_g_list, &free_list);
-                       list_del_init(&mark->g_list);
                        fsnotify_get_mark(mark);
+                       fsnotify_destroy_mark_locked(mark, group);
+                       fsnotify_put_mark(mark);
                }
        }
-       spin_unlock(&group->mark_lock);
-
-       list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) {
-               fsnotify_destroy_mark(mark);
-               fsnotify_put_mark(mark);
-       }
+       mutex_unlock(&group->mark_mutex);
 }
 
 /*
@@ -317,6 +324,8 @@ void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *ol
        assert_spin_locked(&old->lock);
        new->i.inode = old->i.inode;
        new->m.mnt = old->m.mnt;
+       if (old->group)
+               fsnotify_get_group(old->group);
        new->group = old->group;
        new->mask = old->mask;
        new->free_mark = old->free_mark;
index 48cb994e4922cf0d32fb3f61ad1eb05291231a7c..7b51b05f160c36846e47a8f1b7cb417bed9ed914 100644 (file)
@@ -225,6 +225,7 @@ alloc_holder:
        mutex_unlock(&group->notification_mutex);
 
        wake_up(&group->notification_waitq);
+       kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
        return return_event;
 }
 
index b7b4b0e8554fb1e8ab6948f2efd35704ed156e56..4df58b8ea64a97d562f0701f4061152ed0f02fc2 100644 (file)
@@ -46,8 +46,16 @@ void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
        spin_unlock(&mnt->mnt_root->d_lock);
 
        list_for_each_entry_safe(mark, lmark, &free_list, m.free_m_list) {
-               fsnotify_destroy_mark(mark);
+               struct fsnotify_group *group;
+
+               spin_lock(&mark->lock);
+               fsnotify_get_group(mark->group);
+               group = mark->group;
+               spin_unlock(&mark->lock);
+
+               fsnotify_destroy_mark(mark, group);
                fsnotify_put_mark(mark);
+               fsnotify_put_group(group);
        }
 }
 
@@ -88,8 +96,8 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
 {
        struct vfsmount *mnt = mark->m.mnt;
 
+       BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&mark->group->mark_lock);
 
        spin_lock(&mnt->mnt_root->d_lock);
 
@@ -151,8 +159,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
 
        mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 
+       BUG_ON(!mutex_is_locked(&group->mark_mutex));
        assert_spin_locked(&mark->lock);
-       assert_spin_locked(&group->mark_lock);
 
        spin_lock(&mnt->mnt_root->d_lock);
 
index 1ecf46448f858d477c040e313989cc9116315124..5b2d4f0853acfad180c03d9c10764b3199e31089 100644 (file)
@@ -1762,6 +1762,16 @@ err_out:
        return err;
 }
 
+static void ntfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               ntfs_truncate_vfs(inode);
+       }
+}
+
 /**
  * ntfs_file_buffered_write -
  *
@@ -2022,8 +2032,9 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                                 * allocated space, which is not a disaster.
                                 */
                                i_size = i_size_read(vi);
-                               if (pos + bytes > i_size)
-                                       vmtruncate(vi, i_size);
+                               if (pos + bytes > i_size) {
+                                       ntfs_write_failed(mapping, pos + bytes);
+                               }
                                break;
                        }
                }
@@ -2227,7 +2238,6 @@ const struct file_operations ntfs_file_ops = {
 
 const struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
-       .truncate       = ntfs_truncate_vfs,
        .setattr        = ntfs_setattr,
 #endif /* NTFS_RW */
 };
index 1d27331e6fc945ee1ddba591d47ddf1ef1bafbd1..d3e118cc6ffa8f0016c5eb93e246aded38a1cc14 100644 (file)
@@ -2866,9 +2866,11 @@ conv_err_out:
  *
  * See ntfs_truncate() description above for details.
  */
+#ifdef NTFS_RW
 void ntfs_truncate_vfs(struct inode *vi) {
        ntfs_truncate(vi);
 }
+#endif
 
 /**
  * ntfs_setattr - called from notify_change() when an attribute is being changed
@@ -2914,8 +2916,10 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
                                                NInoCompressed(ni) ?
                                                "compressed" : "encrypted");
                                err = -EOPNOTSUPP;
-                       } else
-                               err = vmtruncate(vi, attr->ia_size);
+                       } else {
+                               truncate_setsize(vi, attr->ia_size);
+                               ntfs_truncate_vfs(vi);
+                       }
                        if (err || ia_valid == ATTR_SIZE)
                                goto out;
                } else {
index db29695f845ce6d448aa44308c487342a4356142..76b6cfb579d73944fff234df3999a19a9e002e51 100644 (file)
@@ -316,6 +316,10 @@ static inline void ntfs_commit_inode(struct inode *vi)
        return;
 }
 
+#else
+
+static inline void ntfs_truncate_vfs(struct inode *vi) {}
+
 #endif /* NTFS_RW */
 
 #endif /* _LINUX_NTFS_INODE_H */
index fe492e1a3cfcaa7189ccdd61075d890673231ceb..37d313ede159bdb457667ceacc18fba18cb3999d 100644 (file)
@@ -1218,24 +1218,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                }
        }
 
-       /*
-        * This will intentionally not wind up calling truncate_setsize(),
-        * since all the work for a size change has been done above.
-        * Otherwise, we could get into problems with truncate as
-        * ip_alloc_sem is used there to protect against i_size
-        * changes.
-        *
-        * XXX: this means the conditional below can probably be removed.
-        */
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               status = vmtruncate(inode, attr->ia_size);
-               if (status) {
-                       mlog_errno(status);
-                       goto bail_commit;
-               }
-       }
-
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
 
index 77e3cb2962b46e58a982cce170e9716dfc8880df..e0d9b3e722bd41f91cf4b58f76aa1f34e2684149 100644 (file)
@@ -306,6 +306,16 @@ omfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
        return mpage_writepages(mapping, wbc, omfs_get_block);
 }
 
+static void omfs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               omfs_truncate(inode);
+       }
+}
+
 static int omfs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -314,11 +324,8 @@ static int omfs_write_begin(struct file *file, struct address_space *mapping,
 
        ret = block_write_begin(mapping, pos, len, flags, pagep,
                                omfs_get_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               omfs_write_failed(mapping, pos + len);
 
        return ret;
 }
@@ -350,9 +357,11 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        return error;
+               truncate_setsize(inode, attr->ia_size);
+               omfs_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -362,7 +371,6 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
 
 const struct inode_operations omfs_file_inops = {
        .setattr = omfs_setattr,
-       .truncate = omfs_truncate
 };
 
 const struct address_space_operations omfs_aops = {
index 182d8667b7bd57f5c3c6f738dcdeed0b18c0cbe6..9b33c0cbfacf3dffc3f67df9247a838505aa0d6d 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
        return ret;
 }
 
-static long do_sys_truncate(const char __user *pathname, loff_t length)
+long vfs_truncate(struct path *path, loff_t length)
 {
-       struct path path;
        struct inode *inode;
-       int error;
-
-       error = -EINVAL;
-       if (length < 0) /* sorry, but loff_t says... */
-               goto out;
+       long error;
 
-       error = user_path(pathname, &path);
-       if (error)
-               goto out;
-       inode = path.dentry->d_inode;
+       inode = path->dentry->d_inode;
 
        /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
-       error = -EISDIR;
        if (S_ISDIR(inode->i_mode))
-               goto dput_and_out;
-
-       error = -EINVAL;
+               return -EISDIR;
        if (!S_ISREG(inode->i_mode))
-               goto dput_and_out;
+               return -EINVAL;
 
-       error = mnt_want_write(path.mnt);
+       error = mnt_want_write(path->mnt);
        if (error)
-               goto dput_and_out;
+               goto out;
 
        error = inode_permission(inode, MAY_WRITE);
        if (error)
@@ -111,19 +100,40 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
 
        error = locks_verify_truncate(inode, NULL, length);
        if (!error)
-               error = security_path_truncate(&path);
+               error = security_path_truncate(path);
        if (!error)
-               error = do_truncate(path.dentry, length, 0, NULL);
+               error = do_truncate(path->dentry, length, 0, NULL);
 
 put_write_and_out:
        put_write_access(inode);
 mnt_drop_write_and_out:
-       mnt_drop_write(path.mnt);
-dput_and_out:
-       path_put(&path);
+       mnt_drop_write(path->mnt);
 out:
        return error;
 }
+EXPORT_SYMBOL_GPL(vfs_truncate);
+
+static long do_sys_truncate(const char __user *pathname, loff_t length)
+{
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+       struct path path;
+       int error;
+
+       if (length < 0) /* sorry, but loff_t says... */
+               return -EINVAL;
+
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
+       if (!error) {
+               error = vfs_truncate(&path, length);
+               path_put(&path);
+       }
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
+       return error;
+}
 
 SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
 {
@@ -306,6 +316,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
        struct path path;
        struct inode *inode;
        int res;
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
 
        if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
                return -EINVAL;
@@ -328,8 +339,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
        }
 
        old_cred = override_creds(override_cred);
-
-       res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+retry:
+       res = user_path_at(dfd, filename, lookup_flags, &path);
        if (res)
                goto out;
 
@@ -364,6 +375,10 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
 
 out_path_release:
        path_put(&path);
+       if (retry_estale(res, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        revert_creds(old_cred);
        put_cred(override_cred);
@@ -379,8 +394,9 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename)
 {
        struct path path;
        int error;
-
-       error = user_path_dir(filename, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+retry:
+       error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
        if (error)
                goto out;
 
@@ -392,6 +408,10 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename)
 
 dput_and_out:
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        return error;
 }
@@ -425,8 +445,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 {
        struct path path;
        int error;
-
-       error = user_path_dir(filename, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+retry:
+       error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
        if (error)
                goto out;
 
@@ -445,6 +466,10 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
        error = 0;
 dput_and_out:
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        return error;
 }
@@ -489,11 +514,16 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode
 {
        struct path path;
        int error;
-
-       error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+retry:
+       error = user_path_at(dfd, filename, lookup_flags, &path);
        if (!error) {
                error = chmod_common(&path, mode);
                path_put(&path);
+               if (retry_estale(error, lookup_flags)) {
+                       lookup_flags |= LOOKUP_REVAL;
+                       goto retry;
+               }
        }
        return error;
 }
@@ -552,6 +582,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
        lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
        if (flag & AT_EMPTY_PATH)
                lookup_flags |= LOOKUP_EMPTY;
+retry:
        error = user_path_at(dfd, filename, lookup_flags, &path);
        if (error)
                goto out;
@@ -562,6 +593,10 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
        mnt_drop_write(path.mnt);
 out_release:
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        return error;
 }
index 6a91e6ffbcbded857c4513cee0182ec61f899b74..f7ed9ee46eb9d3818d2210c100731e5eda6ee35e 100644 (file)
@@ -449,7 +449,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                        do {
                                min_flt += t->min_flt;
                                maj_flt += t->maj_flt;
-                               gtime += t->gtime;
+                               gtime += task_gtime(t);
                                t = next_thread(t);
                        } while (t != task);
 
@@ -472,7 +472,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                min_flt = task->min_flt;
                maj_flt = task->maj_flt;
                task_cputime_adjusted(task, &utime, &stime);
-               gtime = task->gtime;
+               gtime = task_gtime(task);
        }
 
        /* scale priority and nice values from timeslices to -20..20 */
index 5a5a0be40e405f4693bad85fcc7d04703b362523..9b43ff77a51ed3b0383f3e96489e1e542331555a 100644 (file)
@@ -542,13 +542,6 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
        if (error)
                return error;
 
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
-               if (error)
-                       return error;
-       }
-
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
        return 0;
index 7b3ae3cc0ef9ae34da5ece6dd63d550042e4b1b5..76ddae83daa58e2b086dd286c847c47de71f1124 100644 (file)
@@ -261,16 +261,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
        if (error)
                return error;
 
-       if ((iattr->ia_valid & ATTR_SIZE) &&
-           iattr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, iattr->ia_size);
-               if (error)
-                       return error;
-       }
-
        setattr_copy(inode, iattr);
        mark_inode_dirty(inode);
-       
+
        de->uid = inode->i_uid;
        de->gid = inode->i_gid;
        de->mode = inode->i_mode;
@@ -359,18 +352,18 @@ retry:
        if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
                return -ENOMEM;
 
-       spin_lock(&proc_inum_lock);
+       spin_lock_irq(&proc_inum_lock);
        error = ida_get_new(&proc_inum_ida, &i);
-       spin_unlock(&proc_inum_lock);
+       spin_unlock_irq(&proc_inum_lock);
        if (error == -EAGAIN)
                goto retry;
        else if (error)
                return error;
 
        if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
-               spin_lock(&proc_inum_lock);
+               spin_lock_irq(&proc_inum_lock);
                ida_remove(&proc_inum_ida, i);
-               spin_unlock(&proc_inum_lock);
+               spin_unlock_irq(&proc_inum_lock);
                return -ENOSPC;
        }
        *inum = PROC_DYNAMIC_FIRST + i;
@@ -379,9 +372,10 @@ retry:
 
 void proc_free_inum(unsigned int inum)
 {
-       spin_lock(&proc_inum_lock);
+       unsigned long flags;
+       spin_lock_irqsave(&proc_inum_lock, flags);
        ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
-       spin_unlock(&proc_inum_lock);
+       spin_unlock_irqrestore(&proc_inum_lock, flags);
 }
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
index 701580ddfcc3c20a4476fe88a9e736b54ca7b858..1827d88ad58b2ea1ec0fb7aa7f4ad7fdc3277fff 100644 (file)
@@ -736,13 +736,6 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
        if (error)
                return error;
 
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
-               if (error)
-                       return error;
-       }
-
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
        return 0;
index 448455b7fd910af4ff4cf1b530bde57d7d02e79d..ca5ce7f9f800934d0252598ec5491bed71dc581d 100644 (file)
@@ -1278,7 +1278,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        walk.mm = mm;
 
        pol = get_vma_policy(task, vma, vma->vm_start);
-       mpol_to_str(buffer, sizeof(buffer), pol, 0);
+       mpol_to_str(buffer, sizeof(buffer), pol);
        mpol_cond_put(pol);
 
        seq_printf(m, "%08lx %s", vma->vm_start, buffer);
index f883e7e74305c9935b2f26e27e92f01c7e138aa9..288f068740f6f6e2eb02dea57ed9a5ab1a8b47b8 100644 (file)
@@ -167,12 +167,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
 {
        char *hdr;
-       struct timeval timestamp;
+       struct timespec timestamp;
        size_t len;
 
-       do_gettimeofday(&timestamp);
+       /* Report zeroed timestamp if called before timekeeping has resumed. */
+       if (__getnstimeofday(&timestamp)) {
+               timestamp.tv_sec = 0;
+               timestamp.tv_nsec = 0;
+       }
        hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
-               (long)timestamp.tv_sec, (long)timestamp.tv_usec);
+               (long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000));
        WARN_ON_ONCE(!hdr);
        len = hdr ? strlen(hdr) : 0;
        persistent_ram_write(prz, hdr, len);
@@ -291,9 +295,8 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
        kfree(cxt->przs);
 }
 
-static int __devinit ramoops_init_przs(struct device *dev,
-                                      struct ramoops_context *cxt,
-                                      phys_addr_t *paddr, size_t dump_mem_sz)
+static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
+                            phys_addr_t *paddr, size_t dump_mem_sz)
 {
        int err = -ENOMEM;
        int i;
@@ -336,10 +339,9 @@ fail_prz:
        return err;
 }
 
-static int __devinit ramoops_init_prz(struct device *dev,
-                                     struct ramoops_context *cxt,
-                                     struct persistent_ram_zone **prz,
-                                     phys_addr_t *paddr, size_t sz, u32 sig)
+static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
+                           struct persistent_ram_zone **prz,
+                           phys_addr_t *paddr, size_t sz, u32 sig)
 {
        if (!sz)
                return 0;
@@ -367,7 +369,7 @@ static int __devinit ramoops_init_prz(struct device *dev,
        return 0;
 }
 
-static int __devinit ramoops_probe(struct platform_device *pdev)
+static int ramoops_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ramoops_platform_data *pdata = pdev->dev.platform_data;
index eecd2a8a84dd1b586967f2c785caf2caee2bc68d..0306303be372d14edb8d46b546e7493f3520ca3e 100644 (file)
@@ -390,8 +390,8 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
        return 0;
 }
 
-static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
-                                             u32 sig, int ecc_size)
+static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
+                                   int ecc_size)
 {
        int ret;
 
@@ -443,9 +443,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
        kfree(prz);
 }
 
-struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
-                                                         size_t size, u32 sig,
-                                                         int ecc_size)
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+                                              u32 sig, int ecc_size)
 {
        struct persistent_ram_zone *prz;
        int ret = -ENOMEM;
index 1edaf099ddd7f28d6dbeb41298269252773ecfa9..bb34af315280328acedfd4122829b3c8125d8a6f 100644 (file)
@@ -935,6 +935,8 @@ ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
        if (retval > 0) {
                add_rchar(current, retval);
                add_wchar(current, retval);
+               fsnotify_access(in.file);
+               fsnotify_modify(out.file);
        }
 
        inc_syscr(current);
index 8375c922c0d56d3467c3c654ef84306531299032..50302d6f889533b5e139d6083d43e475ca0155c5 100644 (file)
@@ -126,7 +126,7 @@ static int reiserfs_file_open(struct inode *inode, struct file *file)
        return err;
 }
 
-static void reiserfs_vfs_truncate_file(struct inode *inode)
+void reiserfs_vfs_truncate_file(struct inode *inode)
 {
        mutex_lock(&(REISERFS_I(inode)->tailpack));
        reiserfs_truncate_file(inode, 1);
@@ -312,7 +312,6 @@ const struct file_operations reiserfs_file_operations = {
 };
 
 const struct inode_operations reiserfs_file_inode_operations = {
-       .truncate = reiserfs_vfs_truncate_file,
        .setattr = reiserfs_setattr,
        .setxattr = reiserfs_setxattr,
        .getxattr = reiserfs_getxattr,
index d83736fbc26cb4679cf074ee33263f125f13afa7..95d7680ead47a8c6379629614eadb0fdbf233fe0 100644 (file)
@@ -3085,8 +3085,10 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
                loff_t isize = i_size_read(inode);
                loff_t end = offset + iov_length(iov, nr_segs);
 
-               if (end > isize)
-                       vmtruncate(inode, isize);
+               if ((end > isize) && inode_newsize_ok(inode, isize) == 0) {
+                       truncate_setsize(inode, isize);
+                       reiserfs_vfs_truncate_file(inode);
+               }
        }
 
        return ret;
@@ -3200,8 +3202,13 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
         */
        reiserfs_write_unlock_once(inode->i_sb, depth);
        if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode))
-               error = vmtruncate(inode, attr->ia_size);
+           attr->ia_size != i_size_read(inode)) {
+               error = inode_newsize_ok(inode, attr->ia_size);
+               if (!error) {
+                       truncate_setsize(inode, attr->ia_size);
+                       reiserfs_vfs_truncate_file(inode);
+               }
+       }
 
        if (!error) {
                setattr_copy(inode, attr);
index 33215f57ea06ce3026ef2d488832a337a361bd71..157e474ab30347cde97360a4c94de73b5aff2164 100644 (file)
@@ -2455,6 +2455,7 @@ struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct
                                                                    *,
                                                                    int count);
 int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *);
+void reiserfs_vfs_truncate_file(struct inode *inode);
 int reiserfs_commit_page(struct inode *inode, struct page *page,
                         unsigned from, unsigned to);
 void reiserfs_flush_old_commits(struct super_block *);
index 2ef72d9650365c71586592a9c456785b7094a59b..8c1c96c27062a504bfc151f33d335fcd8f6779b5 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/fs.h>
 #include <linux/rcupdate.h>
 #include <linux/hrtimer.h>
+#include <linux/sched/rt.h>
 
 #include <asm/uaccess.h>
 
index 9d863fb501f92ab9a9207fcce7d8b2087c637c0e..f2bc3dfd0b883585e1a2afe6734de2db6be77004 100644 (file)
@@ -296,7 +296,7 @@ EXPORT_SYMBOL(seq_read);
  *     seq_lseek -     ->llseek() method for sequential files.
  *     @file: the file in question
  *     @offset: new position
- *     @origin: 0 for absolute, 1 for relative position
+ *     @whence: 0 for absolute, 1 for relative position
  *
  *     Ready-made ->f_op->llseek()
  */
index 8890604e3fcdd638d6d150ffbfc981a783467dfe..6909d89d0da56ffd929a2114b0228a03d1f35589 100644 (file)
@@ -696,8 +696,10 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
                return -EINVAL;
 
        more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0;
-       if (sd->len < sd->total_len)
+
+       if (sd->len < sd->total_len && pipe->nrbufs > 1)
                more |= MSG_SENDPAGE_NOTLAST;
+
        return file->f_op->sendpage(file, buf->page, buf->offset,
                                    sd->len, &pos, more);
 }
index eae494630a36507e03defe8bdf836ee6b337b4ee..14f45459c83d650fb09c4069d5dd7db907a67b95 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -74,7 +74,7 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
 {
        struct path path;
        int error = -EINVAL;
-       int lookup_flags = 0;
+       unsigned int lookup_flags = 0;
 
        if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
                      AT_EMPTY_PATH)) != 0)
@@ -84,13 +84,17 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
                lookup_flags |= LOOKUP_FOLLOW;
        if (flag & AT_EMPTY_PATH)
                lookup_flags |= LOOKUP_EMPTY;
-
+retry:
        error = user_path_at(dfd, filename, lookup_flags, &path);
        if (error)
                goto out;
 
        error = vfs_getattr(path.mnt, path.dentry, stat);
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 out:
        return error;
 }
@@ -296,11 +300,13 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
        struct path path;
        int error;
        int empty = 0;
+       unsigned int lookup_flags = LOOKUP_EMPTY;
 
        if (bufsiz <= 0)
                return -EINVAL;
 
-       error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty);
+retry:
+       error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
        if (!error) {
                struct inode *inode = path.dentry->d_inode;
 
@@ -314,6 +320,10 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
                        }
                }
                path_put(&path);
+               if (retry_estale(error, lookup_flags)) {
+                       lookup_flags |= LOOKUP_REVAL;
+                       goto retry;
+               }
        }
        return error;
 }
index f8e832e6f0a2220d0e16163b230ad0f710ee4132..c219e733f55330741962173e994ac8d4e894a70f 100644 (file)
@@ -77,10 +77,17 @@ EXPORT_SYMBOL(vfs_statfs);
 int user_statfs(const char __user *pathname, struct kstatfs *st)
 {
        struct path path;
-       int error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+       int error;
+       unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (!error) {
                error = vfs_statfs(&path, st);
                path_put(&path);
+               if (retry_estale(error, lookup_flags)) {
+                       lookup_flags |= LOOKUP_REVAL;
+                       goto retry;
+               }
        }
        return error;
 }
index 0a65939508e964f609b6e5ab7432cc2e177a45ad..9d4dc6831792a23270148c2d26b0423f656b505c 100644 (file)
@@ -41,9 +41,11 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            attr->ia_size != i_size_read(inode)) {
-               error = vmtruncate(inode, attr->ia_size);
+               error = inode_newsize_ok(inode, attr->ia_size);
                if (error)
                        return error;
+               truncate_setsize(inode, attr->ia_size);
+               sysv_truncate(inode);
        }
 
        setattr_copy(inode, attr);
@@ -52,7 +54,6 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
 }
 
 const struct inode_operations sysv_file_inode_operations = {
-       .truncate       = sysv_truncate,
        .setattr        = sysv_setattr,
        .getattr        = sysv_getattr,
 };
index 90b54b438789664b555931f07b42e1d356396e07..c1a591a4725b0ba4344862f97e7ab2c72de974f6 100644 (file)
@@ -464,6 +464,16 @@ int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len)
        return __block_write_begin(page, pos, len, get_block);
 }
 
+static void sysv_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               sysv_truncate(inode);
+       }
+}
+
 static int sysv_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -471,11 +481,8 @@ static int sysv_write_begin(struct file *file, struct address_space *mapping,
        int ret;
 
        ret = block_write_begin(mapping, pos, len, flags, pagep, get_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               sysv_write_failed(mapping, pos + len);
 
        return ret;
 }
index d44fb568abe1a945c014a03c88648cd847906cc0..e9be396a558d944fde7086cce64d22c672cdc5b7 100644 (file)
@@ -307,7 +307,8 @@ static void udf_sb_free_partitions(struct super_block *sb)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        int i;
-
+       if (sbi->s_partmaps == NULL)
+               return;
        for (i = 0; i < sbi->s_partitions; i++)
                udf_free_partition(&sbi->s_partmaps[i]);
        kfree(sbi->s_partmaps);
index eb6d0b7dc8791bc580393dd18ea621582ab8f296..ff24e4449ece0184436a179b1815571f2da87e10 100644 (file)
@@ -526,6 +526,14 @@ int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
        return __block_write_begin(page, pos, len, ufs_getfrag_block);
 }
 
+static void ufs_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size)
+               truncate_pagecache(inode, to, inode->i_size);
+}
+
 static int ufs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
@@ -534,11 +542,8 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping,
 
        ret = block_write_begin(mapping, pos, len, flags, pagep,
                                ufs_getfrag_block);
-       if (unlikely(ret)) {
-               loff_t isize = mapping->host->i_size;
-               if (pos + len > isize)
-                       vmtruncate(mapping->host, isize);
-       }
+       if (unlikely(ret))
+               ufs_write_failed(mapping, pos + len);
 
        return ret;
 }
index bb0696a41735608512963ae1648a79a9d7b0bd27..f4fb7eca10e832f5b9c4405092627b94f4a163dc 100644 (file)
@@ -158,13 +158,17 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,
 
                if (!(flags & AT_SYMLINK_NOFOLLOW))
                        lookup_flags |= LOOKUP_FOLLOW;
-
+retry:
                error = user_path_at(dfd, filename, lookup_flags, &path);
                if (error)
                        goto out;
 
                error = utimes_common(&path, times);
                path_put(&path);
+               if (retry_estale(error, lookup_flags)) {
+                       lookup_flags |= LOOKUP_REVAL;
+                       goto retry;
+               }
        }
 
 out:
index e21c119f4f99d8512208a9c08983dd5f9c25d821..3377dff184042044547d42e9b123944a0ad7e96a 100644 (file)
@@ -370,8 +370,9 @@ SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
 {
        struct path path;
        int error;
-
-       error = user_path(pathname, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = mnt_want_write(path.mnt);
@@ -380,6 +381,10 @@ SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
                mnt_drop_write(path.mnt);
        }
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -389,8 +394,9 @@ SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
 {
        struct path path;
        int error;
-
-       error = user_lpath(pathname, &path);
+       unsigned int lookup_flags = 0;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = mnt_want_write(path.mnt);
@@ -399,6 +405,10 @@ SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
                mnt_drop_write(path.mnt);
        }
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -476,12 +486,17 @@ SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
 {
        struct path path;
        ssize_t error;
-
-       error = user_path(pathname, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = getxattr(path.dentry, name, value, size);
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -490,12 +505,17 @@ SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
 {
        struct path path;
        ssize_t error;
-
-       error = user_lpath(pathname, &path);
+       unsigned int lookup_flags = 0;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = getxattr(path.dentry, name, value, size);
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -556,12 +576,17 @@ SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
 {
        struct path path;
        ssize_t error;
-
-       error = user_path(pathname, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = listxattr(path.dentry, list, size);
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -570,12 +595,17 @@ SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
 {
        struct path path;
        ssize_t error;
-
-       error = user_lpath(pathname, &path);
+       unsigned int lookup_flags = 0;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = listxattr(path.dentry, list, size);
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -615,8 +645,9 @@ SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
 {
        struct path path;
        int error;
-
-       error = user_path(pathname, &path);
+       unsigned int lookup_flags = LOOKUP_FOLLOW;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = mnt_want_write(path.mnt);
@@ -625,6 +656,10 @@ SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
                mnt_drop_write(path.mnt);
        }
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -633,8 +668,9 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
 {
        struct path path;
        int error;
-
-       error = user_lpath(pathname, &path);
+       unsigned int lookup_flags = 0;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (error)
                return error;
        error = mnt_want_write(path.mnt);
@@ -643,6 +679,10 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
                mnt_drop_write(path.mnt);
        }
        path_put(&path);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
index 4111a40ebe1a17dde31f89e5154c0d257c6e5d6c..5f707e5371717a331131f72f5babff24670d9bef 100644 (file)
@@ -86,11 +86,11 @@ xfs_destroy_ioend(
        }
 
        if (ioend->io_iocb) {
+               inode_dio_done(ioend->io_inode);
                if (ioend->io_isasync) {
                        aio_complete(ioend->io_iocb, ioend->io_error ?
                                        ioend->io_error : ioend->io_result, 0);
                }
-               inode_dio_done(ioend->io_inode);
        }
 
        mempool_free(ioend, xfs_ioend_pool);
index 0e92d12765d2670146b0325cd1215b449fb60dfe..cdb2d33485837bcd314f380f6d0c6737424626ec 100644 (file)
@@ -4680,9 +4680,6 @@ __xfs_bmapi_allocate(
                        return error;
        }
 
-       if (bma->flags & XFS_BMAPI_STACK_SWITCH)
-               bma->stack_switch = 1;
-
        error = xfs_bmap_alloc(bma);
        if (error)
                return error;
@@ -4956,6 +4953,9 @@ xfs_bmapi_write(
        bma.flist = flist;
        bma.firstblock = firstblock;
 
+       if (flags & XFS_BMAPI_STACK_SWITCH)
+               bma.stack_switch = 1;
+
        while (bno < end && n < *nmap) {
                inhole = eof || bma.got.br_startoff > bno;
                wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
index 26673a0b20e7249a149b22357c0961f86a6ac903..fbbb9eb92e32a7b38ec32c954313cffdb39a8508 100644 (file)
@@ -175,7 +175,7 @@ xfs_buf_get_maps(
        bp->b_map_count = map_count;
 
        if (map_count == 1) {
-               bp->b_maps = &bp->b_map;
+               bp->b_maps = &bp->__b_map;
                return 0;
        }
 
@@ -193,7 +193,7 @@ static void
 xfs_buf_free_maps(
        struct xfs_buf  *bp)
 {
-       if (bp->b_maps != &bp->b_map) {
+       if (bp->b_maps != &bp->__b_map) {
                kmem_free(bp->b_maps);
                bp->b_maps = NULL;
        }
@@ -377,8 +377,8 @@ xfs_buf_allocate_memory(
        }
 
 use_alloc_page:
-       start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT;
-       end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1)
+       start = BBTOB(bp->b_maps[0].bm_bn) >> PAGE_SHIFT;
+       end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1)
                                                                >> PAGE_SHIFT;
        page_count = end - start;
        error = _xfs_buf_get_pages(bp, page_count, flags);
@@ -487,6 +487,7 @@ _xfs_buf_find(
        struct rb_node          *parent;
        xfs_buf_t               *bp;
        xfs_daddr_t             blkno = map[0].bm_bn;
+       xfs_daddr_t             eofs;
        int                     numblks = 0;
        int                     i;
 
@@ -498,6 +499,23 @@ _xfs_buf_find(
        ASSERT(!(numbytes < (1 << btp->bt_sshift)));
        ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask));
 
+       /*
+        * Corrupted block numbers can get through to here, unfortunately, so we
+        * have to check that the buffer falls within the filesystem bounds.
+        */
+       eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
+       if (blkno >= eofs) {
+               /*
+                * XXX (dgc): we should really be returning EFSCORRUPTED here,
+                * but none of the higher level infrastructure supports
+                * returning a specific error on buffer lookup failures.
+                */
+               xfs_alert(btp->bt_mount,
+                         "%s: Block out of range: block 0x%llx, EOFS 0x%llx ",
+                         __func__, blkno, eofs);
+               return NULL;
+       }
+
        /* get tree root */
        pag = xfs_perag_get(btp->bt_mount,
                                xfs_daddr_to_agno(btp->bt_mount, blkno));
@@ -640,7 +658,7 @@ _xfs_buf_read(
        xfs_buf_flags_t         flags)
 {
        ASSERT(!(flags & XBF_WRITE));
-       ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL);
+       ASSERT(bp->b_maps[0].bm_bn != XFS_BUF_DADDR_NULL);
 
        bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD);
        bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
@@ -1487,6 +1505,8 @@ restart:
        while (!list_empty(&btp->bt_lru)) {
                bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
                if (atomic_read(&bp->b_hold) > 1) {
+                       trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
+                       list_move_tail(&bp->b_lru, &btp->bt_lru);
                        spin_unlock(&btp->bt_lru_lock);
                        delay(100);
                        goto restart;
@@ -1709,7 +1729,7 @@ xfs_buf_cmp(
        struct xfs_buf  *bp = container_of(b, struct xfs_buf, b_list);
        xfs_daddr_t             diff;
 
-       diff = ap->b_map.bm_bn - bp->b_map.bm_bn;
+       diff = ap->b_maps[0].bm_bn - bp->b_maps[0].bm_bn;
        if (diff < 0)
                return -1;
        if (diff > 0)
index 23f5642480bb1ea5f0f8a42423c607e7d61e9b83..433a12ed7b179e44ef784e8a144346af4faa9852 100644 (file)
@@ -151,7 +151,7 @@ typedef struct xfs_buf {
        struct page             **b_pages;      /* array of page pointers */
        struct page             *b_page_array[XB_PAGES]; /* inline pages */
        struct xfs_buf_map      *b_maps;        /* compound buffer map */
-       struct xfs_buf_map      b_map;          /* inline compound buffer map */
+       struct xfs_buf_map      __b_map;        /* inline compound buffer map */
        int                     b_map_count;
        int                     b_io_length;    /* IO size in BBs */
        atomic_t                b_pin_count;    /* pin count */
@@ -330,8 +330,8 @@ void xfs_buf_stale(struct xfs_buf *bp);
  * In future, uncached buffers will pass the block number directly to the io
  * request function and hence these macros will go away at that point.
  */
-#define XFS_BUF_ADDR(bp)               ((bp)->b_map.bm_bn)
-#define XFS_BUF_SET_ADDR(bp, bno)      ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno))
+#define XFS_BUF_ADDR(bp)               ((bp)->b_maps[0].bm_bn)
+#define XFS_BUF_SET_ADDR(bp, bno)      ((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno))
 
 static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
 {
index becf4a97efc65c95240e45c1b05b751919d51317..3f9949fee391b11cdfd73c12799cccba4ce1b56b 100644 (file)
@@ -71,7 +71,7 @@ xfs_buf_item_log_debug(
                chunk_num = byte >> XFS_BLF_SHIFT;
                word_num = chunk_num >> BIT_TO_WORD_SHIFT;
                bit_num = chunk_num & (NBWORD - 1);
-               wordp = &(bip->bli_format.blf_data_map[word_num]);
+               wordp = &(bip->__bli_format.blf_data_map[word_num]);
                bit_set = *wordp & (1 << bit_num);
                ASSERT(bit_set);
                byte++;
@@ -237,7 +237,7 @@ xfs_buf_item_size(
                 * cancel flag in it.
                 */
                trace_xfs_buf_item_size_stale(bip);
-               ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+               ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
                return bip->bli_format_count;
        }
 
@@ -278,7 +278,7 @@ xfs_buf_item_format_segment(
        uint            buffer_offset;
 
        /* copy the flags across from the base format item */
-       blfp->blf_flags = bip->bli_format.blf_flags;
+       blfp->blf_flags = bip->__bli_format.blf_flags;
 
        /*
         * Base size is the actual size of the ondisk structure - it reflects
@@ -287,6 +287,17 @@ xfs_buf_item_format_segment(
         */
        base_size = offsetof(struct xfs_buf_log_format, blf_data_map) +
                        (blfp->blf_map_size * sizeof(blfp->blf_data_map[0]));
+
+       nvecs = 0;
+       first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
+       if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) {
+               /*
+                * If the map is not be dirty in the transaction, mark
+                * the size as zero and do not advance the vector pointer.
+                */
+               goto out;
+       }
+
        vecp->i_addr = blfp;
        vecp->i_len = base_size;
        vecp->i_type = XLOG_REG_TYPE_BFORMAT;
@@ -301,15 +312,13 @@ xfs_buf_item_format_segment(
                 */
                trace_xfs_buf_item_format_stale(bip);
                ASSERT(blfp->blf_flags & XFS_BLF_CANCEL);
-               blfp->blf_size = nvecs;
-               return vecp;
+               goto out;
        }
 
        /*
         * Fill in an iovec for each set of contiguous chunks.
         */
-       first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
-       ASSERT(first_bit != -1);
+
        last_bit = first_bit;
        nbits = 1;
        for (;;) {
@@ -371,7 +380,8 @@ xfs_buf_item_format_segment(
                        nbits++;
                }
        }
-       bip->bli_format.blf_size = nvecs;
+out:
+       blfp->blf_size = nvecs;
        return vecp;
 }
 
@@ -405,7 +415,7 @@ xfs_buf_item_format(
        if (bip->bli_flags & XFS_BLI_INODE_BUF) {
                if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
                      xfs_log_item_in_current_chkpt(lip)))
-                       bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF;
+                       bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF;
                bip->bli_flags &= ~XFS_BLI_INODE_BUF;
        }
 
@@ -485,7 +495,7 @@ xfs_buf_item_unpin(
                ASSERT(bip->bli_flags & XFS_BLI_STALE);
                ASSERT(xfs_buf_islocked(bp));
                ASSERT(XFS_BUF_ISSTALE(bp));
-               ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+               ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 
                trace_xfs_buf_item_unpin_stale(bip);
 
@@ -601,7 +611,7 @@ xfs_buf_item_unlock(
 {
        struct xfs_buf_log_item *bip = BUF_ITEM(lip);
        struct xfs_buf          *bp = bip->bli_buf;
-       int                     aborted;
+       int                     aborted, clean, i;
        uint                    hold;
 
        /* Clear the buffer's association with this transaction. */
@@ -631,7 +641,7 @@ xfs_buf_item_unlock(
         */
        if (bip->bli_flags & XFS_BLI_STALE) {
                trace_xfs_buf_item_unlock_stale(bip);
-               ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+               ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
                if (!aborted) {
                        atomic_dec(&bip->bli_refcount);
                        return;
@@ -642,12 +652,27 @@ xfs_buf_item_unlock(
 
        /*
         * If the buf item isn't tracking any data, free it, otherwise drop the
-        * reference we hold to it.
+        * reference we hold to it. If we are aborting the transaction, this may
+        * be the only reference to the buf item, so we free it anyway
+        * regardless of whether it is dirty or not. A dirty abort implies a
+        * shutdown, anyway.
         */
-       if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
-                            bip->bli_format.blf_map_size))
+       clean = 1;
+       for (i = 0; i < bip->bli_format_count; i++) {
+               if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map,
+                            bip->bli_formats[i].blf_map_size)) {
+                       clean = 0;
+                       break;
+               }
+       }
+       if (clean)
                xfs_buf_item_relse(bp);
-       else
+       else if (aborted) {
+               if (atomic_dec_and_test(&bip->bli_refcount)) {
+                       ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
+                       xfs_buf_item_relse(bp);
+               }
+       } else
                atomic_dec(&bip->bli_refcount);
 
        if (!hold)
@@ -716,7 +741,7 @@ xfs_buf_item_get_format(
        bip->bli_format_count = count;
 
        if (count == 1) {
-               bip->bli_formats = &bip->bli_format;
+               bip->bli_formats = &bip->__bli_format;
                return 0;
        }
 
@@ -731,7 +756,7 @@ STATIC void
 xfs_buf_item_free_format(
        struct xfs_buf_log_item *bip)
 {
-       if (bip->bli_formats != &bip->bli_format) {
+       if (bip->bli_formats != &bip->__bli_format) {
                kmem_free(bip->bli_formats);
                bip->bli_formats = NULL;
        }
index 6850f49f4af3f60c0a5a8ef9508f7bac9af00e4c..16def435944ac79063cd3f48bcf8067cc2d270c5 100644 (file)
@@ -104,7 +104,7 @@ typedef struct xfs_buf_log_item {
 #endif
        int                     bli_format_count;       /* count of headers */
        struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */
-       struct xfs_buf_log_format bli_format;   /* embedded in-log header */
+       struct xfs_buf_log_format __bli_format; /* embedded in-log header */
 } xfs_buf_log_item_t;
 
 void   xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
index d0e9c74d3d96a75c18d40f175efd51eec85aab18..a8bd26b82ecb00dd14063da4c62c1a64011f0caa 100644 (file)
@@ -246,10 +246,10 @@ xfs_swap_extents(
                goto out_unlock;
        }
 
-       error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
+       error = -filemap_write_and_wait(VFS_I(tip)->i_mapping);
        if (error)
                goto out_unlock;
-       truncate_pagecache_range(VFS_I(ip), 0, -1);
+       truncate_pagecache_range(VFS_I(tip), 0, -1);
 
        /* Verify O_DIRECT for ftmp */
        if (VN_CACHED(VFS_I(tip)) != 0) {
index 7536faaa61e7852175f7b7c20f1e4b0c566c24db..12afe07a91d71ddc003a763674d7d1ee45a992d3 100644 (file)
@@ -355,10 +355,12 @@ xfs_dir2_block_addname(
        /*
         * If need to compact the leaf entries, do it now.
         */
-       if (compact)
+       if (compact) {
                xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
                                      &lfloghigh, &lfloglow);
-       else if (btp->stale) {
+               /* recalculate blp post-compaction */
+               blp = xfs_dir2_block_leaf_p(btp);
+       } else if (btp->stale) {
                /*
                 * Set leaf logging boundaries to impossible state.
                 * For the no-stale case they're set explicitly.
index add06b4e9a635511afc3e2716836e210ff794c46..364818eef40e55720a6a4509afbde63a1b48cd05 100644 (file)
@@ -351,6 +351,15 @@ xfs_iomap_prealloc_size(
                }
                if (shift)
                        alloc_blocks >>= shift;
+
+               /*
+                * If we are still trying to allocate more space than is
+                * available, squash the prealloc hard. This can happen if we
+                * have a large file on a small filesystem and the above
+                * lowspace thresholds are smaller than MAXEXTLEN.
+                */
+               while (alloc_blocks >= freesp)
+                       alloc_blocks >>= 4;
        }
 
        if (alloc_blocks < mp->m_writeio_blocks)
index da508463ff1006b7b4b5371d5f2c19495cb5d44b..7d6df7c00c36fb22e8f864285c6d2352b44a7cdd 100644 (file)
@@ -658,7 +658,7 @@ xfs_sb_quiet_read_verify(
                return;
        }
        /* quietly fail */
-       xfs_buf_ioerror(bp, EFSCORRUPTED);
+       xfs_buf_ioerror(bp, EWRONGFS);
 }
 
 static void
index 5f53e75409b8f45ad919aae17b24cf92c5218a06..8a59f8546552e9577b3a93c44b8cfb7251e3561a 100644 (file)
@@ -784,11 +784,11 @@ xfs_qm_scall_getquota(
             (XFS_IS_OQUOTA_ENFORCED(mp) &&
                        (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
            dst->d_id != 0) {
-               if (((int) dst->d_bcount > (int) dst->d_blk_softlimit) &&
+               if ((dst->d_bcount > dst->d_blk_softlimit) &&
                    (dst->d_blk_softlimit > 0)) {
                        ASSERT(dst->d_btimer != 0);
                }
-               if (((int) dst->d_icount > (int) dst->d_ino_softlimit) &&
+               if ((dst->d_icount > dst->d_ino_softlimit) &&
                    (dst->d_ino_softlimit > 0)) {
                        ASSERT(dst->d_itimer != 0);
                }
index 2e137d4a85ae66bc3a9172a4d93f734ba7aabb99..16a812977eab3d8fcf001e0175e6cfd773dcfe67 100644 (file)
@@ -341,6 +341,7 @@ DEFINE_BUF_EVENT(xfs_buf_item_relse);
 DEFINE_BUF_EVENT(xfs_buf_item_iodone);
 DEFINE_BUF_EVENT(xfs_buf_item_iodone_async);
 DEFINE_BUF_EVENT(xfs_buf_error_relse);
+DEFINE_BUF_EVENT(xfs_buf_wait_buftarg);
 DEFINE_BUF_EVENT(xfs_trans_read_buf_io);
 DEFINE_BUF_EVENT(xfs_trans_read_buf_shut);
 
index 4fc17d479d42301d13cc86bfd2a8aec194fecea0..3edf5dbee001c60239a11254dbd697c7602e9b06 100644 (file)
@@ -93,7 +93,7 @@ _xfs_trans_bjoin(
        xfs_buf_item_init(bp, tp->t_mountp);
        bip = bp->b_fspriv;
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-       ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+       ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
        ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
        if (reset_recur)
                bip->bli_recur = 0;
@@ -432,7 +432,7 @@ xfs_trans_brelse(xfs_trans_t        *tp,
        bip = bp->b_fspriv;
        ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-       ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+       ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
        trace_xfs_trans_brelse(bip);
@@ -519,7 +519,7 @@ xfs_trans_bhold(xfs_trans_t *tp,
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-       ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+       ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
        bip->bli_flags |= XFS_BLI_HOLD;
@@ -539,7 +539,7 @@ xfs_trans_bhold_release(xfs_trans_t *tp,
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-       ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+       ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
        ASSERT(bip->bli_flags & XFS_BLI_HOLD);
 
@@ -598,7 +598,7 @@ xfs_trans_log_buf(xfs_trans_t       *tp,
                bip->bli_flags &= ~XFS_BLI_STALE;
                ASSERT(XFS_BUF_ISSTALE(bp));
                XFS_BUF_UNSTALE(bp);
-               bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL;
+               bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL;
        }
 
        tp->t_flags |= XFS_TRANS_DIRTY;
@@ -643,6 +643,7 @@ xfs_trans_binval(
        xfs_buf_t       *bp)
 {
        xfs_buf_log_item_t      *bip = bp->b_fspriv;
+       int                     i;
 
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
@@ -657,8 +658,8 @@ xfs_trans_binval(
                 */
                ASSERT(XFS_BUF_ISSTALE(bp));
                ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
-               ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF));
-               ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+               ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF));
+               ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
                ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY);
                ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
                return;
@@ -668,10 +669,12 @@ xfs_trans_binval(
 
        bip->bli_flags |= XFS_BLI_STALE;
        bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
-       bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
-       bip->bli_format.blf_flags |= XFS_BLF_CANCEL;
-       memset((char *)(bip->bli_format.blf_data_map), 0,
-             (bip->bli_format.blf_map_size * sizeof(uint)));
+       bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
+       bip->__bli_format.blf_flags |= XFS_BLF_CANCEL;
+       for (i = 0; i < bip->bli_format_count; i++) {
+               memset(bip->bli_formats[i].blf_data_map, 0,
+                      (bip->bli_formats[i].blf_map_size * sizeof(uint)));
+       }
        bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
        tp->t_flags |= XFS_TRANS_DIRTY;
 }
@@ -775,5 +778,5 @@ xfs_trans_dquot_buf(
               type == XFS_BLF_GDQUOT_BUF);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
-       bip->bli_format.blf_flags |= type;
+       bip->__bli_format.blf_flags |= type;
 }
index 83256b64166a85380eb6a20adc357195ca8bfe77..1dfd33e8d43bdb5a3890f31cbd5810a1010fcef5 100644 (file)
@@ -1,8 +1,5 @@
 # Top-level Makefile calls into asm-$(ARCH)
 # List only non-arch directories below
 
-header-y += linux/
-header-y += sound/
-header-y += rdma/
 header-y += video/
 header-y += scsi/
index 9a62937c56ca342812177e1022910194ca8fba7a..51969436b8b83b21730d25a5cef434ac6db3ef06 100644 (file)
@@ -4,66 +4,12 @@
 #include <linux/time.h>
 #include <linux/jiffies.h>
 
-typedef unsigned long __nocast cputime_t;
-
-#define cputime_one_jiffy              jiffies_to_cputime(1)
-#define cputime_to_jiffies(__ct)       (__force unsigned long)(__ct)
-#define cputime_to_scaled(__ct)                (__ct)
-#define jiffies_to_cputime(__hz)       (__force cputime_t)(__hz)
-
-typedef u64 __nocast cputime64_t;
-
-#define cputime64_to_jiffies64(__ct)   (__force u64)(__ct)
-#define jiffies64_to_cputime64(__jif)  (__force cputime64_t)(__jif)
-
-#define nsecs_to_cputime64(__ct)       \
-       jiffies64_to_cputime64(nsecs_to_jiffies64(__ct))
-
-
-/*
- * Convert cputime to microseconds and back.
- */
-#define cputime_to_usecs(__ct)         \
-       jiffies_to_usecs(cputime_to_jiffies(__ct))
-#define usecs_to_cputime(__usec)       \
-       jiffies_to_cputime(usecs_to_jiffies(__usec))
-#define usecs_to_cputime64(__usec)     \
-       jiffies64_to_cputime64(nsecs_to_jiffies64((__usec) * 1000))
-
-/*
- * Convert cputime to seconds and back.
- */
-#define cputime_to_secs(jif)           (cputime_to_jiffies(jif) / HZ)
-#define secs_to_cputime(sec)           jiffies_to_cputime((sec) * HZ)
-
-/*
- * Convert cputime to timespec and back.
- */
-#define timespec_to_cputime(__val)     \
-       jiffies_to_cputime(timespec_to_jiffies(__val))
-#define cputime_to_timespec(__ct,__val)        \
-       jiffies_to_timespec(cputime_to_jiffies(__ct),__val)
-
-/*
- * Convert cputime to timeval and back.
- */
-#define timeval_to_cputime(__val)      \
-       jiffies_to_cputime(timeval_to_jiffies(__val))
-#define cputime_to_timeval(__ct,__val) \
-       jiffies_to_timeval(cputime_to_jiffies(__ct),__val)
-
-/*
- * Convert cputime to clock and back.
- */
-#define cputime_to_clock_t(__ct)       \
-       jiffies_to_clock_t(cputime_to_jiffies(__ct))
-#define clock_t_to_cputime(__x)                \
-       jiffies_to_cputime(clock_t_to_jiffies(__x))
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+# include <asm-generic/cputime_jiffies.h>
+#endif
 
-/*
- * Convert cputime64 to clock.
- */
-#define cputime64_to_clock_t(__ct)     \
-       jiffies_64_to_clock_t(cputime64_to_jiffies64(__ct))
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+# include <asm-generic/cputime_nsecs.h>
+#endif
 
 #endif
diff --git a/include/asm-generic/cputime_jiffies.h b/include/asm-generic/cputime_jiffies.h
new file mode 100644 (file)
index 0000000..272ecba
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _ASM_GENERIC_CPUTIME_JIFFIES_H
+#define _ASM_GENERIC_CPUTIME_JIFFIES_H
+
+typedef unsigned long __nocast cputime_t;
+
+#define cputime_one_jiffy              jiffies_to_cputime(1)
+#define cputime_to_jiffies(__ct)       (__force unsigned long)(__ct)
+#define cputime_to_scaled(__ct)                (__ct)
+#define jiffies_to_cputime(__hz)       (__force cputime_t)(__hz)
+
+typedef u64 __nocast cputime64_t;
+
+#define cputime64_to_jiffies64(__ct)   (__force u64)(__ct)
+#define jiffies64_to_cputime64(__jif)  (__force cputime64_t)(__jif)
+
+
+/*
+ * Convert nanoseconds to cputime
+ */
+#define nsecs_to_cputime64(__nsec)     \
+       jiffies64_to_cputime64(nsecs_to_jiffies64(__nsec))
+#define nsecs_to_cputime(__nsec)       \
+       jiffies_to_cputime(nsecs_to_jiffies(__nsec))
+
+
+/*
+ * Convert cputime to microseconds and back.
+ */
+#define cputime_to_usecs(__ct)         \
+       jiffies_to_usecs(cputime_to_jiffies(__ct))
+#define usecs_to_cputime(__usec)       \
+       jiffies_to_cputime(usecs_to_jiffies(__usec))
+#define usecs_to_cputime64(__usec)     \
+       jiffies64_to_cputime64(nsecs_to_jiffies64((__usec) * 1000))
+
+/*
+ * Convert cputime to seconds and back.
+ */
+#define cputime_to_secs(jif)           (cputime_to_jiffies(jif) / HZ)
+#define secs_to_cputime(sec)           jiffies_to_cputime((sec) * HZ)
+
+/*
+ * Convert cputime to timespec and back.
+ */
+#define timespec_to_cputime(__val)     \
+       jiffies_to_cputime(timespec_to_jiffies(__val))
+#define cputime_to_timespec(__ct,__val)        \
+       jiffies_to_timespec(cputime_to_jiffies(__ct),__val)
+
+/*
+ * Convert cputime to timeval and back.
+ */
+#define timeval_to_cputime(__val)      \
+       jiffies_to_cputime(timeval_to_jiffies(__val))
+#define cputime_to_timeval(__ct,__val) \
+       jiffies_to_timeval(cputime_to_jiffies(__ct),__val)
+
+/*
+ * Convert cputime to clock and back.
+ */
+#define cputime_to_clock_t(__ct)       \
+       jiffies_to_clock_t(cputime_to_jiffies(__ct))
+#define clock_t_to_cputime(__x)                \
+       jiffies_to_cputime(clock_t_to_jiffies(__x))
+
+/*
+ * Convert cputime64 to clock.
+ */
+#define cputime64_to_clock_t(__ct)     \
+       jiffies_64_to_clock_t(cputime64_to_jiffies64(__ct))
+
+#endif
diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h
new file mode 100644 (file)
index 0000000..b6485ca
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Definitions for measuring cputime in nsecs resolution.
+ *
+ * Based on <arch/ia64/include/asm/cputime.h>
+ *
+ * Copyright (C) 2007 FUJITSU LIMITED
+ * Copyright (C) 2007 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.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 _ASM_GENERIC_CPUTIME_NSECS_H
+#define _ASM_GENERIC_CPUTIME_NSECS_H
+
+typedef u64 __nocast cputime_t;
+typedef u64 __nocast cputime64_t;
+
+#define cputime_one_jiffy              jiffies_to_cputime(1)
+
+/*
+ * Convert cputime <-> jiffies (HZ)
+ */
+#define cputime_to_jiffies(__ct)       \
+       ((__force u64)(__ct) / (NSEC_PER_SEC / HZ))
+#define cputime_to_scaled(__ct)                (__ct)
+#define jiffies_to_cputime(__jif)      \
+       (__force cputime_t)((__jif) * (NSEC_PER_SEC / HZ))
+#define cputime64_to_jiffies64(__ct)   \
+       ((__force u64)(__ct) / (NSEC_PER_SEC / HZ))
+#define jiffies64_to_cputime64(__jif)  \
+       (__force cputime64_t)((__jif) * (NSEC_PER_SEC / HZ))
+
+
+/*
+ * Convert cputime <-> nanoseconds
+ */
+#define nsecs_to_cputime(__nsecs)      ((__force u64)(__nsecs))
+
+
+/*
+ * Convert cputime <-> microseconds
+ */
+#define cputime_to_usecs(__ct)         \
+       ((__force u64)(__ct) / NSEC_PER_USEC)
+#define usecs_to_cputime(__usecs)      \
+       (__force cputime_t)((__usecs) * NSEC_PER_USEC)
+#define usecs_to_cputime64(__usecs)    \
+       (__force cputime64_t)((__usecs) * NSEC_PER_USEC)
+
+/*
+ * Convert cputime <-> seconds
+ */
+#define cputime_to_secs(__ct)          \
+       ((__force u64)(__ct) / NSEC_PER_SEC)
+#define secs_to_cputime(__secs)                \
+       (__force cputime_t)((__secs) * NSEC_PER_SEC)
+
+/*
+ * Convert cputime <-> timespec (nsec)
+ */
+static inline cputime_t timespec_to_cputime(const struct timespec *val)
+{
+       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
+       return (__force cputime_t) ret;
+}
+static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
+{
+       val->tv_sec  = (__force u64) ct / NSEC_PER_SEC;
+       val->tv_nsec = (__force u64) ct % NSEC_PER_SEC;
+}
+
+/*
+ * Convert cputime <-> timeval (msec)
+ */
+static inline cputime_t timeval_to_cputime(struct timeval *val)
+{
+       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_usec * NSEC_PER_USEC;
+       return (__force cputime_t) ret;
+}
+static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
+{
+       val->tv_sec = (__force u64) ct / NSEC_PER_SEC;
+       val->tv_usec = ((__force u64) ct % NSEC_PER_SEC) / NSEC_PER_USEC;
+}
+
+/*
+ * Convert cputime <-> clock (USER_HZ)
+ */
+#define cputime_to_clock_t(__ct)       \
+       ((__force u64)(__ct) / (NSEC_PER_SEC / USER_HZ))
+#define clock_t_to_cputime(__x)                \
+       (__force cputime_t)((__x) * (NSEC_PER_SEC / USER_HZ))
+
+/*
+ * Convert cputime64 to clock.
+ */
+#define cputime64_to_clock_t(__ct)     \
+       cputime_to_clock_t((__force cputime_t)__ct)
+
+#endif
index ccf7b4f34a3c4e070fb44cd7456c859ee5c3c645..6c32af918c2f1dc257fea3613bcf5bca8137d9ec 100644 (file)
@@ -16,6 +16,22 @@ extern void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
                    dma_addr_t dma_handle);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
index d1e93284d72a6ebdc4e246732a11e398e6ba5d7f..33bbbae4ddc699ba84b5ae657594c35bfa61cb22 100644 (file)
@@ -12,7 +12,6 @@
 #define __ASM_GENERIC_IO_H
 
 #include <asm/page.h> /* I/O is all done through memory accesses */
-#include <asm/cacheflush.h>
 #include <linux/types.h>
 
 #ifdef CONFIG_GENERIC_IOMAP
@@ -223,36 +222,6 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 }
 #endif
 
-static inline void readsl(const void __iomem *addr, void *buf, int len)
-{
-       insl(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void readsw(const void __iomem *addr, void *buf, int len)
-{
-       insw(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void readsb(const void __iomem *addr, void *buf, int len)
-{
-       insb(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesl(const void __iomem *addr, const void *buf, int len)
-{
-       outsl(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesw(const void __iomem *addr, const void *buf, int len)
-{
-       outsw(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesb(const void __iomem *addr, const void *buf, int len)
-{
-       outsb(addr - PCI_IOBASE, buf, len);
-}
-
 #ifndef CONFIG_GENERIC_IOMAP
 #define ioread8(addr)          readb(addr)
 #define ioread16(addr)         readw(addr)
index 4f4aa56d6b5273246082cb8e31defedfada1fc43..0ed3f1cfb85444443566ca46ca6ceb7e15d3e017 100644 (file)
@@ -7,8 +7,12 @@
  */
 #ifndef __ASSEMBLY__
 typedef struct {
-       struct vm_list_struct   *vmlist;
        unsigned long           end_brk;
+
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+       unsigned long           exec_fdpic_loadmap;
+       unsigned long           interp_fdpic_loadmap;
+#endif
 } mm_context_t;
 #endif
 
index 40528cb977e81be02b244f2a6f82c006635c9388..2c9f9d4336cacf8cf46d591cf1a4b019ef4044e7 100644 (file)
@@ -10,8 +10,8 @@
  * to devices on the PCI bus.
  */
 
-static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+static int parport_pc_find_isa_ports(int autoirq, int autodma);
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
 {
 #ifdef CONFIG_ISA
        return parport_pc_find_isa_ports(autoirq, autodma);
index 701beab27aab71c94031151d9daaf6090f570b99..5cf680a98f9bcb7494a2c0a4bc557fca00b84296 100644 (file)
@@ -461,10 +461,8 @@ static inline int is_zero_pfn(unsigned long pfn)
        return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
 }
 
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-       return page_to_pfn(ZERO_PAGE(addr));
-}
+#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+
 #else
 static inline int is_zero_pfn(unsigned long pfn)
 {
index 58f466ff00d363701155427cb7968515ef60c935..1db51b8524e9fb86fcc71e797f95a6518c259bfc 100644 (file)
@@ -21,10 +21,12 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                        unsigned long fd, off_t pgoff);
 #endif
 
+#ifndef CONFIG_GENERIC_SIGALTSTACK
 #ifndef sys_sigaltstack
 asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
                        struct pt_regs *);
 #endif
+#endif
 
 #ifndef sys_rt_sigreturn
 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs);
index ed6642ad03e073fcd5a4d35d02ba9f6bcb5221b0..25f01d0bc149cc388ce5a8e66d556669809e2b34 100644 (file)
@@ -78,6 +78,14 @@ struct mmu_gather_batch {
 #define MAX_GATHER_BATCH       \
        ((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *))
 
+/*
+ * Limit the maximum number of mmu_gather batches to reduce a risk of soft
+ * lockups for non-preemptible kernels on huge machines when a lot of memory
+ * is zapped during unmapping.
+ * 10K pages freed at once should be safe even without a preemption point.
+ */
+#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH)
+
 /* struct mmu_gather is an opaque type used by the mm code for passing around
  * any data needed by arch specific code for tlb_remove_page.
  */
@@ -96,6 +104,7 @@ struct mmu_gather {
        struct mmu_gather_batch *active;
        struct mmu_gather_batch local;
        struct page             *__pages[MMU_GATHER_BUNDLE];
+       unsigned int            batch_count;
 };
 
 #define HAVE_GENERIC_MMU_GATHER
index 06d7f798a08c547c3dfbd3ed3139c33b86c26c0b..3527fb3f75bbe82c408e8614f5cfbb8c1a88dff9 100644 (file)
@@ -70,7 +70,7 @@ struct drm_mm {
        unsigned long scan_color;
        unsigned long scan_size;
        unsigned long scan_hit_start;
-       unsigned scan_hit_size;
+       unsigned long scan_hit_end;
        unsigned scanned_blocks;
        unsigned long scan_start;
        unsigned long scan_end;
@@ -158,12 +158,29 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
        return drm_mm_get_block_range_generic(parent, size, alignment, 0,
                                                start, end, 1);
 }
-extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
-                             unsigned long size, unsigned alignment);
+
+extern int drm_mm_insert_node(struct drm_mm *mm,
+                             struct drm_mm_node *node,
+                             unsigned long size,
+                             unsigned alignment);
 extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
                                       struct drm_mm_node *node,
-                                      unsigned long size, unsigned alignment,
-                                      unsigned long start, unsigned long end);
+                                      unsigned long size,
+                                      unsigned alignment,
+                                      unsigned long start,
+                                      unsigned long end);
+extern int drm_mm_insert_node_generic(struct drm_mm *mm,
+                                     struct drm_mm_node *node,
+                                     unsigned long size,
+                                     unsigned alignment,
+                                     unsigned long color);
+extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
+                                      struct drm_mm_node *node,
+                                      unsigned long size,
+                                      unsigned alignment,
+                                      unsigned long color,
+                                      unsigned long start,
+                                      unsigned long end);
 extern void drm_mm_put_block(struct drm_mm_node *cur);
 extern void drm_mm_remove_node(struct drm_mm_node *node);
 extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
index 808dad29607a17790c0bf9b69ba5493e021e3bfd..d6aeaf3c6d6cb69ad039ec18bddd559cf32f8d62 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _EXYNOS_DRM_H_
 #define _EXYNOS_DRM_H_
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
deleted file mode 100644 (file)
index 7fe2dae..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-header-y += dvb/
-header-y += hdlc/
-header-y += hsi/
-header-y += raid/
-header-y += usb/
index 544abdb2238ccdffda329816578b41bb954fc617..ec10e1b24c1cce50d50581d58c5000cf7b9e5565 100644 (file)
@@ -49,8 +49,8 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 }
 #endif
 
-extern void cper_print_aer(const char *prefix, int cper_severity,
-                          struct aer_capability_regs *aer);
+extern void cper_print_aer(const char *prefix, struct pci_dev *dev,
+                          int cper_severity, struct aer_capability_regs *aer);
 extern int cper_severity_to_aer(int cper_severity);
 extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
                              int severity);
index 408da9502177bd18a3ba88e2831701e916e800aa..8f7a3d68371a37314ab8263c078674fd79a8c5b5 100644 (file)
@@ -297,10 +297,12 @@ enum {
        ATA_LOG_SATA_NCQ        = 0x10,
        ATA_LOG_SATA_ID_DEV_DATA  = 0x30,
        ATA_LOG_SATA_SETTINGS     = 0x08,
-       ATA_LOG_DEVSLP_MDAT       = 0x30,
+       ATA_LOG_DEVSLP_OFFSET     = 0x30,
+       ATA_LOG_DEVSLP_SIZE       = 0x08,
+       ATA_LOG_DEVSLP_MDAT       = 0x00,
        ATA_LOG_DEVSLP_MDAT_MASK  = 0x1F,
-       ATA_LOG_DEVSLP_DETO       = 0x31,
-       ATA_LOG_DEVSLP_VALID      = 0x37,
+       ATA_LOG_DEVSLP_DETO       = 0x01,
+       ATA_LOG_DEVSLP_VALID      = 0x07,
        ATA_LOG_DEVSLP_VALID_MASK = 0x80,
 
        /* READ/WRITE LONG (obsolete) */
index fe9989636b6252536b6abf7042e598c7d6da39fd..b9fde17f767cf654479759b66e22ec9828206ed3 100644 (file)
@@ -15,12 +15,12 @@ struct pata_platform_info {
        unsigned int irq_flags;
 };
 
-extern int __devinit __pata_platform_probe(struct device *dev,
-                                          struct resource *io_res,
-                                          struct resource *ctl_res,
-                                          struct resource *irq_res,
-                                          unsigned int ioport_shift,
-                                          int __pio_mask);
+extern int __pata_platform_probe(struct device *dev,
+                                struct resource *io_res,
+                                struct resource *ctl_res,
+                                struct resource *irq_res,
+                                unsigned int ioport_shift,
+                                int __pio_mask);
 
 /*
  * Marvell SATA private data
index bce729afbcf9a5e184e70edc1bebf9f65a0176a3..5a6d718adf34825eb11bc4dd20cbcb8f1dced0ad 100644 (file)
@@ -24,6 +24,7 @@
 #define _LINUX_AUDIT_H_
 
 #include <linux/sched.h>
+#include <linux/ptrace.h>
 #include <uapi/linux/audit.h>
 
 struct audit_sig_info {
@@ -157,7 +158,8 @@ void audit_core_dumps(long signr);
 
 static inline void audit_seccomp(unsigned long syscall, long signr, int code)
 {
-       if (unlikely(!audit_dummy_context()))
+       /* Force a record to be reported if a signal was delivered. */
+       if (signr || unlikely(!audit_dummy_context()))
                __audit_seccomp(syscall, signr, code);
 }
 
index 2a9a9abc91260c09a7940136a965a08209c5828b..12731a19ef060792b5500c3731551b636c437fe8 100644 (file)
@@ -114,6 +114,7 @@ struct backing_dev_info {
 int bdi_init(struct backing_dev_info *bdi);
 void bdi_destroy(struct backing_dev_info *bdi);
 
+__printf(3, 4)
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
                const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
index def894b83b0dcc48010c3e69f5593ce3e68f80ae..4dd1f33e36a20accc10d1aa1f1d66cfd5203f49b 100644 (file)
@@ -92,7 +92,7 @@ struct bcma_drv_gmac_cmn {
 #define gmac_cmn_write32(gc, offset, val)      bcma_write32((gc)->core, offset, val)
 
 #ifdef CONFIG_BCMA_DRIVER_GMAC_CMN
-extern void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc);
+extern void bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc);
 #else
 static inline void bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc) { }
 #endif
index 41da581e1612a515157559aee5b5e90e23fccf50..c48d98d27b770ee8f13a6ff26aa918aeb89d66be 100644 (file)
@@ -214,7 +214,7 @@ struct bcma_drv_pci {
 #define pcicore_write16(pc, offset, val)       bcma_write16((pc)->core, offset, val)
 #define pcicore_write32(pc, offset, val)       bcma_write32((pc)->core, offset, val)
 
-extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
+extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
 extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
                                 struct bcma_device *core, bool enable);
 extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
index a4c2b565c835dfceade1065efe641d5009b85b08..0530b9860359afb26cfb8a2a05ed7ec0a4c2169a 100644 (file)
@@ -112,6 +112,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
                           unsigned long stack_top,
                           int executable_stack);
 extern int bprm_mm_init(struct linux_binprm *bprm);
+extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
                               struct linux_binprm *bprm);
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
@@ -119,8 +120,4 @@ extern void install_exec_creds(struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
 extern void free_bprm(struct linux_binprm *);
 
-#ifdef __ARCH_WANT_KERNEL_EXECVE
-extern void ret_from_kernel_execve(struct pt_regs *normal) __noreturn;
-#endif
-
 #endif /* _LINUX_BINFMTS_H */
index 6470792b13d3c79734a9a3ae7321a9df691cec78..084d3c622b12a8ac58ad626da2e8f325d6d3d1c9 100644 (file)
@@ -43,7 +43,6 @@ struct ceph_options {
        struct ceph_entity_addr my_addr;
        int mount_timeout;
        int osd_idle_ttl;
-       int osd_timeout;
        int osd_keepalive_timeout;
 
        /*
@@ -63,7 +62,6 @@ struct ceph_options {
  * defaults
  */
 #define CEPH_MOUNT_TIMEOUT_DEFAULT  60
-#define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
 #define CEPH_OSD_KEEPALIVE_DEFAULT  5
 #define CEPH_OSD_IDLE_TTL_DEFAULT    60
 
index e37acbe989a906c8cdead48c6eea2e68f53e6ed8..10a417f9f76fa9ccd2e2fffbc27950dbc355df59 100644 (file)
@@ -123,6 +123,7 @@ extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
 extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
                                struct ceph_pg pgid);
 
+extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id);
 extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
 
 #endif
index de91fbdf127e64b343f3fc3530d6d7fb9bd4e59e..2c04afeead1cb3d776feea90e51f93731417b1a3 100644 (file)
@@ -87,6 +87,8 @@ struct ceph_pg {
  *
  *  lpgp_num -- as above.
  */
+#define CEPH_NOPOOL  ((__u64) (-1))  /* pool id not defined */
+
 #define CEPH_PG_TYPE_REP     1
 #define CEPH_PG_TYPE_RAID4   2
 #define CEPH_PG_POOL_VERSION 2
index 8a7096fcb01ee1354e1d46c67d5d1ff9919bc742..66346521cb6561641045297cb74c8d15f7b71f74 100644 (file)
@@ -161,6 +161,15 @@ clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
+extern void tick_broadcast(const struct cpumask *mask);
+#else
+#define tick_broadcast NULL
+#endif
+extern int tick_receive_broadcast(void);
+#endif
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void clockevents_notify(unsigned long reason, void *arg);
 #else
index 6ecb6dc2f3033fc50ba1a8f14eb4b2b12b8ec044..cc7bddeaf553b334e6aa1250fbf74924358e5de4 100644 (file)
@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
 extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
                        int order, gfp_t gfp_mask, nodemask_t *mask,
-                       bool sync, bool *contended, struct page **page);
+                       bool sync, bool *contended);
 extern int compact_pgdat(pg_data_t *pgdat, int order);
 extern void reset_isolation_suitable(pg_data_t *pgdat);
 extern unsigned long compaction_suitable(struct zone *zone, int order);
@@ -75,7 +75,7 @@ static inline bool compaction_restarting(struct zone *zone, int order)
 #else
 static inline unsigned long try_to_compact_pages(struct zonelist *zonelist,
                        int order, gfp_t gfp_mask, nodemask_t *nodemask,
-                       bool sync, bool *contended, struct page **page)
+                       bool sync, bool *contended)
 {
        return COMPACT_CONTINUE;
 }
index e4920bd58a4792c040d3901d702388c50d6c3c26..dec7e2d188758369d1c5d10cc7a978eb3b9ce423 100644 (file)
 #define COMPAT_USE_64BIT_TIME 0
 #endif
 
+#ifndef __SC_DELOUSE
+#define __SC_DELOUSE(t,v) ((t)(unsigned long)(v))
+#endif
+
+#define __SC_CCAST1(t1, a1)      __SC_DELOUSE(t1,a1)
+#define __SC_CCAST2(t2, a2, ...) __SC_DELOUSE(t2,a2), __SC_CCAST1(__VA_ARGS__)
+#define __SC_CCAST3(t3, a3, ...) __SC_DELOUSE(t3,a3), __SC_CCAST2(__VA_ARGS__)
+#define __SC_CCAST4(t4, a4, ...) __SC_DELOUSE(t4,a4), __SC_CCAST3(__VA_ARGS__)
+#define __SC_CCAST5(t5, a5, ...) __SC_DELOUSE(t5,a5), __SC_CCAST4(__VA_ARGS__)
+#define __SC_CCAST6(t6, a6, ...) __SC_DELOUSE(t6,a6), __SC_CCAST5(__VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE1(name, ...) \
+        COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE2(name, ...) \
+       COMPAT_SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE3(name, ...) \
+       COMPAT_SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE4(name, ...) \
+       COMPAT_SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE5(name, ...) \
+       COMPAT_SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_DEFINE6(name, ...) \
+       COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
+
+#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
+
+#define COMPAT_SYSCALL_DEFINEx(x, name, ...)                           \
+       asmlinkage long compat_sys##name(__SC_DECL##x(__VA_ARGS__));    \
+       static inline long C_SYSC##name(__SC_DECL##x(__VA_ARGS__));     \
+       asmlinkage long compat_SyS##name(__SC_LONG##x(__VA_ARGS__))     \
+       {                                                               \
+               return (long) C_SYSC##name(__SC_CCAST##x(__VA_ARGS__)); \
+       }                                                               \
+       SYSCALL_ALIAS(compat_sys##name, compat_SyS##name);              \
+       static inline long C_SYSC##name(__SC_DECL##x(__VA_ARGS__))
+
+#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */
+
+#define COMPAT_SYSCALL_DEFINEx(x, name, ...)                           \
+       asmlinkage long compat_sys##name(__SC_DECL##x(__VA_ARGS__))
+
+#endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */
+
+#ifndef compat_user_stack_pointer
+#define compat_user_stack_pointer() current_user_stack_pointer()
+#endif
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+#ifndef compat_sigaltstack     /* we'll need that for MIPS */
+typedef struct compat_sigaltstack {
+       compat_uptr_t                   ss_sp;
+       int                             ss_flags;
+       compat_size_t                   ss_size;
+} compat_stack_t;
+#endif
+#endif
+
 #define compat_jiffies_to_clock_t(x)   \
                (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
@@ -587,6 +642,13 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
 
 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
                                    compat_off_t __user *offset, compat_size_t count);
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
+                                      compat_stack_t __user *uoss_ptr);
+
+int compat_restore_altstack(const compat_stack_t __user *uss);
+int __compat_save_altstack(compat_stack_t __user *, unsigned long);
+#endif
 
 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
                                                 struct compat_timespec __user *interval);
index e24339ccb7f04a066dd52b7a88cd8a7d06c265bc..b28d161c1091908b9395df4e3ad73e6d88518966 100644 (file)
@@ -3,12 +3,40 @@
 
 #ifdef CONFIG_CONTEXT_TRACKING
 #include <linux/sched.h>
+#include <linux/percpu.h>
+
+struct context_tracking {
+       /*
+        * When active is false, probes are unset in order
+        * to minimize overhead: TIF flags are cleared
+        * and calls to user_enter/exit are ignored. This
+        * may be further optimized using static keys.
+        */
+       bool active;
+       enum {
+               IN_KERNEL = 0,
+               IN_USER,
+       } state;
+};
+
+DECLARE_PER_CPU(struct context_tracking, context_tracking);
+
+static inline bool context_tracking_in_user(void)
+{
+       return __this_cpu_read(context_tracking.state) == IN_USER;
+}
+
+static inline bool context_tracking_active(void)
+{
+       return __this_cpu_read(context_tracking.active);
+}
 
 extern void user_enter(void);
 extern void user_exit(void);
 extern void context_tracking_task_switch(struct task_struct *prev,
                                         struct task_struct *next);
 #else
+static inline bool context_tracking_in_user(void) { return false; }
 static inline void user_enter(void) { }
 static inline void user_exit(void) { }
 static inline void context_tracking_task_switch(struct task_struct *prev,
index ac3bbb5b95029caeea6546372ad2b6f35c0b83ad..1739510d89943df23f193d5fb04332f47cdaf958 100644 (file)
 #include <linux/cpumask.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
+#include <linux/kref.h>
 
 /**
  * struct cpu_rmap - CPU affinity reverse-map
+ * @refcount: kref for object
  * @size: Number of objects to be reverse-mapped
  * @used: Number of objects added
  * @obj: Pointer to array of object pointers
@@ -23,6 +25,7 @@
  *      based on affinity masks
  */
 struct cpu_rmap {
+       struct kref     refcount;
        u16             size, used;
        void            **obj;
        struct {
@@ -33,15 +36,7 @@ struct cpu_rmap {
 #define CPU_RMAP_DIST_INF 0xffff
 
 extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags);
-
-/**
- * free_cpu_rmap - free CPU affinity reverse-map
- * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL
- */
-static inline void free_cpu_rmap(struct cpu_rmap *rmap)
-{
-       kfree(rmap);
-}
+extern int cpu_rmap_put(struct cpu_rmap *rmap);
 
 extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj);
 extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index,
index 3711b34dc4f9fd8cafab9691bce55e617326dbb6..24cd1037b6d6f487d93ce79dfe0844887f949b9f 100644 (file)
@@ -126,9 +126,9 @@ struct cpuidle_driver {
        struct module           *owner;
        int                     refcnt;
 
-       unsigned int            power_specified:1;
        /* set to 1 to use the core cpuidle time keeping (for all states). */
        unsigned int            en_core_tk_irqen:1;
+       /* states array must be ordered in decreasing power consumption */
        struct cpuidle_state    states[CPUIDLE_STATE_MAX];
        int                     state_count;
        int                     safe_state_index;
index abb2cd50f6b26ace7da7a554527087d4685d3e76..04421e82536596c5aeb7a28b35e142556c821598 100644 (file)
@@ -128,7 +128,6 @@ struct cred {
        struct key      *process_keyring; /* keyring private to this process */
        struct key      *thread_keyring; /* keyring private to this thread */
        struct key      *request_key_auth; /* assumed request_key authority */
-       struct thread_group_cred *tgcred; /* thread-group shared credentials */
 #endif
 #ifdef CONFIG_SECURITY
        void            *security;      /* subjective LSM security */
index 59200795482eebccde8497372c82d1aca0cadd40..c1754b59ddd3d7bb2406590434d656c379bb0346 100644 (file)
@@ -202,7 +202,6 @@ struct dentry_operations {
 #define DCACHE_MOUNTED         0x10000 /* is a mountpoint */
 #define DCACHE_NEED_AUTOMOUNT  0x20000 /* handle automount on this dir */
 #define DCACHE_MANAGE_TRANSIT  0x40000 /* manage transit from this dirent */
-#define DCACHE_NEED_LOOKUP     0x80000 /* dentry requires i_op->lookup */
 #define DCACHE_MANAGED_DENTRY \
        (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
 
@@ -408,13 +407,6 @@ static inline bool d_mountpoint(struct dentry *dentry)
        return dentry->d_flags & DCACHE_MOUNTED;
 }
 
-static inline bool d_need_lookup(struct dentry *dentry)
-{
-       return dentry->d_flags & DCACHE_NEED_LOOKUP;
-}
-
-extern void d_clear_need_lookup(struct dentry *dentry);
-
 extern int sysctl_vfs_cache_pressure;
 
 #endif /* __LINUX_DCACHE_H */
index 38d27a10aa5d9f922a14dd5746b9e29f34bce633..bf6afa2fc432ba5d2cbdba3f1940e31e33b051b3 100644 (file)
@@ -23,7 +23,6 @@ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
 union map_info {
        void *ptr;
        unsigned long long ll;
-       unsigned target_request_nr;
 };
 
 /*
@@ -46,8 +45,7 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti);
  * = 1: simple remap complete
  * = 2: The target wants to push back the io
  */
-typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
-                         union map_info *map_context);
+typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio);
 typedef int (*dm_map_request_fn) (struct dm_target *ti, struct request *clone,
                                  union map_info *map_context);
 
@@ -60,8 +58,7 @@ typedef int (*dm_map_request_fn) (struct dm_target *ti, struct request *clone,
  * 2   : The target wants to push back the io
  */
 typedef int (*dm_endio_fn) (struct dm_target *ti,
-                           struct bio *bio, int error,
-                           union map_info *map_context);
+                           struct bio *bio, int error);
 typedef int (*dm_request_endio_fn) (struct dm_target *ti,
                                    struct request *clone, int error,
                                    union map_info *map_context);
@@ -193,18 +190,30 @@ struct dm_target {
         * A number of zero-length barrier requests that will be submitted
         * to the target for the purpose of flushing cache.
         *
-        * The request number will be placed in union map_info->target_request_nr.
+        * The request number can be accessed with dm_bio_get_target_request_nr.
         * It is a responsibility of the target driver to remap these requests
         * to the real underlying devices.
         */
        unsigned num_flush_requests;
 
        /*
-        * The number of discard requests that will be submitted to the
-        * target.  map_info->request_nr is used just like num_flush_requests.
+        * The number of discard requests that will be submitted to the target.
+        * The request number can be accessed with dm_bio_get_target_request_nr.
         */
        unsigned num_discard_requests;
 
+       /*
+        * The number of WRITE SAME requests that will be submitted to the target.
+        * The request number can be accessed with dm_bio_get_target_request_nr.
+        */
+       unsigned num_write_same_requests;
+
+       /*
+        * The minimum number of extra bytes allocated in each bio for the
+        * target to use.  dm_per_bio_data returns the data location.
+        */
+       unsigned per_bio_data_size;
+
        /* target specific data */
        void *private;
 
@@ -241,6 +250,36 @@ struct dm_target_callbacks {
        int (*congested_fn) (struct dm_target_callbacks *, int);
 };
 
+/*
+ * For bio-based dm.
+ * One of these is allocated for each bio.
+ * This structure shouldn't be touched directly by target drivers.
+ * It is here so that we can inline dm_per_bio_data and
+ * dm_bio_from_per_bio_data
+ */
+struct dm_target_io {
+       struct dm_io *io;
+       struct dm_target *ti;
+       union map_info info;
+       unsigned target_request_nr;
+       struct bio clone;
+};
+
+static inline void *dm_per_bio_data(struct bio *bio, size_t data_size)
+{
+       return (char *)bio - offsetof(struct dm_target_io, clone) - data_size;
+}
+
+static inline struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size)
+{
+       return (struct bio *)((char *)data + data_size + offsetof(struct dm_target_io, clone));
+}
+
+static inline unsigned dm_bio_get_target_request_nr(const struct bio *bio)
+{
+       return container_of(bio, struct dm_target_io, clone)->target_request_nr;
+}
+
 int dm_register_target(struct target_type *t);
 void dm_unregister_target(struct target_type *t);
 
index 8b84916dc6719ce46430fa791aa27c0bf8b16835..7a9498ab3c2d10dedf8af5c5dae3b2fd56753684 100644 (file)
@@ -618,18 +618,30 @@ extern int __init efi_setup_pcdp_console(char *);
 #endif
 
 /*
- * We play games with efi_enabled so that the compiler will, if possible, remove
- * EFI-related code altogether.
+ * We play games with efi_enabled so that the compiler will, if
+ * possible, remove EFI-related code altogether.
  */
+#define EFI_BOOT               0       /* Were we booted from EFI? */
+#define EFI_SYSTEM_TABLES      1       /* Can we use EFI system tables? */
+#define EFI_CONFIG_TABLES      2       /* Can we use EFI config tables? */
+#define EFI_RUNTIME_SERVICES   3       /* Can we use runtime services? */
+#define EFI_MEMMAP             4       /* Can we use EFI memory map? */
+#define EFI_64BIT              5       /* Is the firmware 64-bit? */
+
 #ifdef CONFIG_EFI
 # ifdef CONFIG_X86
-   extern int efi_enabled;
-   extern bool efi_64bit;
+extern int efi_enabled(int facility);
 # else
-#  define efi_enabled 1
+static inline int efi_enabled(int facility)
+{
+       return 1;
+}
 # endif
 #else
-# define efi_enabled 0
+static inline int efi_enabled(int facility)
+{
+       return 0;
+}
 #endif
 
 /*
index c7e6b6392ab8e28a92d69b17ea17a88c72a935a3..5b9b5b317180ceff7ac1d3d31e639e66c2f9b80f 100644 (file)
@@ -83,6 +83,11 @@ enum fid_type {
         * 64 bit parent inode number.
         */
        FILEID_NILFS_WITH_PARENT = 0x62,
+
+       /*
+        * Filesystems must not use 0xff file ID.
+        */
+       FILEID_INVALID = 0xff,
 };
 
 struct fid {
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
new file mode 100644 (file)
index 0000000..f9a12f6
--- /dev/null
@@ -0,0 +1,413 @@
+/**
+ * include/linux/f2fs_fs.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.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 _LINUX_F2FS_FS_H
+#define _LINUX_F2FS_FS_H
+
+#include <linux/pagemap.h>
+#include <linux/types.h>
+
+#define F2FS_SUPER_OFFSET              1024    /* byte-size offset */
+#define F2FS_LOG_SECTOR_SIZE           9       /* 9 bits for 512 byte */
+#define F2FS_LOG_SECTORS_PER_BLOCK     3       /* 4KB: F2FS_BLKSIZE */
+#define F2FS_BLKSIZE                   4096    /* support only 4KB block */
+#define F2FS_MAX_EXTENSION             64      /* # of extension entries */
+
+#define NULL_ADDR              0x0U
+#define NEW_ADDR               -1U
+
+#define F2FS_ROOT_INO(sbi)     (sbi->root_ino_num)
+#define F2FS_NODE_INO(sbi)     (sbi->node_ino_num)
+#define F2FS_META_INO(sbi)     (sbi->meta_ino_num)
+
+/* This flag is used by node and meta inodes, and by recovery */
+#define GFP_F2FS_ZERO  (GFP_NOFS | __GFP_ZERO)
+
+/*
+ * For further optimization on multi-head logs, on-disk layout supports maximum
+ * 16 logs by default. The number, 16, is expected to cover all the cases
+ * enoughly. The implementaion currently uses no more than 6 logs.
+ * Half the logs are used for nodes, and the other half are used for data.
+ */
+#define MAX_ACTIVE_LOGS        16
+#define MAX_ACTIVE_NODE_LOGS   8
+#define MAX_ACTIVE_DATA_LOGS   8
+
+/*
+ * For superblock
+ */
+struct f2fs_super_block {
+       __le32 magic;                   /* Magic Number */
+       __le16 major_ver;               /* Major Version */
+       __le16 minor_ver;               /* Minor Version */
+       __le32 log_sectorsize;          /* log2 sector size in bytes */
+       __le32 log_sectors_per_block;   /* log2 # of sectors per block */
+       __le32 log_blocksize;           /* log2 block size in bytes */
+       __le32 log_blocks_per_seg;      /* log2 # of blocks per segment */
+       __le32 segs_per_sec;            /* # of segments per section */
+       __le32 secs_per_zone;           /* # of sections per zone */
+       __le32 checksum_offset;         /* checksum offset inside super block */
+       __le64 block_count;             /* total # of user blocks */
+       __le32 section_count;           /* total # of sections */
+       __le32 segment_count;           /* total # of segments */
+       __le32 segment_count_ckpt;      /* # of segments for checkpoint */
+       __le32 segment_count_sit;       /* # of segments for SIT */
+       __le32 segment_count_nat;       /* # of segments for NAT */
+       __le32 segment_count_ssa;       /* # of segments for SSA */
+       __le32 segment_count_main;      /* # of segments for main area */
+       __le32 segment0_blkaddr;        /* start block address of segment 0 */
+       __le32 cp_blkaddr;              /* start block address of checkpoint */
+       __le32 sit_blkaddr;             /* start block address of SIT */
+       __le32 nat_blkaddr;             /* start block address of NAT */
+       __le32 ssa_blkaddr;             /* start block address of SSA */
+       __le32 main_blkaddr;            /* start block address of main area */
+       __le32 root_ino;                /* root inode number */
+       __le32 node_ino;                /* node inode number */
+       __le32 meta_ino;                /* meta inode number */
+       __u8 uuid[16];                  /* 128-bit uuid for volume */
+       __le16 volume_name[512];        /* volume name */
+       __le32 extension_count;         /* # of extensions below */
+       __u8 extension_list[F2FS_MAX_EXTENSION][8];     /* extension array */
+} __packed;
+
+/*
+ * For checkpoint
+ */
+#define CP_ERROR_FLAG          0x00000008
+#define CP_COMPACT_SUM_FLAG    0x00000004
+#define CP_ORPHAN_PRESENT_FLAG 0x00000002
+#define CP_UMOUNT_FLAG         0x00000001
+
+struct f2fs_checkpoint {
+       __le64 checkpoint_ver;          /* checkpoint block version number */
+       __le64 user_block_count;        /* # of user blocks */
+       __le64 valid_block_count;       /* # of valid blocks in main area */
+       __le32 rsvd_segment_count;      /* # of reserved segments for gc */
+       __le32 overprov_segment_count;  /* # of overprovision segments */
+       __le32 free_segment_count;      /* # of free segments in main area */
+
+       /* information of current node segments */
+       __le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
+       __le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
+       /* information of current data segments */
+       __le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
+       __le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
+       __le32 ckpt_flags;              /* Flags : umount and journal_present */
+       __le32 cp_pack_total_block_count;       /* total # of one cp pack */
+       __le32 cp_pack_start_sum;       /* start block number of data summary */
+       __le32 valid_node_count;        /* Total number of valid nodes */
+       __le32 valid_inode_count;       /* Total number of valid inodes */
+       __le32 next_free_nid;           /* Next free node number */
+       __le32 sit_ver_bitmap_bytesize; /* Default value 64 */
+       __le32 nat_ver_bitmap_bytesize; /* Default value 256 */
+       __le32 checksum_offset;         /* checksum offset inside cp block */
+       __le64 elapsed_time;            /* mounted time */
+       /* allocation type of current segment */
+       unsigned char alloc_type[MAX_ACTIVE_LOGS];
+
+       /* SIT and NAT version bitmap */
+       unsigned char sit_nat_version_bitmap[1];
+} __packed;
+
+/*
+ * For orphan inode management
+ */
+#define F2FS_ORPHANS_PER_BLOCK 1020
+
+struct f2fs_orphan_block {
+       __le32 ino[F2FS_ORPHANS_PER_BLOCK];     /* inode numbers */
+       __le32 reserved;        /* reserved */
+       __le16 blk_addr;        /* block index in current CP */
+       __le16 blk_count;       /* Number of orphan inode blocks in CP */
+       __le32 entry_count;     /* Total number of orphan nodes in current CP */
+       __le32 check_sum;       /* CRC32 for orphan inode block */
+} __packed;
+
+/*
+ * For NODE structure
+ */
+struct f2fs_extent {
+       __le32 fofs;            /* start file offset of the extent */
+       __le32 blk_addr;        /* start block address of the extent */
+       __le32 len;             /* lengh of the extent */
+} __packed;
+
+#define F2FS_MAX_NAME_LEN      256
+#define ADDRS_PER_INODE         923    /* Address Pointers in an Inode */
+#define ADDRS_PER_BLOCK         1018   /* Address Pointers in a Direct Block */
+#define NIDS_PER_BLOCK          1018   /* Node IDs in an Indirect Block */
+
+struct f2fs_inode {
+       __le16 i_mode;                  /* file mode */
+       __u8 i_advise;                  /* file hints */
+       __u8 i_reserved;                /* reserved */
+       __le32 i_uid;                   /* user ID */
+       __le32 i_gid;                   /* group ID */
+       __le32 i_links;                 /* links count */
+       __le64 i_size;                  /* file size in bytes */
+       __le64 i_blocks;                /* file size in blocks */
+       __le64 i_atime;                 /* access time */
+       __le64 i_ctime;                 /* change time */
+       __le64 i_mtime;                 /* modification time */
+       __le32 i_atime_nsec;            /* access time in nano scale */
+       __le32 i_ctime_nsec;            /* change time in nano scale */
+       __le32 i_mtime_nsec;            /* modification time in nano scale */
+       __le32 i_generation;            /* file version (for NFS) */
+       __le32 i_current_depth;         /* only for directory depth */
+       __le32 i_xattr_nid;             /* nid to save xattr */
+       __le32 i_flags;                 /* file attributes */
+       __le32 i_pino;                  /* parent inode number */
+       __le32 i_namelen;               /* file name length */
+       __u8 i_name[F2FS_MAX_NAME_LEN]; /* file name for SPOR */
+
+       struct f2fs_extent i_ext;       /* caching a largest extent */
+
+       __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */
+
+       __le32 i_nid[5];                /* direct(2), indirect(2),
+                                               double_indirect(1) node id */
+} __packed;
+
+struct direct_node {
+       __le32 addr[ADDRS_PER_BLOCK];   /* array of data block address */
+} __packed;
+
+struct indirect_node {
+       __le32 nid[NIDS_PER_BLOCK];     /* array of data block address */
+} __packed;
+
+enum {
+       COLD_BIT_SHIFT = 0,
+       FSYNC_BIT_SHIFT,
+       DENT_BIT_SHIFT,
+       OFFSET_BIT_SHIFT
+};
+
+struct node_footer {
+       __le32 nid;             /* node id */
+       __le32 ino;             /* inode nunmber */
+       __le32 flag;            /* include cold/fsync/dentry marks and offset */
+       __le64 cp_ver;          /* checkpoint version */
+       __le32 next_blkaddr;    /* next node page block address */
+} __packed;
+
+struct f2fs_node {
+       /* can be one of three types: inode, direct, and indirect types */
+       union {
+               struct f2fs_inode i;
+               struct direct_node dn;
+               struct indirect_node in;
+       };
+       struct node_footer footer;
+} __packed;
+
+/*
+ * For NAT entries
+ */
+#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry))
+
+struct f2fs_nat_entry {
+       __u8 version;           /* latest version of cached nat entry */
+       __le32 ino;             /* inode number */
+       __le32 block_addr;      /* block address */
+} __packed;
+
+struct f2fs_nat_block {
+       struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
+} __packed;
+
+/*
+ * For SIT entries
+ *
+ * Each segment is 2MB in size by default so that a bitmap for validity of
+ * there-in blocks should occupy 64 bytes, 512 bits.
+ * Not allow to change this.
+ */
+#define SIT_VBLOCK_MAP_SIZE 64
+#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
+
+/*
+ * Note that f2fs_sit_entry->vblocks has the following bit-field information.
+ * [15:10] : allocation type such as CURSEG_XXXX_TYPE
+ * [9:0] : valid block count
+ */
+#define SIT_VBLOCKS_SHIFT      10
+#define SIT_VBLOCKS_MASK       ((1 << SIT_VBLOCKS_SHIFT) - 1)
+#define GET_SIT_VBLOCKS(raw_sit)                               \
+       (le16_to_cpu((raw_sit)->vblocks) & SIT_VBLOCKS_MASK)
+#define GET_SIT_TYPE(raw_sit)                                  \
+       ((le16_to_cpu((raw_sit)->vblocks) & ~SIT_VBLOCKS_MASK)  \
+        >> SIT_VBLOCKS_SHIFT)
+
+struct f2fs_sit_entry {
+       __le16 vblocks;                         /* reference above */
+       __u8 valid_map[SIT_VBLOCK_MAP_SIZE];    /* bitmap for valid blocks */
+       __le64 mtime;                           /* segment age for cleaning */
+} __packed;
+
+struct f2fs_sit_block {
+       struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
+} __packed;
+
+/*
+ * For segment summary
+ *
+ * One summary block contains exactly 512 summary entries, which represents
+ * exactly 2MB segment by default. Not allow to change the basic units.
+ *
+ * NOTE: For initializing fields, you must use set_summary
+ *
+ * - If data page, nid represents dnode's nid
+ * - If node page, nid represents the node page's nid.
+ *
+ * The ofs_in_node is used by only data page. It represents offset
+ * from node's page's beginning to get a data block address.
+ * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
+ */
+#define ENTRIES_IN_SUM         512
+#define        SUMMARY_SIZE            (7)     /* sizeof(struct summary) */
+#define        SUM_FOOTER_SIZE         (5)     /* sizeof(struct summary_footer) */
+#define SUM_ENTRY_SIZE         (SUMMARY_SIZE * ENTRIES_IN_SUM)
+
+/* a summary entry for a 4KB-sized block in a segment */
+struct f2fs_summary {
+       __le32 nid;             /* parent node id */
+       union {
+               __u8 reserved[3];
+               struct {
+                       __u8 version;           /* node version number */
+                       __le16 ofs_in_node;     /* block index in parent node */
+               } __packed;
+       };
+} __packed;
+
+/* summary block type, node or data, is stored to the summary_footer */
+#define SUM_TYPE_NODE          (1)
+#define SUM_TYPE_DATA          (0)
+
+struct summary_footer {
+       unsigned char entry_type;       /* SUM_TYPE_XXX */
+       __u32 check_sum;                /* summary checksum */
+} __packed;
+
+#define SUM_JOURNAL_SIZE       (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\
+                               SUM_ENTRY_SIZE)
+#define NAT_JOURNAL_ENTRIES    ((SUM_JOURNAL_SIZE - 2) /\
+                               sizeof(struct nat_journal_entry))
+#define NAT_JOURNAL_RESERVED   ((SUM_JOURNAL_SIZE - 2) %\
+                               sizeof(struct nat_journal_entry))
+#define SIT_JOURNAL_ENTRIES    ((SUM_JOURNAL_SIZE - 2) /\
+                               sizeof(struct sit_journal_entry))
+#define SIT_JOURNAL_RESERVED   ((SUM_JOURNAL_SIZE - 2) %\
+                               sizeof(struct sit_journal_entry))
+/*
+ * frequently updated NAT/SIT entries can be stored in the spare area in
+ * summary blocks
+ */
+enum {
+       NAT_JOURNAL = 0,
+       SIT_JOURNAL
+};
+
+struct nat_journal_entry {
+       __le32 nid;
+       struct f2fs_nat_entry ne;
+} __packed;
+
+struct nat_journal {
+       struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
+       __u8 reserved[NAT_JOURNAL_RESERVED];
+} __packed;
+
+struct sit_journal_entry {
+       __le32 segno;
+       struct f2fs_sit_entry se;
+} __packed;
+
+struct sit_journal {
+       struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
+       __u8 reserved[SIT_JOURNAL_RESERVED];
+} __packed;
+
+/* 4KB-sized summary block structure */
+struct f2fs_summary_block {
+       struct f2fs_summary entries[ENTRIES_IN_SUM];
+       union {
+               __le16 n_nats;
+               __le16 n_sits;
+       };
+       /* spare area is used by NAT or SIT journals */
+       union {
+               struct nat_journal nat_j;
+               struct sit_journal sit_j;
+       };
+       struct summary_footer footer;
+} __packed;
+
+/*
+ * For directory operations
+ */
+#define F2FS_DOT_HASH          0
+#define F2FS_DDOT_HASH         F2FS_DOT_HASH
+#define F2FS_MAX_HASH          (~((0x3ULL) << 62))
+#define F2FS_HASH_COL_BIT      ((0x1ULL) << 63)
+
+typedef __le32 f2fs_hash_t;
+
+/* One directory entry slot covers 8bytes-long file name */
+#define F2FS_NAME_LEN          8
+#define F2FS_NAME_LEN_BITS     3
+
+#define GET_DENTRY_SLOTS(x)    ((x + F2FS_NAME_LEN - 1) >> F2FS_NAME_LEN_BITS)
+
+/* the number of dentry in a block */
+#define NR_DENTRY_IN_BLOCK     214
+
+/* MAX level for dir lookup */
+#define MAX_DIR_HASH_DEPTH     63
+
+#define SIZE_OF_DIR_ENTRY      11      /* by byte */
+#define SIZE_OF_DENTRY_BITMAP  ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
+                                       BITS_PER_BYTE)
+#define SIZE_OF_RESERVED       (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
+                               F2FS_NAME_LEN) * \
+                               NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+
+/* One directory entry slot representing F2FS_NAME_LEN-sized file name */
+struct f2fs_dir_entry {
+       __le32 hash_code;       /* hash code of file name */
+       __le32 ino;             /* inode number */
+       __le16 name_len;        /* lengh of file name */
+       __u8 file_type;         /* file type */
+} __packed;
+
+/* 4KB-sized directory entry block */
+struct f2fs_dentry_block {
+       /* validity bitmap for directory entries in each block */
+       __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
+       __u8 reserved[SIZE_OF_RESERVED];
+       struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
+       __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_NAME_LEN];
+} __packed;
+
+/* file types used in inode_info->flags */
+enum {
+       F2FS_FT_UNKNOWN,
+       F2FS_FT_REG_FILE,
+       F2FS_FT_DIR,
+       F2FS_FT_CHRDEV,
+       F2FS_FT_BLKDEV,
+       F2FS_FT_FIFO,
+       F2FS_FT_SOCK,
+       F2FS_FT_SYMLINK,
+       F2FS_FT_MAX
+};
+
+#endif  /* _LINUX_F2FS_FS_H */
index a823d4be38e7590275be303d40840bf6bd9117e6..7617ee04f066e7b2852f95c0b1b690b2a92f533b 100644 (file)
@@ -1445,10 +1445,6 @@ static inline void sb_start_intwrite(struct super_block *sb)
 
 extern bool inode_owner_or_capable(const struct inode *inode);
 
-/* not quite ready to be deprecated, but... */
-extern void lock_super(struct super_block *);
-extern void unlock_super(struct super_block *);
-
 /*
  * VFS helper functions..
  */
@@ -1565,7 +1561,6 @@ struct inode_operations {
        int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
        int (*rename) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *);
-       void (*truncate) (struct inode *);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1999,6 +1994,7 @@ struct filename {
        bool                    separate; /* should "name" be freed? */
 };
 
+extern long vfs_truncate(struct path *, loff_t);
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
                       struct file *filp);
 extern int do_fallocate(struct file *file, int mode, loff_t offset,
index ce31408b1e47d6e6cfb81ad25a3ca0fdaefaef84..5dfa0aa216b66f410f591c58815a17b2302e8bf8 100644 (file)
@@ -75,6 +75,16 @@ extern wait_queue_head_t fscache_cache_cleared_wq;
 typedef void (*fscache_operation_release_t)(struct fscache_operation *op);
 typedef void (*fscache_operation_processor_t)(struct fscache_operation *op);
 
+enum fscache_operation_state {
+       FSCACHE_OP_ST_BLANK,            /* Op is not yet submitted */
+       FSCACHE_OP_ST_INITIALISED,      /* Op is initialised */
+       FSCACHE_OP_ST_PENDING,          /* Op is blocked from running */
+       FSCACHE_OP_ST_IN_PROGRESS,      /* Op is in progress */
+       FSCACHE_OP_ST_COMPLETE,         /* Op is complete */
+       FSCACHE_OP_ST_CANCELLED,        /* Op has been cancelled */
+       FSCACHE_OP_ST_DEAD              /* Op is now dead */
+};
+
 struct fscache_operation {
        struct work_struct      work;           /* record for async ops */
        struct list_head        pend_link;      /* link in object->pending_ops */
@@ -86,10 +96,10 @@ struct fscache_operation {
 #define FSCACHE_OP_MYTHREAD    0x0002  /* - processing is done be issuing thread, not pool */
 #define FSCACHE_OP_WAITING     4       /* cleared when op is woken */
 #define FSCACHE_OP_EXCLUSIVE   5       /* exclusive op, other ops must wait */
-#define FSCACHE_OP_DEAD                6       /* op is now dead */
-#define FSCACHE_OP_DEC_READ_CNT        7       /* decrement object->n_reads on destruction */
-#define FSCACHE_OP_KEEP_FLAGS  0xc0    /* flags to keep when repurposing an op */
+#define FSCACHE_OP_DEC_READ_CNT        6       /* decrement object->n_reads on destruction */
+#define FSCACHE_OP_KEEP_FLAGS  0x0070  /* flags to keep when repurposing an op */
 
+       enum fscache_operation_state state;
        atomic_t                usage;
        unsigned                debug_id;       /* debugging ID */
 
@@ -106,6 +116,7 @@ extern atomic_t fscache_op_debug_id;
 extern void fscache_op_work_func(struct work_struct *work);
 
 extern void fscache_enqueue_operation(struct fscache_operation *);
+extern void fscache_op_complete(struct fscache_operation *, bool);
 extern void fscache_put_operation(struct fscache_operation *);
 
 /**
@@ -122,6 +133,7 @@ static inline void fscache_operation_init(struct fscache_operation *op,
 {
        INIT_WORK(&op->work, fscache_op_work_func);
        atomic_set(&op->usage, 1);
+       op->state = FSCACHE_OP_ST_INITIALISED;
        op->debug_id = atomic_inc_return(&fscache_op_debug_id);
        op->processor = processor;
        op->release = release;
@@ -138,6 +150,7 @@ struct fscache_retrieval {
        void                    *context;       /* netfs read context (pinned) */
        struct list_head        to_do;          /* list of things to be done by the backend */
        unsigned long           start_time;     /* time at which retrieval started */
+       unsigned                n_pages;        /* number of pages to be retrieved */
 };
 
 typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op,
@@ -173,9 +186,23 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
        fscache_enqueue_operation(&op->op);
 }
 
+/**
+ * fscache_retrieval_complete - Record (partial) completion of a retrieval
+ * @op: The retrieval operation affected
+ * @n_pages: The number of pages to account for
+ */
+static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
+                                             int n_pages)
+{
+       op->n_pages -= n_pages;
+       if (op->n_pages <= 0)
+               fscache_op_complete(&op->op, true);
+}
+
 /**
  * fscache_put_retrieval - Drop a reference to a retrieval operation
  * @op: The retrieval operation affected
+ * @n_pages: The number of pages to account for
  *
  * Drop a reference to a retrieval operation.
  */
@@ -227,6 +254,9 @@ struct fscache_cache_ops {
        /* store the updated auxiliary data on an object */
        void (*update_object)(struct fscache_object *object);
 
+       /* Invalidate an object */
+       void (*invalidate_object)(struct fscache_operation *op);
+
        /* discard the resources pinned by an object and effect retirement if
         * necessary */
        void (*drop_object)(struct fscache_object *object);
@@ -301,10 +331,29 @@ struct fscache_cookie {
 #define FSCACHE_COOKIE_PENDING_FILL    3       /* T if pending initial fill on object */
 #define FSCACHE_COOKIE_FILLING         4       /* T if filling object incrementally */
 #define FSCACHE_COOKIE_UNAVAILABLE     5       /* T if cookie is unavailable (error, etc) */
+#define FSCACHE_COOKIE_WAITING_ON_READS        6       /* T if cookie is waiting on reads */
+#define FSCACHE_COOKIE_INVALIDATING    7       /* T if cookie is being invalidated */
 };
 
 extern struct fscache_cookie fscache_fsdef_index;
 
+/*
+ * Event list for fscache_object::{event_mask,events}
+ */
+enum {
+       FSCACHE_OBJECT_EV_REQUEUE,      /* T if object should be requeued */
+       FSCACHE_OBJECT_EV_UPDATE,       /* T if object should be updated */
+       FSCACHE_OBJECT_EV_INVALIDATE,   /* T if cache requested object invalidation */
+       FSCACHE_OBJECT_EV_CLEARED,      /* T if accessors all gone */
+       FSCACHE_OBJECT_EV_ERROR,        /* T if fatal error occurred during processing */
+       FSCACHE_OBJECT_EV_RELEASE,      /* T if netfs requested object release */
+       FSCACHE_OBJECT_EV_RETIRE,       /* T if netfs requested object retirement */
+       FSCACHE_OBJECT_EV_WITHDRAW,     /* T if cache requested object withdrawal */
+       NR_FSCACHE_OBJECT_EVENTS
+};
+
+#define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1)
+
 /*
  * on-disk cache file or index handle
  */
@@ -317,6 +366,7 @@ struct fscache_object {
                /* active states */
                FSCACHE_OBJECT_AVAILABLE,       /* cleaning up object after creation */
                FSCACHE_OBJECT_ACTIVE,          /* object is usable */
+               FSCACHE_OBJECT_INVALIDATING,    /* object is invalidating */
                FSCACHE_OBJECT_UPDATING,        /* object is updating */
 
                /* terminal states */
@@ -332,10 +382,10 @@ struct fscache_object {
 
        int                     debug_id;       /* debugging ID */
        int                     n_children;     /* number of child objects */
-       int                     n_ops;          /* number of ops outstanding on object */
+       int                     n_ops;          /* number of extant ops on object */
        int                     n_obj_ops;      /* number of object ops outstanding on object */
        int                     n_in_progress;  /* number of ops in progress */
-       int                     n_exclusive;    /* number of exclusive ops queued */
+       int                     n_exclusive;    /* number of exclusive ops queued or in progress */
        atomic_t                n_reads;        /* number of read ops in progress */
        spinlock_t              lock;           /* state and operations lock */
 
@@ -343,14 +393,6 @@ struct fscache_object {
        unsigned long           event_mask;     /* events this object is interested in */
        unsigned long           events;         /* events to be processed by this object
                                                 * (order is important - using fls) */
-#define FSCACHE_OBJECT_EV_REQUEUE      0       /* T if object should be requeued */
-#define FSCACHE_OBJECT_EV_UPDATE       1       /* T if object should be updated */
-#define FSCACHE_OBJECT_EV_CLEARED      2       /* T if accessors all gone */
-#define FSCACHE_OBJECT_EV_ERROR                3       /* T if fatal error occurred during processing */
-#define FSCACHE_OBJECT_EV_RELEASE      4       /* T if netfs requested object release */
-#define FSCACHE_OBJECT_EV_RETIRE       5       /* T if netfs requested object retirement */
-#define FSCACHE_OBJECT_EV_WITHDRAW     6       /* T if cache requested object withdrawal */
-#define FSCACHE_OBJECT_EVENTS_MASK     0x7f    /* mask of all events*/
 
        unsigned long           flags;
 #define FSCACHE_OBJECT_LOCK            0       /* T if object is busy being processed */
@@ -504,6 +546,9 @@ extern void fscache_withdraw_cache(struct fscache_cache *cache);
 
 extern void fscache_io_error(struct fscache_cache *cache);
 
+extern void fscache_mark_page_cached(struct fscache_retrieval *op,
+                                    struct page *page);
+
 extern void fscache_mark_pages_cached(struct fscache_retrieval *op,
                                      struct pagevec *pagevec);
 
index 9ec20dec3353afa83478ef0509fb15309be5fca0..7a086235da4be1ab94a026e0a1be3728dc1304a7 100644 (file)
@@ -135,14 +135,14 @@ struct fscache_cookie_def {
         */
        void (*put_context)(void *cookie_netfs_data, void *context);
 
-       /* indicate pages that now have cache metadata retained
-        * - this function should mark the specified pages as now being cached
-        * - the pages will have been marked with PG_fscache before this is
+       /* indicate page that now have cache metadata retained
+        * - this function should mark the specified page as now being cached
+        * - the page will have been marked with PG_fscache before this is
         *   called, so this is optional
         */
-       void (*mark_pages_cached)(void *cookie_netfs_data,
-                                 struct address_space *mapping,
-                                 struct pagevec *cached_pvec);
+       void (*mark_page_cached)(void *cookie_netfs_data,
+                                struct address_space *mapping,
+                                struct page *page);
 
        /* indicate the cookie is no longer cached
         * - this function is called when the backing store currently caching
@@ -185,6 +185,8 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
 extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
 extern void __fscache_update_cookie(struct fscache_cookie *);
 extern int __fscache_attr_changed(struct fscache_cookie *);
+extern void __fscache_invalidate(struct fscache_cookie *);
+extern void __fscache_wait_on_invalidate(struct fscache_cookie *);
 extern int __fscache_read_or_alloc_page(struct fscache_cookie *,
                                        struct page *,
                                        fscache_rw_complete_t,
@@ -389,6 +391,42 @@ int fscache_attr_changed(struct fscache_cookie *cookie)
                return -ENOBUFS;
 }
 
+/**
+ * fscache_invalidate - Notify cache that an object needs invalidation
+ * @cookie: The cookie representing the cache object
+ *
+ * Notify the cache that an object is needs to be invalidated and that it
+ * should abort any retrievals or stores it is doing on the cache.  The object
+ * is then marked non-caching until such time as the invalidation is complete.
+ *
+ * This can be called with spinlocks held.
+ *
+ * See Documentation/filesystems/caching/netfs-api.txt for a complete
+ * description.
+ */
+static inline
+void fscache_invalidate(struct fscache_cookie *cookie)
+{
+       if (fscache_cookie_valid(cookie))
+               __fscache_invalidate(cookie);
+}
+
+/**
+ * fscache_wait_on_invalidate - Wait for invalidation to complete
+ * @cookie: The cookie representing the cache object
+ *
+ * Wait for the invalidation of an object to complete.
+ *
+ * See Documentation/filesystems/caching/netfs-api.txt for a complete
+ * description.
+ */
+static inline
+void fscache_wait_on_invalidate(struct fscache_cookie *cookie)
+{
+       if (fscache_cookie_valid(cookie))
+               __fscache_wait_on_invalidate(cookie);
+}
+
 /**
  * fscache_reserve_space - Reserve data space for a cached object
  * @cookie: The cookie representing the cache object
index 63d966d5c2ea7a382c2f42cc664c7804dec86f73..d5b0910d49615ee01cf3255818d99e78241cb09f 100644 (file)
@@ -88,9 +88,10 @@ struct fsnotify_event_private_data;
  *             if the group is interested in this event.
  * handle_event - main call for a group to handle an fs event
  * free_group_priv - called when a group refcnt hits 0 to clean up the private union
- * freeing-mark - this means that a mark has been flagged to die when everything
- *             finishes using it.  The function is supplied with what must be a
- *             valid group and inode to use to clean up.
+ * freeing_mark - called when a mark is being destroyed for some reason.  The group
+ *             MUST be holding a reference on each mark and that reference must be
+ *             dropped in this function.  inotify uses this function to send
+ *             userspace messages that marks have been removed.
  */
 struct fsnotify_ops {
        bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
@@ -141,12 +142,14 @@ struct fsnotify_group {
        unsigned int priority;
 
        /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
-       spinlock_t mark_lock;           /* protect marks_list */
+       struct mutex mark_mutex;        /* protect marks_list */
        atomic_t num_marks;             /* 1 for each mark and 1 for not being
                                         * past the point of no return when freeing
                                         * a group */
        struct list_head marks_list;    /* all inode marks for this group */
 
+       struct fasync_struct    *fsn_fa;    /* async notification */
+
        /* groups can define private fields here or use the void *private */
        union {
                void *private;
@@ -155,7 +158,6 @@ struct fsnotify_group {
                        spinlock_t      idr_lock;
                        struct idr      idr;
                        u32             last_wd;
-                       struct fasync_struct    *fa;    /* async notification */
                        struct user_struct      *user;
                } inotify_data;
 #endif
@@ -287,7 +289,6 @@ struct fsnotify_mark {
                struct fsnotify_inode_mark i;
                struct fsnotify_vfsmount_mark m;
        };
-       struct list_head free_g_list;   /* tmp list used when freeing this mark */
        __u32 ignored_mask;             /* events types to ignore */
 #define FSNOTIFY_MARK_FLAG_INODE               0x01
 #define FSNOTIFY_MARK_FLAG_VFSMOUNT            0x02
@@ -360,11 +361,16 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
 
 /* called from fsnotify listeners, such as fanotify or dnotify */
 
-/* get a reference to an existing or create a new group */
+/* create a new group */
 extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
+/* get reference to a group */
+extern void fsnotify_get_group(struct fsnotify_group *group);
 /* drop reference on a group from fsnotify_alloc_group */
 extern void fsnotify_put_group(struct fsnotify_group *group);
-
+/* destroy group */
+extern void fsnotify_destroy_group(struct fsnotify_group *group);
+/* fasync handler function */
+extern int fsnotify_fasync(int fd, struct file *file, int on);
 /* take a reference to an event */
 extern void fsnotify_get_event(struct fsnotify_event *event);
 extern void fsnotify_put_event(struct fsnotify_event *event);
@@ -405,8 +411,13 @@ extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask
 /* attach the mark to both the group and the inode */
 extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
                             struct inode *inode, struct vfsmount *mnt, int allow_dups);
-/* given a mark, flag it to be freed when all references are dropped */
-extern void fsnotify_destroy_mark(struct fsnotify_mark *mark);
+extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group,
+                                   struct inode *inode, struct vfsmount *mnt, int allow_dups);
+/* given a group and a mark, flag mark to be freed when all references are dropped */
+extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+                                 struct fsnotify_group *group);
+extern void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+                                        struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the vfsmount marks */
 extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the inode marks */
index 92691d85c32061f4d0acbe45ecccfcd78267240d..e5ca8ef50e9bf674e46fa58d7fff5f0424ab5bad 100644 (file)
@@ -74,7 +74,7 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
  * SAVE_REGS - The ftrace_ops wants regs saved at each function called
  *            and passed to the callback. If this flag is set, but the
  *            architecture does not support passing regs
- *            (ARCH_SUPPORTS_FTRACE_SAVE_REGS is not defined), then the
+ *            (CONFIG_DYNAMIC_FTRACE_WITH_REGS is not defined), then the
  *            ftrace_ops will fail to register, unless the next flag
  *            is set.
  * SAVE_REGS_IF_SUPPORTED - This is the same as SAVE_REGS, but if the
@@ -418,7 +418,7 @@ void ftrace_modify_all_code(int command);
 #endif
 
 #ifndef FTRACE_REGS_ADDR
-#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 # define FTRACE_REGS_ADDR ((unsigned long)ftrace_regs_caller)
 #else
 # define FTRACE_REGS_ADDR FTRACE_ADDR
@@ -480,7 +480,7 @@ extern int ftrace_make_nop(struct module *mod,
  */
 extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
 
-#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 /**
  * ftrace_modify_call - convert from one addr to another (no nop)
  * @rec: the mcount call site record
index a3d489531d83a7c396aaa6a24d09961eeae47929..13a54d0bdfa8afbe2cc29ec6bf8ce016c1b2306c 100644 (file)
@@ -49,7 +49,6 @@ struct trace_entry {
        unsigned char           flags;
        unsigned char           preempt_count;
        int                     pid;
-       int                     padding;
 };
 
 #define FTRACE_MAX_EVENT                                               \
@@ -84,6 +83,9 @@ struct trace_iterator {
        long                    idx;
 
        cpumask_var_t           started;
+
+       /* it's true when current open file is snapshot */
+       bool                    snapshot;
 };
 
 enum trace_iter_flags {
@@ -272,7 +274,7 @@ extern int trace_define_field(struct ftrace_event_call *call, const char *type,
 extern int trace_add_event_call(struct ftrace_event_call *call);
 extern void trace_remove_event_call(struct ftrace_event_call *call);
 
-#define is_signed_type(type)   (((type)(-1)) < 0)
+#define is_signed_type(type)   (((type)(-1)) < (type)0)
 
 int trace_set_clr_event(const char *system, const char *event, int set);
 
index 624ef3f45c8efe51667a6d2d9f558e3d6351736f..29eb805ea4a6b2c98236bbd0f24cc00a45ec53df 100644 (file)
@@ -153,7 +153,7 @@ extern void rcu_nmi_exit(void);
  */
 #define __irq_enter()                                  \
        do {                                            \
-               vtime_account_irq_enter(current);       \
+               account_irq_enter_time(current);        \
                add_preempt_count(HARDIRQ_OFFSET);      \
                trace_hardirq_enter();                  \
        } while (0)
@@ -169,7 +169,7 @@ extern void irq_enter(void);
 #define __irq_exit()                                   \
        do {                                            \
                trace_hardirq_exit();                   \
-               vtime_account_irq_exit(current);        \
+               account_irq_exit_time(current);         \
                sub_preempt_count(HARDIRQ_OFFSET);      \
        } while (0)
 
@@ -180,10 +180,10 @@ extern void irq_exit(void);
 
 #define nmi_enter()                                            \
        do {                                                    \
+               lockdep_off();                                  \
                ftrace_nmi_enter();                             \
                BUG_ON(in_nmi());                               \
                add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
-               lockdep_off();                                  \
                rcu_nmi_enter();                                \
                trace_hardirq_enter();                          \
        } while (0)
@@ -192,10 +192,10 @@ extern void irq_exit(void);
        do {                                                    \
                trace_hardirq_exit();                           \
                rcu_nmi_exit();                                 \
-               lockdep_on();                                   \
                BUG_ON(!in_nmi());                              \
                sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
                ftrace_nmi_exit();                              \
+               lockdep_on();                                   \
        } while (0)
 
 #endif /* LINUX_HARDIRQ_H */
diff --git a/include/linux/hdlc/Kbuild b/include/linux/hdlc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index a799273714accff40c0bf54850389b095746ff83..10ed4f4364589d5d810385e144ab7138fefc13ba 100644 (file)
 
 #define __exit          __section(.exit.text) __exitused __cold notrace
 
-/* Used for HOTPLUG, but that is always enabled now, so just make them noops */
-#define __devinit
-#define __devinitdata
-#define __devinitconst
-#define __devexit
-#define __devexitdata
-#define __devexitconst
-
 /* Used for HOTPLUG_CPU */
 #define __cpuinit        __section(.cpuinit.text) __cold notrace
 #define __cpuinitdata    __section(.cpuinit.data)
@@ -337,18 +329,6 @@ void __init parse_early_options(char *cmdline);
 #define __INITRODATA_OR_MODULE __INITRODATA
 #endif /*CONFIG_MODULES*/
 
-/* Functions marked as __devexit may be discarded at kernel link time, depending
-   on config options.  Newer versions of binutils detect references from
-   retained sections to discarded sections and flag an error.  Pointers to
-   __devexit functions must use __devexit_p(function_name), the wrapper will
-   insert either the function_name or NULL, depending on the config options.
- */
-#if defined(MODULE) || defined(CONFIG_HOTPLUG)
-#define __devexit_p(x) x
-#else
-#define __devexit_p(x) NULL
-#endif
-
 #ifdef MODULE
 #define __exit_p(x) x
 #else
index 6d087c5f57f79e5a22ffa9a440061b5079838f53..5cd0f09499271283795bb49a7b18b8ed3f1930cd 100644 (file)
@@ -10,7 +10,9 @@
 #include <linux/pid_namespace.h>
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
+#include <linux/seqlock.h>
 #include <net/net_namespace.h>
+#include <linux/sched/rt.h>
 
 #ifdef CONFIG_SMP
 # define INIT_PUSHABLE_TASKS(tsk)                                      \
@@ -141,6 +143,15 @@ extern struct task_group root_task_group;
 # define INIT_PERF_EVENTS(tsk)
 #endif
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+# define INIT_VTIME(tsk)                                               \
+       .vtime_seqlock = __SEQLOCK_UNLOCKED(tsk.vtime_seqlock), \
+       .vtime_snap = 0,                                \
+       .vtime_snap_whence = VTIME_SYS,
+#else
+# define INIT_VTIME(tsk)
+#endif
+
 #define INIT_TASK_COMM "swapper"
 
 /*
@@ -210,6 +221,7 @@ extern struct task_group root_task_group;
        INIT_TRACE_RECURSION                                            \
        INIT_TASK_RCU_PREEMPT(tsk)                                      \
        INIT_CPUSET_SEQ                                                 \
+       INIT_VTIME(tsk)                                                 \
 }
 
 
index 5e4e6170f43a5ef672ddd0d28694849669e310cb..5fa5afeeb7599d6c0f05d7fb59796cf153a614a9 100644 (file)
@@ -268,11 +268,6 @@ struct irq_affinity_notify {
 extern int
 irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
 
-static inline void irq_run_affinity_notifiers(void)
-{
-       flush_scheduled_work();
-}
-
 #else /* CONFIG_SMP */
 
 static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m)
index fe771978e87759000562162835f32fa66b4b4571..ae221a7b509237a649e8ccfed988265e22f07fa5 100644 (file)
@@ -24,6 +24,7 @@ struct ipc_ids {
        unsigned short seq_max;
        struct rw_semaphore rw_mutex;
        struct idr ipcs_idr;
+       int next_id;
 };
 
 struct ipc_namespace {
index fdf2c4a238cc605390b63bcdefb1f41533ae426b..bc4e06611958ce476c749b79b63b747a97390ea1 100644 (file)
@@ -509,8 +509,11 @@ static inline void irq_set_percpu_devid_flags(unsigned int irq)
 
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
+extern unsigned int __create_irqs(unsigned int from, unsigned int count,
+                                 int node);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
+extern void destroy_irqs(unsigned int irq, unsigned int count);
 
 /*
  * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and
@@ -528,6 +531,8 @@ extern int irq_set_handler_data(unsigned int irq, void *data);
 extern int irq_set_chip_data(unsigned int irq, void *data);
 extern int irq_set_irq_type(unsigned int irq, unsigned int type);
 extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
+extern int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
+                               struct msi_desc *entry);
 extern struct irq_data *irq_get_irq_data(unsigned int irq);
 
 static inline struct irq_chip *irq_get_chip(unsigned int irq)
@@ -590,6 +595,9 @@ int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
 #define irq_alloc_desc_from(from, node)                \
        irq_alloc_descs(-1, from, 1, node)
 
+#define irq_alloc_descs_from(from, cnt, node)  \
+       irq_alloc_descs(-1, from, cnt, node)
+
 void irq_free_descs(unsigned int irq, unsigned int cnt);
 int irq_reserve_irqs(unsigned int from, unsigned int cnt);
 
index 6a9e8f5399e2ab137b3c251eb49349fdc6b333ac..f5dbce50466e6546fc72f4084ed0d0c91d91fe1e 100644 (file)
@@ -3,6 +3,20 @@
 
 #include <linux/llist.h>
 
+/*
+ * An entry can be in one of four states:
+ *
+ * free             NULL, 0 -> {claimed}       : free to be used
+ * claimed   NULL, 3 -> {pending}       : claimed to be enqueued
+ * pending   next, 3 -> {busy}          : queued, pending callback
+ * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
+ */
+
+#define IRQ_WORK_PENDING       1UL
+#define IRQ_WORK_BUSY          2UL
+#define IRQ_WORK_FLAGS         3UL
+#define IRQ_WORK_LAZY          4UL /* Doesn't want IPI, wait for tick */
+
 struct irq_work {
        unsigned long flags;
        struct llist_node llnode;
@@ -16,8 +30,14 @@ void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
        work->func = func;
 }
 
-bool irq_work_queue(struct irq_work *work);
+void irq_work_queue(struct irq_work *work);
 void irq_work_run(void);
 void irq_work_sync(struct irq_work *work);
 
+#ifdef CONFIG_IRQ_WORK
+bool irq_work_needs_cpu(void);
+#else
+static bool irq_work_needs_cpu(void) { return false; }
+#endif
+
 #endif /* _LINUX_IRQ_WORK_H */
index 1be23d9fdacb5151a6af6f8b30b2086e50c50bb1..e30b66346942a90a4c79cdc5a0362b3899db0521 100644 (file)
@@ -1098,7 +1098,7 @@ void               jbd2_journal_set_triggers(struct buffer_head *,
 extern int      jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
 extern int      jbd2_journal_forget (handle_t *, struct buffer_head *);
 extern void     journal_sync_buffer (struct buffer_head *);
-extern void     jbd2_journal_invalidatepage(journal_t *,
+extern int      jbd2_journal_invalidatepage(journal_t *,
                                struct page *, unsigned long);
 extern int      jbd2_journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
 extern int      jbd2_journal_stop(handle_t *);
index d140e8fb075f7dca2dba8ed0dd91fb5cb51938c1..c566927efcbd254efa6c30c0a82fd10ccb11f363 100644 (file)
 
 /*
  * Divide positive or negative dividend by positive divisor and round
- * to closest integer. Result is undefined for negative divisors.
+ * to closest integer. Result is undefined for negative divisors and
+ * for negative dividends if the divisor variable type is unsigned.
  */
 #define DIV_ROUND_CLOSEST(x, divisor)(                 \
 {                                                      \
        typeof(x) __x = x;                              \
        typeof(divisor) __d = divisor;                  \
-       (((typeof(x))-1) > 0 || (__x) > 0) ?            \
+       (((typeof(x))-1) > 0 ||                         \
+        ((typeof(divisor))-1) > 0 || (__x) > 0) ?      \
                (((__x) + ((__d) / 2)) / (__d)) :       \
                (((__x) - ((__d) / 2)) / (__d));        \
 }                                                      \
index 66b70780e910dfb846241bc3b70ce1a97aeeee47..ed5f6ed6eb772797ea1c7eb0e98e46f55dbcf027 100644 (file)
@@ -127,7 +127,7 @@ extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t)
 extern void account_steal_time(cputime_t);
 extern void account_idle_time(cputime_t);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 static inline void account_process_tick(struct task_struct *tsk, int user)
 {
        vtime_account_user(tsk);
index 23755ba42abc456a06ffd663d0b3817570c1e7cb..4b6ef4d33cc26b65e242fb8f086cd3754672d962 100644 (file)
 #define KPROBE_REENTER         0x00000004
 #define KPROBE_HIT_SSDONE      0x00000008
 
-/*
- * If function tracer is enabled and the arch supports full
- * passing of pt_regs to function tracing, then kprobes can
- * optimize on top of function tracing.
- */
-#if defined(CONFIG_FUNCTION_TRACER) && defined(ARCH_SUPPORTS_FTRACE_SAVE_REGS) \
-       && defined(ARCH_SUPPORTS_KPROBES_ON_FTRACE)
-# define KPROBES_CAN_USE_FTRACE
-#endif
-
 /* Attach to insert probes on any functions which should be ignored*/
 #define __kprobes      __attribute__((__section__(".kprobes.text")))
 
@@ -316,7 +306,7 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
 #endif
 
 #endif /* CONFIG_OPTPROBES */
-#ifdef KPROBES_CAN_USE_FTRACE
+#ifdef CONFIG_KPROBES_ON_FTRACE
 extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
                                  struct ftrace_ops *ops, struct pt_regs *regs);
 extern int arch_prepare_kprobe_ftrace(struct kprobe *p);
index 2c497ab0d03d41f7c8e85531a46776cba47f8d14..b7996a768eb2c656417fdb082f62871a89fc6f1d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/rcupdate.h>
 #include <linux/ratelimit.h>
 #include <linux/err.h>
+#include <linux/irqflags.h>
 #include <asm/signal.h>
 
 #include <linux/kvm.h>
@@ -740,15 +741,52 @@ static inline int kvm_deassign_device(struct kvm *kvm,
 }
 #endif /* CONFIG_IOMMU_API */
 
-static inline void kvm_guest_enter(void)
+static inline void __guest_enter(void)
 {
-       BUG_ON(preemptible());
        /*
         * This is running in ioctl context so we can avoid
         * the call to vtime_account() with its unnecessary idle check.
         */
-       vtime_account_system_irqsafe(current);
+       vtime_account_system(current);
        current->flags |= PF_VCPU;
+}
+
+static inline void __guest_exit(void)
+{
+       /*
+        * This is running in ioctl context so we can avoid
+        * the call to vtime_account() with its unnecessary idle check.
+        */
+       vtime_account_system(current);
+       current->flags &= ~PF_VCPU;
+}
+
+#ifdef CONFIG_CONTEXT_TRACKING
+extern void guest_enter(void);
+extern void guest_exit(void);
+
+#else /* !CONFIG_CONTEXT_TRACKING */
+static inline void guest_enter(void)
+{
+       __guest_enter();
+}
+
+static inline void guest_exit(void)
+{
+       __guest_exit();
+}
+#endif /* !CONFIG_CONTEXT_TRACKING */
+
+static inline void kvm_guest_enter(void)
+{
+       unsigned long flags;
+
+       BUG_ON(preemptible());
+
+       local_irq_save(flags);
+       guest_enter();
+       local_irq_restore(flags);
+
        /* KVM does not hold any references to rcu protected data when it
         * switches CPU into a guest mode. In fact switching to a guest mode
         * is very similar to exiting to userspase from rcu point of view. In
@@ -761,12 +799,11 @@ static inline void kvm_guest_enter(void)
 
 static inline void kvm_guest_exit(void)
 {
-       /*
-        * This is running in ioctl context so we can avoid
-        * the call to vtime_account() with its unnecessary idle check.
-        */
-       vtime_account_system_irqsafe(current);
-       current->flags &= ~PF_VCPU;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       guest_exit();
+       local_irq_restore(flags);
 }
 
 /*
index 83ba0ab2c915c1bdb66fc7c922343b3f027ad120..649e5f86b5f00928b94e9f8515bf18f286e6b6e4 100644 (file)
@@ -652,8 +652,8 @@ struct ata_device {
                u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
        };
 
-       /* Identify Device Data Log (30h), SATA Settings (page 08h) */
-       u8                      sata_settings[ATA_SECT_SIZE];
+       /* DEVSLP Timing Variables from Identify Device Data Log */
+       u8                      devslp_timing[ATA_LOG_DEVSLP_SIZE];
 
        /* error history */
        int                     spdn_cnt;
index a5199f6d0e82592dde0e4ba7908b1d1b70323483..d0ab98f73d380c67f2572a0b9536719e17325ca9 100644 (file)
@@ -124,6 +124,31 @@ static inline void init_llist_head(struct llist_head *list)
             &(pos)->member != NULL;                                    \
             (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
 
+/**
+ * llist_for_each_entry_safe - iterate safely against remove over some entries
+ * of lock-less list of given type.
+ * @pos:       the type * to use as a loop cursor.
+ * @n:         another type * to use as a temporary storage.
+ * @node:      the fist entry of deleted list entries.
+ * @member:    the name of the llist_node with the struct.
+ *
+ * In general, some entries of the lock-less list can be traversed
+ * safely only after being removed from list, so start with an entry
+ * instead of list head. This variant allows removal of entries
+ * as we iterate.
+ *
+ * If being used on entries deleted from lock-less list directly, the
+ * traverse order is from the newest to the oldest added entry.  If
+ * you want to traverse from the oldest to the newest, you must
+ * reverse the order by yourself before traversing.
+ */
+#define llist_for_each_entry_safe(pos, n, node, member)                \
+       for ((pos) = llist_entry((node), typeof(*(pos)), member),       \
+            (n) = (pos)->member.next;                                  \
+            &(pos)->member != NULL;                                    \
+            (pos) = llist_entry(n, typeof(*(pos)), member),            \
+            (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL)
+
 /**
  * llist_empty - tests whether a lock-less list is empty
  * @head:      the list to test
index 00e46376e28f73d33bdfbf56480932dfa12eee9f..2bca44b0893c787bdb463a8f42e7306e02edf87f 100644 (file)
@@ -524,14 +524,17 @@ static inline void print_irqtrace_events(struct task_struct *curr)
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 # ifdef CONFIG_PROVE_LOCKING
 #  define rwsem_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 2, NULL, i)
+#  define rwsem_acquire_nest(l, s, t, n, i)    lock_acquire(l, s, t, 0, 2, n, i)
 #  define rwsem_acquire_read(l, s, t, i)       lock_acquire(l, s, t, 1, 2, NULL, i)
 # else
 #  define rwsem_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 1, NULL, i)
+#  define rwsem_acquire_nest(l, s, t, n, i)    lock_acquire(l, s, t, 0, 1, n, i)
 #  define rwsem_acquire_read(l, s, t, i)       lock_acquire(l, s, t, 1, 1, NULL, i)
 # endif
 # define rwsem_release(l, n, i)                        lock_release(l, n, i)
 #else
 # define rwsem_acquire(l, s, t, i)             do { } while (0)
+# define rwsem_acquire_nest(l, s, t, n, i)     do { } while (0)
 # define rwsem_acquire_read(l, s, t, i)                do { } while (0)
 # define rwsem_release(l, n, i)                        do { } while (0)
 #endif
index 0108a56f814ed7559b2f1fcee41a903890ed919d..28bd5fa2ff2eb1c0550891cfa5af551cc03b6c5c 100644 (file)
@@ -429,7 +429,7 @@ extern int memcg_limited_groups_array_size;
  * the slab_mutex must be held when looping through those caches
  */
 #define for_each_memcg_cache_index(_idx)       \
-       for ((_idx) = 0; i < memcg_limited_groups_array_size; (_idx)++)
+       for ((_idx) = 0; (_idx) < memcg_limited_groups_array_size; (_idx)++)
 
 static inline bool memcg_kmem_enabled(void)
 {
index 9adc270de7ef0fe020a8bd36d7dd905367dfe2e0..0d7df39a5885f84c33a843e59f77f44d3ec6824f 100644 (file)
@@ -123,7 +123,7 @@ struct sp_node {
 
 struct shared_policy {
        struct rb_root root;
-       struct mutex mutex;
+       spinlock_t lock;
 };
 
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
@@ -165,11 +165,10 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
 
 
 #ifdef CONFIG_TMPFS
-extern int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context);
+extern int mpol_parse_str(char *str, struct mempolicy **mpol);
 #endif
 
-extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
-                       int no_context);
+extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol);
 
 /* Check if a vma is migratable */
 static inline int vma_migratable(struct vm_area_struct *vma)
@@ -296,15 +295,13 @@ static inline void check_highest_zone(int k)
 }
 
 #ifdef CONFIG_TMPFS
-static inline int mpol_parse_str(char *str, struct mempolicy **mpol,
-                               int no_context)
+static inline int mpol_parse_str(char *str, struct mempolicy **mpol)
 {
        return 1;       /* error */
 }
 #endif
 
-static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
-                               int no_context)
+static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 {
        return 0;
 }
index 2138bd33021a629f59b868d5a3938aefa4f87449..e53dcfeaee69bb052181261f4843c9da57f04e05 100644 (file)
@@ -272,8 +272,6 @@ struct abx500_bm_data {
        const struct abx500_fg_parameters *fg_params;
 };
 
-extern struct abx500_bm_data ab8500_bm_data;
-
 enum {
        NTC_EXTERNAL = 0,
        NTC_INTERNAL,
index 44310c98ee6eb59f38ca3024622966e6b528bf1d..9bd037df97d95a673d80f771cb9b1eaf56bce1c1 100644 (file)
@@ -422,7 +422,10 @@ struct ab8500_chargalg_platform_data {
 struct ab8500_btemp;
 struct ab8500_gpadc;
 struct ab8500_fg;
+
 #ifdef CONFIG_AB8500_BM
+extern struct abx500_bm_data ab8500_bm_data;
+
 void ab8500_fg_reinit(void);
 void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
 struct ab8500_btemp *ab8500_btemp_get(void);
@@ -434,31 +437,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res);
 int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
 
 #else
-int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
-{
-}
-static void ab8500_fg_reinit(void)
-{
-}
-static void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA)
-{
-}
-static struct ab8500_btemp *ab8500_btemp_get(void)
-{
-       return NULL;
-}
-static int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
-{
-       return 0;
-}
-struct ab8500_fg *ab8500_fg_get(void)
-{
-       return NULL;
-}
-static int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev)
-{
-       return -ENODEV;
-}
+static struct abx500_bm_data ab8500_bm_data;
 
 static inline int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
 {
index 86dd93de6ff2b70ac4c693e8a9a05083bea72503..786d02eb79d2210ef8c3dfe145e3c8d0e0123ef1 100644 (file)
@@ -99,6 +99,9 @@ struct da9052 {
        u8 chip_id;
 
        int chip_irq;
+
+       /* SOC I/O transfer related fixes for DA9052/53 */
+       int (*fix_io) (struct da9052 *da9052, unsigned char reg);
 };
 
 /* ADC API */
@@ -113,32 +116,87 @@ static inline int da9052_reg_read(struct da9052 *da9052, unsigned char reg)
        ret = regmap_read(da9052->regmap, reg, &val);
        if (ret < 0)
                return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
        return val;
 }
 
 static inline int da9052_reg_write(struct da9052 *da9052, unsigned char reg,
                                    unsigned char val)
 {
-       return regmap_write(da9052->regmap, reg, val);
+       int ret;
+
+       ret = regmap_write(da9052->regmap, reg, val);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
                                     unsigned reg_cnt, unsigned char *val)
 {
-       return regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+       int ret;
+
+       ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
                                      unsigned reg_cnt, unsigned char *val)
 {
-       return regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+       int ret;
+
+       ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static inline int da9052_reg_update(struct da9052 *da9052, unsigned char reg,
                                     unsigned char bit_mask,
                                     unsigned char reg_val)
 {
-       return regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+       int ret;
+
+       ret = regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+       if (ret < 0)
+               return ret;
+
+       if (da9052->fix_io) {
+               ret = da9052->fix_io(da9052, reg);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
 }
 
 int da9052_device_init(struct da9052 *da9052, u8 chip_id);
index b97f7309d7f69e7189d74aead8ac4281a8ed0881..c4dd3a8add21b94cc526843c117734c506cc5233 100644 (file)
@@ -34,6 +34,9 @@
 #define DA9052_STATUS_C_REG            3
 #define DA9052_STATUS_D_REG            4
 
+/* PARK REGISTER */
+#define DA9052_PARK_REGISTER           DA9052_STATUS_D_REG
+
 /* EVENT REGISTERS */
 #define DA9052_EVENT_A_REG             5
 #define DA9052_EVENT_B_REG             6
index a8d393e3066b74465f14994740b758f1a134850b..2b13970596f53732cda07a6fd3b270cc9e933e5b 100644 (file)
@@ -38,6 +38,9 @@
 #define RTSX_SD_CARD                   0
 #define RTSX_MS_CARD                   1
 
+#define CLK_TO_DIV_N                   0
+#define DIV_N_TO_CLK                   1
+
 struct platform_device;
 
 struct rtsx_slot {
index 060b721fcbfb93b690d51191daeb95da692eef8c..4b117a3f54d493f59393226c6351e1fa8c1e16ca 100644 (file)
 #define SG_TRANS_DATA          (0x02 << 4)
 #define SG_LINK_DESC           (0x03 << 4)
 
-/* SD bank voltage */
-#define SD_IO_3V3              0
-#define SD_IO_1V8              1
-
+/* Output voltage */
+#define OUTPUT_3V3             0
+#define OUTPUT_1V8             1
 
 /* Card Clock Enable Register */
 #define SD_CLK_EN                      0x04
 #define CHANGE_CLK                     0x01
 
 /* LDO_CTL */
+#define BPP_ASIC_1V7                   0x00
+#define BPP_ASIC_1V8                   0x01
+#define BPP_ASIC_1V9                   0x02
+#define BPP_ASIC_2V0                   0x03
+#define BPP_ASIC_2V7                   0x04
+#define BPP_ASIC_2V8                   0x05
+#define BPP_ASIC_3V2                   0x06
+#define BPP_ASIC_3V3                   0x07
+#define BPP_REG_TUNED18                        0x07
+#define BPP_TUNED18_SHIFT_8402         5
+#define BPP_TUNED18_SHIFT_8411         4
+#define BPP_PAD_MASK                   0x04
+#define BPP_PAD_3V3                    0x04
+#define BPP_PAD_1V8                    0x00
 #define BPP_LDO_POWB                   0x03
 #define BPP_LDO_ON                     0x00
 #define BPP_LDO_SUSPEND                        0x02
@@ -688,7 +701,10 @@ struct pcr_ops {
        int             (*disable_auto_blink)(struct rtsx_pcr *pcr);
        int             (*card_power_on)(struct rtsx_pcr *pcr, int card);
        int             (*card_power_off)(struct rtsx_pcr *pcr, int card);
+       int             (*switch_output_voltage)(struct rtsx_pcr *pcr,
+                                               u8 voltage);
        unsigned int    (*cd_deglitch)(struct rtsx_pcr *pcr);
+       int             (*conv_clk_and_div_n)(int clk, int dir);
 };
 
 enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
@@ -783,6 +799,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
                u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
 int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
 int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage);
 unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
 void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
 
index 21821da2abfd321f3755b8c0eb5481033183abeb..20ea939c22a639c04bca11f244d8c34040c1477d 100644 (file)
@@ -625,6 +625,7 @@ struct mlx4_dev {
        u8                      rev_id;
        char                    board_id[MLX4_BOARD_ID_LEN];
        int                     num_vfs;
+       int                     oper_log_mgm_entry_size;
        u64                     regid_promisc_array[MLX4_MAX_PORTS + 1];
        u64                     regid_allmulti_array[MLX4_MAX_PORTS + 1];
 };
index 7f4f906190bd75edd941771fe5ce0f0ac2089424..66e2f7c61e5c9d3a2924389e28ffa9d32c8728bf 100644 (file)
@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pages);
 
 void split_page(struct page *page, unsigned int order);
 int split_free_page(struct page *page);
-int capture_free_page(struct page *page, int alloc_order, int migratetype);
 
 /*
  * Compound pages have a destructor function.  Provide a
@@ -1007,7 +1006,6 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
 
 extern void truncate_pagecache(struct inode *inode, loff_t old, loff_t new);
 extern void truncate_setsize(struct inode *inode, loff_t newsize);
-extern int vmtruncate(struct inode *inode, loff_t offset);
 void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end);
 int truncate_inode_page(struct address_space *mapping, struct page *page);
 int generic_error_remove_page(struct address_space *mapping, struct page *page);
index bc823c4c028bd8c0404940384da729c072dc31a3..deca87452528b2888823a4daf4cb148d43a52544 100644 (file)
@@ -151,7 +151,7 @@ struct mmu_notifier_ops {
  * Therefore notifier chains can only be traversed when either
  *
  * 1. mmap_sem is held.
- * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->mutex).
+ * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->rwsem).
  * 3. No other concurrent thread can access the list (release)
  */
 struct mmu_notifier {
index 4bec5be82cab5fe2f873cd867c84c8ac18993dba..73b64a38b984a985259c468049cff50a6c44fdd3 100644 (file)
@@ -503,14 +503,6 @@ struct zone {
         * rarely used fields:
         */
        const char              *name;
-#ifdef CONFIG_MEMORY_ISOLATION
-       /*
-        * the number of MIGRATE_ISOLATE *pageblock*.
-        * We need this for free page counting. Look at zone_watermark_ok_safe.
-        * It's protected by zone->lock
-        */
-       int             nr_pageblock_isolate;
-#endif
 } ____cacheline_internodealigned_in_smp;
 
 typedef enum {
index 7760c6d344a32cd6a59cbb163a56c9bcd4888683..1375ee3f03aadd4d2504762628a3991272861fa8 100644 (file)
@@ -199,11 +199,11 @@ struct module_use {
        struct module *source, *target;
 };
 
-enum module_state
-{
-       MODULE_STATE_LIVE,
-       MODULE_STATE_COMING,
-       MODULE_STATE_GOING,
+enum module_state {
+       MODULE_STATE_LIVE,      /* Normal state. */
+       MODULE_STATE_COMING,    /* Full formed, running module_init. */
+       MODULE_STATE_GOING,     /* Going away. */
+       MODULE_STATE_UNFORMED,  /* Still setting it up. */
 };
 
 /**
index 7a4b9e97d29a0782ef0dde63126f6a124eeb848b..391af8d11cceea2f306f460ec137d75f0ea236c9 100644 (file)
@@ -34,7 +34,9 @@ struct msg_queue {
 /* Helper routines for sys_msgsnd and sys_msgrcv */
 extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
                        size_t msgsz, int msgflg);
-extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
-                       size_t msgsz, long msgtyp, int msgflg);
+extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+                     int msgflg,
+                     long (*msg_fill)(void __user *, struct msg_msg *,
+                                      size_t));
 
 #endif /* _LINUX_MSG_H */
index 4bf19d8174ed49301470eff1c6593ad1192a6e31..5a5ff57ceed4e74f76237437fc3b22453ec27a66 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_NAMEI_H
 
 #include <linux/dcache.h>
+#include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/path.h>
 
@@ -65,8 +66,8 @@ extern int user_path_at_empty(int, const char __user *, unsigned, struct path *,
 
 extern int kern_path(const char *, unsigned, struct path *);
 
-extern struct dentry *kern_path_create(int, const char *, struct path *, int);
-extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
+extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
+extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
 extern void done_path_create(struct path *, struct dentry *);
 extern struct dentry *kern_path_locked(const char *, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
@@ -98,4 +99,20 @@ static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
        ((char *) name)[min(len, maxlen)] = '\0';
 }
 
+/**
+ * retry_estale - determine whether the caller should retry an operation
+ * @error: the error that would currently be returned
+ * @flags: flags being used for next lookup attempt
+ *
+ * Check to see if the error code was -ESTALE, and then determine whether
+ * to retry the call based on whether "flags" already has LOOKUP_REVAL set.
+ *
+ * Returns true if the caller should try the operation again.
+ */
+static inline bool
+retry_estale(const long error, const unsigned int flags)
+{
+       return error == -ESTALE && !(flags & LOOKUP_REVAL);
+}
+
 #endif /* _LINUX_NAMEI_H */
index 02e0f6b156c3f2dc7c2cae5c663cbdbfd6341484..9ef07d0868b6012da1d1089daa2c9b0d7d304389 100644 (file)
@@ -60,6 +60,9 @@ struct wireless_dev;
 #define SET_ETHTOOL_OPS(netdev,ops) \
        ( (netdev)->ethtool_ops = (ops) )
 
+extern void netdev_set_default_ethtool_ops(struct net_device *dev,
+                                          const struct ethtool_ops *ops);
+
 /* hardware address assignment types */
 #define NET_ADDR_PERM          0       /* address is permanent (default) */
 #define NET_ADDR_RANDOM                1       /* address is generated randomly */
@@ -1576,7 +1579,7 @@ extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 extern rwlock_t                                dev_base_lock;          /* Device list lock */
 
-extern seqlock_t       devnet_rename_seq;      /* Device rename lock */
+extern seqcount_t      devnet_rename_seq;      /* Device rename seq */
 
 
 #define for_each_netdev(net, d)                \
index b5d13841604ee3614710cf6076cd0d29276bda4e..70473da47b3f88c11f5aa09235b698f726fc84c8 100644 (file)
@@ -362,7 +362,7 @@ static inline void ClearPageCompound(struct page *page)
  * pages on the LRU and/or pagecache.
  */
 TESTPAGEFLAG(Compound, compound)
-__PAGEFLAG(Head, compound)
+__SETPAGEFLAG(Head, compound)  __CLEARPAGEFLAG(Head, compound)
 
 /*
  * PG_reclaim is used in combination with PG_compound to mark the
@@ -374,8 +374,14 @@ __PAGEFLAG(Head, compound)
  * PG_compound & PG_reclaim    => Tail page
  * PG_compound & ~PG_reclaim   => Head page
  */
+#define PG_head_mask ((1L << PG_compound))
 #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
 
+static inline int PageHead(struct page *page)
+{
+       return ((page->flags & PG_head_tail_mask) == PG_head_mask);
+}
+
 static inline int PageTail(struct page *page)
 {
        return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
index 15472d691ee68c6aad5dbeb0a75933ec18f00404..6fa4dd2a3b9e08f94b2f6b446d88b8b2ed8e3ad4 100644 (file)
@@ -1101,6 +1101,12 @@ static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
        return -1;
 }
 
+static inline int
+pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
+{
+       return -1;
+}
+
 static inline void pci_msi_shutdown(struct pci_dev *dev)
 { }
 static inline void pci_disable_msi(struct pci_dev *dev)
@@ -1132,6 +1138,7 @@ static inline int pci_msi_enabled(void)
 }
 #else
 extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
+extern int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
 extern void pci_msi_shutdown(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
 extern int pci_msix_table_size(struct pci_dev *dev);
index 0f8447376ddbf1dc7177924438076645d34e2671..0eb65796bcb9af7f5876c300608e7caebdfe6297 100644 (file)
 #define PCI_DEVICE_ID_RICOH_RL5C476    0x0476
 #define PCI_DEVICE_ID_RICOH_RL5C478    0x0478
 #define PCI_DEVICE_ID_RICOH_R5C822     0x0822
+#define PCI_DEVICE_ID_RICOH_R5CE822    0xe822
 #define PCI_DEVICE_ID_RICOH_R5CE823    0xe823
 #define PCI_DEVICE_ID_RICOH_R5C832     0x0832
 #define PCI_DEVICE_ID_RICOH_R5C843     0x0843
index 6bfb2faa0b1937555f5ca8fa937c7007bf5b3bc4..e47ee462c2f2e69a8cbef4ef3a3d7bfc873cb51f 100644 (file)
@@ -135,16 +135,21 @@ struct hw_perf_event {
                struct { /* software */
                        struct hrtimer  hrtimer;
                };
+               struct { /* tracepoint */
+                       struct task_struct      *tp_target;
+                       /* for tp_event->class */
+                       struct list_head        tp_list;
+               };
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
                struct { /* breakpoint */
-                       struct arch_hw_breakpoint       info;
-                       struct list_head                bp_list;
                        /*
                         * Crufty hack to avoid the chicken and egg
                         * problem hw_breakpoint has with context
                         * creation and event initalization.
                         */
                        struct task_struct              *bp_target;
+                       struct arch_hw_breakpoint       info;
+                       struct list_head                bp_list;
                };
 #endif
        };
@@ -817,6 +822,17 @@ do {                                                                       \
 } while (0)
 
 
+struct perf_pmu_events_attr {
+       struct device_attribute attr;
+       u64 id;
+};
+
+#define PMU_EVENT_ATTR(_name, _var, _id, _show)                                \
+static struct perf_pmu_events_attr _var = {                            \
+       .attr = __ATTR(_name, 0444, _show, NULL),                       \
+       .id   =  _id,                                                   \
+};
+
 #define PMU_FORMAT_ATTR(_name, _format)                                        \
 static ssize_t                                                         \
 _name##_show(struct device *dev,                                       \
index b152d44fb18122e0659a7cdabf0d6b782ef63d59..2381c973d897e8ae9147e465f5884ee7481012b2 100644 (file)
@@ -121,6 +121,7 @@ int next_pidmap(struct pid_namespace *pid_ns, unsigned int last);
 
 extern struct pid *alloc_pid(struct pid_namespace *ns);
 extern void free_pid(struct pid *pid);
+extern void disable_pid_allocation(struct pid_namespace *ns);
 
 /*
  * ns_of_pid() returns the pid namespace in which the specified pid was
index bf285999273a6bce0da2db81c007b643883f37ff..215e5e3dda1063e955c93fa566b46de16f6c8dc3 100644 (file)
@@ -21,7 +21,7 @@ struct pid_namespace {
        struct kref kref;
        struct pidmap pidmap[PIDMAP_ENTRIES];
        int last_pid;
-       int nr_hashed;
+       unsigned int nr_hashed;
        struct task_struct *child_reaper;
        struct kmem_cache *pid_cachep;
        unsigned int level;
@@ -42,6 +42,8 @@ struct pid_namespace {
 
 extern struct pid_namespace init_pid_ns;
 
+#define PIDNS_HASH_ADDING (1U << 31)
+
 #ifdef CONFIG_PID_NS
 static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 {
diff --git a/include/linux/platform_data/imx-iram.h b/include/linux/platform_data/imx-iram.h
new file mode 100644 (file)
index 0000000..022690c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+#include <linux/errno.h>
+
+#ifdef CONFIG_IRAM_ALLOC
+
+int __init iram_init(unsigned long base, unsigned long size);
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
+void iram_free(unsigned long dma_addr, unsigned int size);
+
+#else
+
+static inline int __init iram_init(unsigned long base, unsigned long size)
+{
+       return -ENOMEM;
+}
+
+static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+       return NULL;
+}
+
+static inline void iram_free(unsigned long base, unsigned long size) {}
+
+#endif
index 9afc01e5a0a61ce5f4a9fe1e53ad6e0fb1b8e5bf..86c4b6294713a613fff6d8c3150691967baa6124 100644 (file)
@@ -98,9 +98,6 @@ int no_printk(const char *fmt, ...)
 extern asmlinkage __printf(1, 2)
 void early_printk(const char *fmt, ...);
 
-extern int printk_needs_cpu(int cpu);
-extern void printk_tick(void);
-
 #ifdef CONFIG_PRINTK
 asmlinkage __printf(5, 0)
 int vprintk_emit(int facility, int level,
index a0fc32279fc09d53a94b73b4c9dc89645d637b54..21123902366d8eb2b9b9be26b78e98e8c9badf13 100644 (file)
@@ -82,9 +82,6 @@ int task_handoff_unregister(struct notifier_block * n);
 int profile_event_register(enum profile_type, struct notifier_block * n);
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
 
-int register_timer_hook(int (*hook)(struct pt_regs *));
-void unregister_timer_hook(int (*hook)(struct pt_regs *));
-
 struct pt_regs;
 
 #else
@@ -135,16 +132,6 @@ static inline int profile_event_unregister(enum profile_type t, struct notifier_
 #define profile_handoff_task(a) (0)
 #define profile_munmap(a) do { } while (0)
 
-static inline int register_timer_hook(int (*hook)(struct pt_regs *))
-{
-       return -ENOSYS;
-}
-
-static inline void unregister_timer_hook(int (*hook)(struct pt_regs *))
-{
-       return;
-}
-
 #endif /* CONFIG_PROFILING */
 
 #endif /* _LINUX_PROFILE_H */
index 098d2a83829618e585cd4412920c6d803af6fa21..cb6ab5feab67812e6c55c31b23a9c504f8e63b5c 100644 (file)
@@ -46,9 +46,8 @@ struct persistent_ram_zone {
        size_t old_log_size;
 };
 
-struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
-                                                         size_t size, u32 sig,
-                                                         int ecc_size);
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+                                              u32 sig, int ecc_size);
 void persistent_ram_free(struct persistent_ram_zone *prz);
 void persistent_ram_zap(struct persistent_ram_zone *prz);
 
index addfbe7c180e0c5806adf375120e5919cfe35c4b..89573a33ab3c43ee84cf629d84e5ff3d7f091206 100644 (file)
@@ -45,7 +45,6 @@ extern long arch_ptrace(struct task_struct *child, long request,
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern void ptrace_disable(struct task_struct *);
-extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
 extern int ptrace_request(struct task_struct *child, long request,
                          unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
@@ -344,6 +343,10 @@ static inline void user_single_step_siginfo(struct task_struct *tsk,
 #define signal_pt_regs() task_pt_regs(current)
 #endif
 
+#ifndef current_user_stack_pointer
+#define current_user_stack_pointer() user_stack_pointer(current_pt_regs())
+#endif
+
 extern int task_current_syscall(struct task_struct *target, long *callno,
                                unsigned long args[6], unsigned int maxargs,
                                unsigned long *sp, unsigned long *pc);
diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 2ac60c9cf6448fac839074e752d61f2de7b56c0a..fea49b5da12a99bfa6c87b865a461a2a28e0495b 100644 (file)
@@ -123,9 +123,9 @@ __rb_change_child(struct rb_node *old, struct rb_node *new,
 extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
        void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
 
-static __always_inline void
-rb_erase_augmented(struct rb_node *node, struct rb_root *root,
-                  const struct rb_augment_callbacks *augment)
+static __always_inline struct rb_node *
+__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+                    const struct rb_augment_callbacks *augment)
 {
        struct rb_node *child = node->rb_right, *tmp = node->rb_left;
        struct rb_node *parent, *rebalance;
@@ -217,6 +217,14 @@ rb_erase_augmented(struct rb_node *node, struct rb_root *root,
        }
 
        augment->propagate(tmp, NULL);
+       return rebalance;
+}
+
+static __always_inline void
+rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+                  const struct rb_augment_callbacks *augment)
+{
+       struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
        if (rebalance)
                __rb_erase_color(rebalance, root, augment->rotate);
 }
index 275aa3f1062d4b8db48be4f5201dce83b6c9bcb4..b758ce17b309d933face58b1a557ded7eae6914e 100644 (file)
@@ -53,7 +53,10 @@ extern int rcutorture_runnable; /* for sysctl */
 extern void rcutorture_record_test_transition(void);
 extern void rcutorture_record_progress(unsigned long vernum);
 extern void do_trace_rcu_torture_read(char *rcutorturename,
-                                     struct rcu_head *rhp);
+                                     struct rcu_head *rhp,
+                                     unsigned long secs,
+                                     unsigned long c_old,
+                                     unsigned long c);
 #else
 static inline void rcutorture_record_test_transition(void)
 {
@@ -63,9 +66,13 @@ static inline void rcutorture_record_progress(unsigned long vernum)
 }
 #ifdef CONFIG_RCU_TRACE
 extern void do_trace_rcu_torture_read(char *rcutorturename,
-                                     struct rcu_head *rhp);
+                                     struct rcu_head *rhp,
+                                     unsigned long secs,
+                                     unsigned long c_old,
+                                     unsigned long c);
 #else
-#define do_trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
+#define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
+       do { } while (0)
 #endif
 #endif
 
@@ -749,7 +756,7 @@ static inline void rcu_preempt_sleep_check(void)
  * preemptible RCU implementations (TREE_PREEMPT_RCU and TINY_PREEMPT_RCU)
  * in CONFIG_PREEMPT kernel builds, RCU read-side critical sections may
  * be preempted, but explicit blocking is illegal.  Finally, in preemptible
- * RCU implementations in real-time (CONFIG_PREEMPT_RT) kernel builds,
+ * RCU implementations in real-time (with -rt patchset) kernel builds,
  * RCU read-side critical sections may be preempted and they may also
  * block, but only when acquiring spinlocks that are subject to priority
  * inheritance.
index 519777e3fa019f87883224154e875003ca56bbdd..1342e69542f345dada550d298f7bacf6f6fe75e9 100644 (file)
@@ -167,6 +167,7 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_dropped_events_cpu(struct ring_buffer *buffer, int cpu);
+unsigned long ring_buffer_read_events_cpu(struct ring_buffer *buffer, int cpu);
 
 u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);
 void ring_buffer_normalize_time_stamp(struct ring_buffer *buffer,
index 9531845c419f8329000b8927a341057bb2a64e6d..11d05f9fe8b6485b43ecaa00395f36919fc13e33 100644 (file)
@@ -138,6 +138,7 @@ extern void rtc_device_unregister(struct rtc_device *rtc);
 extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
 extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
 extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
+extern int rtc_set_ntp_time(struct timespec now);
 int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
 extern int rtc_read_alarm(struct rtc_device *rtc,
                        struct rtc_wkalrm *alrm);
index 54bd7cd7ecbd11449b9e15b49f9ab7e208e96413..8da67d625e13fc888413847da4e2a7ae560b3d86 100644 (file)
@@ -125,8 +125,17 @@ extern void downgrade_write(struct rw_semaphore *sem);
  */
 extern void down_read_nested(struct rw_semaphore *sem, int subclass);
 extern void down_write_nested(struct rw_semaphore *sem, int subclass);
+extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
+
+# define down_write_nest_lock(sem, nest_lock)                  \
+do {                                                           \
+       typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \
+       _down_write_nest_lock(sem, &(nest_lock)->dep_map);      \
+} while (0);
+
 #else
 # define down_read_nested(sem, subclass)               down_read(sem)
+# define down_write_nest_lock(sem, nest_lock)  down_write(sem)
 # define down_write_nested(sem, subclass)      down_write(sem)
 #endif
 
index f712465b05c52e2bb5ad48dbd9453217cc06b8c7..33cc4213037170aa1b9a13275c6a525555682e77 100644 (file)
@@ -304,19 +304,6 @@ static inline void lockup_detector_init(void)
 }
 #endif
 
-#ifdef CONFIG_DETECT_HUNG_TASK
-extern unsigned int  sysctl_hung_task_panic;
-extern unsigned long sysctl_hung_task_check_count;
-extern unsigned long sysctl_hung_task_timeout_secs;
-extern unsigned long sysctl_hung_task_warnings;
-extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
-                                        void __user *buffer,
-                                        size_t *lenp, loff_t *ppos);
-#else
-/* Avoid need for ifdefs elsewhere in the code */
-enum { sysctl_hung_task_timeout_secs = 0 };
-#endif
-
 /* Attach to any functions which should be ignored in wchan output. */
 #define __sched                __attribute__((__section__(".sched.text")))
 
@@ -338,23 +325,6 @@ extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
 struct nsproxy;
 struct user_namespace;
 
-/*
- * Default maximum number of active map areas, this limits the number of vmas
- * per mm struct. Users can overwrite this number by sysctl but there is a
- * problem.
- *
- * When a program's coredump is generated as ELF format, a section is created
- * per a vma. In ELF, the number of sections is represented in unsigned short.
- * This means the number of sections should be smaller than 65535 at coredump.
- * Because the kernel adds some informative sections to a image of program at
- * generating coredump, we need some margin. The number of extra sections is
- * 1-3 now and depends on arch. We use "5" as safe margin, here.
- */
-#define MAPCOUNT_ELF_CORE_MARGIN       (5)
-#define DEFAULT_MAX_MAP_COUNT  (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
-
-extern int sysctl_max_map_count;
-
 #include <linux/aio.h>
 
 #ifdef CONFIG_MMU
@@ -1194,6 +1164,7 @@ struct sched_entity {
        /* rq "owned" by this entity/group: */
        struct cfs_rq           *my_q;
 #endif
+
 /*
  * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
  * removed when useful for applications beyond shares distribution (e.g.
@@ -1208,6 +1179,7 @@ struct sched_entity {
 struct sched_rt_entity {
        struct list_head run_list;
        unsigned long timeout;
+       unsigned long watchdog_stamp;
        unsigned int time_slice;
 
        struct sched_rt_entity *back;
@@ -1220,11 +1192,6 @@ struct sched_rt_entity {
 #endif
 };
 
-/*
- * default timeslice is 100 msecs (used only for SCHED_RR tasks).
- * Timeslices get refilled after they expire.
- */
-#define RR_TIMESLICE           (100 * HZ / 1000)
 
 struct rcu_node;
 
@@ -1367,6 +1334,15 @@ struct task_struct {
        cputime_t gtime;
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
        struct cputime prev_cputime;
+#endif
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+       seqlock_t vtime_seqlock;
+       unsigned long long vtime_snap;
+       enum {
+               VTIME_SLEEPING = 0,
+               VTIME_USER,
+               VTIME_SYS,
+       } vtime_snap_whence;
 #endif
        unsigned long nvcsw, nivcsw; /* context switch counts */
        struct timespec start_time;             /* monotonic time */
@@ -1622,37 +1598,6 @@ static inline void set_numabalancing_state(bool enabled)
 }
 #endif
 
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space.  This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO       100
-#define MAX_RT_PRIO            MAX_USER_RT_PRIO
-
-#define MAX_PRIO               (MAX_RT_PRIO + 40)
-#define DEFAULT_PRIO           (MAX_RT_PRIO + 20)
-
-static inline int rt_prio(int prio)
-{
-       if (unlikely(prio < MAX_RT_PRIO))
-               return 1;
-       return 0;
-}
-
-static inline int rt_task(struct task_struct *p)
-{
-       return rt_prio(p->prio);
-}
-
 static inline struct pid *task_pid(struct task_struct *task)
 {
        return task->pids[PIDTYPE_PID].pid;
@@ -1792,6 +1737,37 @@ static inline void put_task_struct(struct task_struct *t)
                __put_task_struct(t);
 }
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+extern void task_cputime(struct task_struct *t,
+                        cputime_t *utime, cputime_t *stime);
+extern void task_cputime_scaled(struct task_struct *t,
+                               cputime_t *utimescaled, cputime_t *stimescaled);
+extern cputime_t task_gtime(struct task_struct *t);
+#else
+static inline void task_cputime(struct task_struct *t,
+                               cputime_t *utime, cputime_t *stime)
+{
+       if (utime)
+               *utime = t->utime;
+       if (stime)
+               *stime = t->stime;
+}
+
+static inline void task_cputime_scaled(struct task_struct *t,
+                                      cputime_t *utimescaled,
+                                      cputime_t *stimescaled)
+{
+       if (utimescaled)
+               *utimescaled = t->utimescaled;
+       if (stimescaled)
+               *stimescaled = t->stimescaled;
+}
+
+static inline cputime_t task_gtime(struct task_struct *t)
+{
+       return t->gtime;
+}
+#endif
 extern void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
 extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
 
@@ -1810,6 +1786,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
 #define PF_MEMALLOC    0x00000800      /* Allocating memory */
 #define PF_NPROC_EXCEEDED 0x00001000   /* set_user noticed that RLIMIT_NPROC was exceeded */
 #define PF_USED_MATH   0x00002000      /* if unset the fpu must be initialized before use */
+#define PF_USED_ASYNC  0x00004000      /* used async_schedule*(), used by module init */
 #define PF_NOFREEZE    0x00008000      /* this thread should not be frozen */
 #define PF_FROZEN      0x00010000      /* frozen for system suspend */
 #define PF_FSTRANS     0x00020000      /* inside a filesystem transaction */
@@ -2032,58 +2009,7 @@ extern void wake_up_idle_cpu(int cpu);
 static inline void wake_up_idle_cpu(int cpu) { }
 #endif
 
-extern unsigned int sysctl_sched_latency;
-extern unsigned int sysctl_sched_min_granularity;
-extern unsigned int sysctl_sched_wakeup_granularity;
-extern unsigned int sysctl_sched_child_runs_first;
-
-enum sched_tunable_scaling {
-       SCHED_TUNABLESCALING_NONE,
-       SCHED_TUNABLESCALING_LOG,
-       SCHED_TUNABLESCALING_LINEAR,
-       SCHED_TUNABLESCALING_END,
-};
-extern enum sched_tunable_scaling sysctl_sched_tunable_scaling;
-
-extern unsigned int sysctl_numa_balancing_scan_delay;
-extern unsigned int sysctl_numa_balancing_scan_period_min;
-extern unsigned int sysctl_numa_balancing_scan_period_max;
-extern unsigned int sysctl_numa_balancing_scan_period_reset;
-extern unsigned int sysctl_numa_balancing_scan_size;
-extern unsigned int sysctl_numa_balancing_settle_count;
-
-#ifdef CONFIG_SCHED_DEBUG
-extern unsigned int sysctl_sched_migration_cost;
-extern unsigned int sysctl_sched_nr_migrate;
-extern unsigned int sysctl_sched_time_avg;
-extern unsigned int sysctl_timer_migration;
-extern unsigned int sysctl_sched_shares_window;
-
-int sched_proc_update_handler(struct ctl_table *table, int write,
-               void __user *buffer, size_t *length,
-               loff_t *ppos);
-#endif
-#ifdef CONFIG_SCHED_DEBUG
-static inline unsigned int get_sysctl_timer_migration(void)
-{
-       return sysctl_timer_migration;
-}
-#else
-static inline unsigned int get_sysctl_timer_migration(void)
-{
-       return 1;
-}
-#endif
-extern unsigned int sysctl_sched_rt_period;
-extern int sysctl_sched_rt_runtime;
-
-int sched_rt_handler(struct ctl_table *table, int write,
-               void __user *buffer, size_t *lenp,
-               loff_t *ppos);
-
 #ifdef CONFIG_SCHED_AUTOGROUP
-extern unsigned int sysctl_sched_autogroup_enabled;
-
 extern void sched_autogroup_create_attach(struct task_struct *p);
 extern void sched_autogroup_detach(struct task_struct *p);
 extern void sched_autogroup_fork(struct signal_struct *sig);
@@ -2099,30 +2025,6 @@ static inline void sched_autogroup_fork(struct signal_struct *sig) { }
 static inline void sched_autogroup_exit(struct signal_struct *sig) { }
 #endif
 
-#ifdef CONFIG_CFS_BANDWIDTH
-extern unsigned int sysctl_sched_cfs_bandwidth_slice;
-#endif
-
-#ifdef CONFIG_RT_MUTEXES
-extern int rt_mutex_getprio(struct task_struct *p);
-extern void rt_mutex_setprio(struct task_struct *p, int prio);
-extern void rt_mutex_adjust_pi(struct task_struct *p);
-static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
-{
-       return tsk->pi_blocked_on != NULL;
-}
-#else
-static inline int rt_mutex_getprio(struct task_struct *p)
-{
-       return p->normal_prio;
-}
-# define rt_mutex_adjust_pi(p)         do { } while (0)
-static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
-{
-       return false;
-}
-#endif
-
 extern bool yield_to(struct task_struct *p, bool preempt);
 extern void set_user_nice(struct task_struct *p, long nice);
 extern int task_prio(const struct task_struct *p);
@@ -2353,9 +2255,7 @@ extern int do_execve(const char *,
                     const char __user * const __user *);
 extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
 struct task_struct *fork_idle(int);
-#ifdef CONFIG_GENERIC_KERNEL_THREAD
 extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-#endif
 
 extern void set_task_comm(struct task_struct *tsk, char *from);
 extern char *get_task_comm(char *to, struct task_struct *tsk);
@@ -2715,7 +2615,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig)
 extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
 
-extern void signal_wake_up(struct task_struct *t, int resume_stopped);
+extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
+
+static inline void signal_wake_up(struct task_struct *t, bool resume)
+{
+       signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
+}
+static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
+{
+       signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
+}
 
 /*
  * Wrappers for p->thread_info->cpu access. No-op on UP.
@@ -2745,8 +2654,6 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
 extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
 extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
 
-extern void normalize_rt_tasks(void);
-
 #ifdef CONFIG_CGROUP_SCHED
 
 extern struct task_group root_task_group;
diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h
new file mode 100644 (file)
index 0000000..94e19ea
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _SCHED_RT_H
+#define _SCHED_RT_H
+
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space.  This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO       100
+#define MAX_RT_PRIO            MAX_USER_RT_PRIO
+
+#define MAX_PRIO               (MAX_RT_PRIO + 40)
+#define DEFAULT_PRIO           (MAX_RT_PRIO + 20)
+
+static inline int rt_prio(int prio)
+{
+       if (unlikely(prio < MAX_RT_PRIO))
+               return 1;
+       return 0;
+}
+
+static inline int rt_task(struct task_struct *p)
+{
+       return rt_prio(p->prio);
+}
+
+#ifdef CONFIG_RT_MUTEXES
+extern int rt_mutex_getprio(struct task_struct *p);
+extern void rt_mutex_setprio(struct task_struct *p, int prio);
+extern void rt_mutex_adjust_pi(struct task_struct *p);
+static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
+{
+       return tsk->pi_blocked_on != NULL;
+}
+#else
+static inline int rt_mutex_getprio(struct task_struct *p)
+{
+       return p->normal_prio;
+}
+# define rt_mutex_adjust_pi(p)         do { } while (0)
+static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
+{
+       return false;
+}
+#endif
+
+extern void normalize_rt_tasks(void);
+
+
+#endif /* _SCHED_RT_H */
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
new file mode 100644 (file)
index 0000000..d2bb0ae
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef _SCHED_SYSCTL_H
+#define _SCHED_SYSCTL_H
+
+#ifdef CONFIG_DETECT_HUNG_TASK
+extern unsigned int  sysctl_hung_task_panic;
+extern unsigned long sysctl_hung_task_check_count;
+extern unsigned long sysctl_hung_task_timeout_secs;
+extern unsigned long sysctl_hung_task_warnings;
+extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
+                                        void __user *buffer,
+                                        size_t *lenp, loff_t *ppos);
+#else
+/* Avoid need for ifdefs elsewhere in the code */
+enum { sysctl_hung_task_timeout_secs = 0 };
+#endif
+
+/*
+ * Default maximum number of active map areas, this limits the number of vmas
+ * per mm struct. Users can overwrite this number by sysctl but there is a
+ * problem.
+ *
+ * When a program's coredump is generated as ELF format, a section is created
+ * per a vma. In ELF, the number of sections is represented in unsigned short.
+ * This means the number of sections should be smaller than 65535 at coredump.
+ * Because the kernel adds some informative sections to a image of program at
+ * generating coredump, we need some margin. The number of extra sections is
+ * 1-3 now and depends on arch. We use "5" as safe margin, here.
+ */
+#define MAPCOUNT_ELF_CORE_MARGIN       (5)
+#define DEFAULT_MAX_MAP_COUNT  (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
+
+extern int sysctl_max_map_count;
+
+extern unsigned int sysctl_sched_latency;
+extern unsigned int sysctl_sched_min_granularity;
+extern unsigned int sysctl_sched_wakeup_granularity;
+extern unsigned int sysctl_sched_child_runs_first;
+
+enum sched_tunable_scaling {
+       SCHED_TUNABLESCALING_NONE,
+       SCHED_TUNABLESCALING_LOG,
+       SCHED_TUNABLESCALING_LINEAR,
+       SCHED_TUNABLESCALING_END,
+};
+extern enum sched_tunable_scaling sysctl_sched_tunable_scaling;
+
+extern unsigned int sysctl_numa_balancing_scan_delay;
+extern unsigned int sysctl_numa_balancing_scan_period_min;
+extern unsigned int sysctl_numa_balancing_scan_period_max;
+extern unsigned int sysctl_numa_balancing_scan_period_reset;
+extern unsigned int sysctl_numa_balancing_scan_size;
+extern unsigned int sysctl_numa_balancing_settle_count;
+
+#ifdef CONFIG_SCHED_DEBUG
+extern unsigned int sysctl_sched_migration_cost;
+extern unsigned int sysctl_sched_nr_migrate;
+extern unsigned int sysctl_sched_time_avg;
+extern unsigned int sysctl_timer_migration;
+extern unsigned int sysctl_sched_shares_window;
+
+int sched_proc_update_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *length,
+               loff_t *ppos);
+#endif
+#ifdef CONFIG_SCHED_DEBUG
+static inline unsigned int get_sysctl_timer_migration(void)
+{
+       return sysctl_timer_migration;
+}
+#else
+static inline unsigned int get_sysctl_timer_migration(void)
+{
+       return 1;
+}
+#endif
+
+/*
+ *  control realtime throttling:
+ *
+ *  /proc/sys/kernel/sched_rt_period_us
+ *  /proc/sys/kernel/sched_rt_runtime_us
+ */
+extern unsigned int sysctl_sched_rt_period;
+extern int sysctl_sched_rt_runtime;
+
+#ifdef CONFIG_CFS_BANDWIDTH
+extern unsigned int sysctl_sched_cfs_bandwidth_slice;
+#endif
+
+#ifdef CONFIG_SCHED_AUTOGROUP
+extern unsigned int sysctl_sched_autogroup_enabled;
+#endif
+
+/*
+ * default timeslice is 100 msecs (used only for SCHED_RR tasks).
+ * Timeslices get refilled after they expire.
+ */
+#define RR_TIMESLICE           (100 * HZ / 1000)
+
+extern int sched_rr_timeslice;
+
+extern int sched_rr_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos);
+
+extern int sched_rt_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos);
+
+#endif /* _SCHED_SYSCTL_H */
index 0f6afc657f778f2e682e7fb108e97b6788a53973..eee7478cda701ddeabc00150f607f368a4239350 100644 (file)
@@ -989,17 +989,29 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     tells the LSM to decrement the number of secmark labeling rules loaded
  * @req_classify_flow:
  *     Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ *     This hook allows a module to allocate a security structure for a TUN
+ *     device.
+ *     @security pointer to a security structure pointer.
+ *     Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ *     This hook allows a module to free the security structure for a TUN
+ *     device.
+ *     @security pointer to the TUN device's security structure
  * @tun_dev_create:
  *     Check permissions prior to creating a new TUN device.
- * @tun_dev_post_create:
- *     This hook allows a module to update or allocate a per-socket security
- *     structure.
- *     @sk contains the newly created sock structure.
+ * @tun_dev_attach_queue:
+ *     Check permissions prior to attaching to a TUN device queue.
+ *     @security pointer to the TUN device's security structure.
  * @tun_dev_attach:
- *     Check permissions prior to attaching to a persistent TUN device.  This
- *     hook can also be used by the module to update any security state
+ *     This hook can be used by the module to update any security state
  *     associated with the TUN device's sock structure.
  *     @sk contains the existing sock structure.
+ *     @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ *     This hook can be used by the module to update any security state
+ *     associated with the TUN device's security structure.
+ *     @security pointer to the TUN devices's security structure.
  *
  * Security hooks for XFRM operations.
  *
@@ -1620,9 +1632,12 @@ struct security_operations {
        void (*secmark_refcount_inc) (void);
        void (*secmark_refcount_dec) (void);
        void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
-       int (*tun_dev_create)(void);
-       void (*tun_dev_post_create)(struct sock *sk);
-       int (*tun_dev_attach)(struct sock *sk);
+       int (*tun_dev_alloc_security) (void **security);
+       void (*tun_dev_free_security) (void *security);
+       int (*tun_dev_create) (void);
+       int (*tun_dev_attach_queue) (void *security);
+       int (*tun_dev_attach) (struct sock *sk, void *security);
+       int (*tun_dev_open) (void *security);
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2566,9 +2581,12 @@ void security_inet_conn_established(struct sock *sk,
 int security_secmark_relabel_packet(u32 secid);
 void security_secmark_refcount_inc(void);
 void security_secmark_refcount_dec(void);
+int security_tun_dev_alloc_security(void **security);
+void security_tun_dev_free_security(void *security);
 int security_tun_dev_create(void);
-void security_tun_dev_post_create(struct sock *sk);
-int security_tun_dev_attach(struct sock *sk);
+int security_tun_dev_attach_queue(void *security);
+int security_tun_dev_attach(struct sock *sk, void *security);
+int security_tun_dev_open(void *security);
 
 #else  /* CONFIG_SECURITY_NETWORK */
 static inline int security_unix_stream_connect(struct sock *sock,
@@ -2733,16 +2751,31 @@ static inline void security_secmark_refcount_dec(void)
 {
 }
 
+static inline int security_tun_dev_alloc_security(void **security)
+{
+       return 0;
+}
+
+static inline void security_tun_dev_free_security(void *security)
+{
+}
+
 static inline int security_tun_dev_create(void)
 {
        return 0;
 }
 
-static inline void security_tun_dev_post_create(struct sock *sk)
+static inline int security_tun_dev_attach_queue(void *security)
+{
+       return 0;
+}
+
+static inline int security_tun_dev_attach(struct sock *sk, void *security)
 {
+       return 0;
 }
 
-static inline int security_tun_dev_attach(struct sock *sk)
+static inline int security_tun_dev_open(void *security)
 {
        return 0;
 }
index e19a011b43b7632163894ca70dde03ebaac64203..0a89ffc4846669c7bfa5f6289e8563decb84c520 100644 (file)
@@ -385,4 +385,7 @@ int unhandled_signal(struct task_struct *tsk, int sig);
 
 void signals_init(void);
 
+int restore_altstack(const stack_t __user *);
+int __save_altstack(stack_t __user *, unsigned long);
+
 #endif /* _LINUX_SIGNAL_H */
index e0106d8581d380c2bee45d10141297cb8ac0b4b0..c65dee059913c8d429a614bf3c9b16e088369216 100644 (file)
@@ -14,6 +14,8 @@ struct smpboot_thread_data;
  * @thread_should_run: Check whether the thread should run or not. Called with
  *                     preemption disabled.
  * @thread_fn:         The associated thread function
+ * @create:            Optional setup function, called when the thread gets
+ *                     created (Not called from the thread context)
  * @setup:             Optional setup function, called when the thread gets
  *                     operational the first time
  * @cleanup:           Optional cleanup function, called when the thread
@@ -22,6 +24,7 @@ struct smpboot_thread_data;
  *                     parked (cpu offline)
  * @unpark:            Optional unpark function, called when the thread is
  *                     unparked (cpu online)
+ * @selfparking:       Thread is not parked by the park function.
  * @thread_comm:       The base name of the thread
  */
 struct smp_hotplug_thread {
@@ -29,10 +32,12 @@ struct smp_hotplug_thread {
        struct list_head                list;
        int                             (*thread_should_run)(unsigned int cpu);
        void                            (*thread_fn)(unsigned int cpu);
+       void                            (*create)(unsigned int cpu);
        void                            (*setup)(unsigned int cpu);
        void                            (*cleanup)(unsigned int cpu, bool online);
        void                            (*park)(unsigned int cpu);
        void                            (*unpark)(unsigned int cpu);
+       bool                            selfparking;
        const char                      *thread_comm;
 };
 
index 6eb691b083581ff88ffd9e7c3da73bc5aa2170fd..04f4121a23ae2b6f5854bf35e7678cd9f93fe991 100644 (file)
@@ -151,30 +151,14 @@ void srcu_barrier(struct srcu_struct *sp);
  * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
  *
- * Note that if the CPU is in the idle loop from an RCU point of view
- * (ie: that we are in the section between rcu_idle_enter() and
- * rcu_idle_exit()) then srcu_read_lock_held() returns false even if
- * the CPU did an srcu_read_lock().  The reason for this is that RCU
- * ignores CPUs that are in such a section, considering these as in
- * extended quiescent state, so such a CPU is effectively never in an
- * RCU read-side critical section regardless of what RCU primitives it
- * invokes.  This state of affairs is required --- we need to keep an
- * RCU-free window in idle where the CPU may possibly enter into low
- * power mode. This way we can notice an extended quiescent state to
- * other CPUs that started a grace period. Otherwise we would delay any
- * grace period as long as we run in the idle task.
- *
- * Similarly, we avoid claiming an SRCU read lock held if the current
- * CPU is offline.
+ * Note that SRCU is based on its own statemachine and it doesn't
+ * relies on normal RCU, it can be called from the CPU which
+ * is in the idle loop from an RCU point of view or offline.
  */
 static inline int srcu_read_lock_held(struct srcu_struct *sp)
 {
        if (!debug_lockdep_rcu_enabled())
                return 1;
-       if (rcu_is_cpu_idle())
-               return 0;
-       if (!rcu_lockdep_current_cpu_online())
-               return 0;
        return lock_is_held(&sp->dep_map);
 }
 
@@ -236,8 +220,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
        int retval = __srcu_read_lock(sp);
 
        rcu_lock_acquire(&(sp)->dep_map);
-       rcu_lockdep_assert(!rcu_is_cpu_idle(),
-                          "srcu_read_lock() used illegally while idle");
        return retval;
 }
 
@@ -251,8 +233,6 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
 static inline void srcu_read_unlock(struct srcu_struct *sp, int idx)
        __releases(sp)
 {
-       rcu_lockdep_assert(!rcu_is_cpu_idle(),
-                          "srcu_read_unlock() used illegally while idle");
        rcu_lock_release(&(sp)->dep_map);
        __srcu_read_unlock(sp, idx);
 }
index f792794f66341a5888136e6697322f445ba62197..5dc9ee4d616e6f966e1b4abe9fe69021f48645ea 100644 (file)
@@ -217,6 +217,8 @@ extern int qword_get(char **bpp, char *dest, int bufsize);
 static inline int get_int(char **bpp, int *anint)
 {
        char buf[50];
+       char *ep;
+       int rv;
        int len = qword_get(bpp, buf, sizeof(buf));
 
        if (len < 0)
@@ -224,9 +226,11 @@ static inline int get_int(char **bpp, int *anint)
        if (len == 0)
                return -ENOENT;
 
-       if (kstrtoint(buf, 0, anint))
+       rv = simple_strtol(buf, &ep, 0);
+       if (*ep)
                return -EINVAL;
 
+       *anint = rv;
        return 0;
 }
 
index d83db800fe02eeabbfc96f76e56a2662cce7c0cf..676ddf53b3eee063b3c6b433de057c1da6894023 100644 (file)
@@ -243,6 +243,7 @@ struct svc_rqst {
        struct page *           rq_pages[RPCSVC_MAXPAGES];
        struct page *           *rq_respages;   /* points into rq_pages */
        int                     rq_resused;     /* number of pages used for result */
+       struct page *           *rq_next_page; /* next reply page to use */
 
        struct kvec             rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */
 
@@ -338,9 +339,8 @@ xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p)
 
 static inline void svc_free_res_pages(struct svc_rqst *rqstp)
 {
-       while (rqstp->rq_resused) {
-               struct page **pp = (rqstp->rq_respages +
-                                   --rqstp->rq_resused);
+       while (rqstp->rq_next_page != rqstp->rq_respages) {
+               struct page **pp = --rqstp->rq_next_page;
                if (*pp) {
                        put_page(*pp);
                        *pp = NULL;
index 92ad02f0dcc0ea9409a09c1b3637e1f5c1869bc1..62fd1b756e9914a63ea72ae21a401a7b14115161 100644 (file)
@@ -26,11 +26,28 @@ struct svc_sock {
        void                    (*sk_owspace)(struct sock *);
 
        /* private TCP part */
-       u32                     sk_reclen;      /* length of record */
-       u32                     sk_tcplen;      /* current read length */
+       /* On-the-wire fragment header: */
+       __be32                  sk_reclen;
+       /* As we receive a record, this includes the length received so
+        * far (including the fragment header): */
+       u32                     sk_tcplen;
+       /* Total length of the data (not including fragment headers)
+        * received so far in the fragments making up this rpc: */
+       u32                     sk_datalen;
+
        struct page *           sk_pages[RPCSVC_MAXPAGES];      /* received data */
 };
 
+static inline u32 svc_sock_reclen(struct svc_sock *svsk)
+{
+       return ntohl(svsk->sk_reclen) & RPC_FRAGMENT_SIZE_MASK;
+}
+
+static inline u32 svc_sock_final_rec(struct svc_sock *svsk)
+{
+       return ntohl(svsk->sk_reclen) & RPC_LAST_STREAM_FRAGMENT;
+}
+
 /*
  * Function prototypes.
  */
index 6caee34bf8a23a8276fbf67cbb11a9f2f071a399..45e2db2702557c1ddb57700671205546868cdc45 100644 (file)
@@ -63,6 +63,7 @@ struct getcpu_cache;
 struct old_linux_dirent;
 struct perf_event_attr;
 struct file_handle;
+struct sigaltstack;
 
 #include <linux/types.h>
 #include <linux/aio_abi.h>
@@ -299,6 +300,11 @@ asmlinkage long sys_personality(unsigned int personality);
 asmlinkage long sys_sigpending(old_sigset_t __user *set);
 asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
                                old_sigset_t __user *oset);
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss,
+                               struct sigaltstack __user *uoss);
+#endif
+
 asmlinkage long sys_getitimer(int which, struct itimerval __user *value);
 asmlinkage long sys_setitimer(int which,
                                struct itimerval __user *value,
@@ -827,15 +833,6 @@ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
                                  const char  __user *pathname);
 asmlinkage long sys_syncfs(int fd);
 
-#ifndef CONFIG_GENERIC_KERNEL_EXECVE
-int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
-#else
-#define kernel_execve(filename, argv, envp) \
-       do_execve(filename, \
-               (const char __user *const __user *)argv, \
-               (const char __user *const __user *)envp)
-#endif
-
 asmlinkage long sys_fork(void);
 asmlinkage long sys_vfork(void);
 #ifdef CONFIG_CLONE_BACKWARDS
index 1a6567b48492d3dd782b0646a9d87d496b8c95f1..553272e6af554844fbea920f0c3b08707c52e13a 100644 (file)
@@ -8,6 +8,8 @@
 
 #include <linux/clockchips.h>
 #include <linux/irqflags.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 
@@ -122,13 +124,26 @@ static inline int tick_oneshot_mode_active(void) { return 0; }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 # ifdef CONFIG_NO_HZ
+DECLARE_PER_CPU(struct tick_sched, tick_cpu_sched);
+
+static inline int tick_nohz_tick_stopped(void)
+{
+       return __this_cpu_read(tick_cpu_sched.tick_stopped);
+}
+
 extern void tick_nohz_idle_enter(void);
 extern void tick_nohz_idle_exit(void);
 extern void tick_nohz_irq_exit(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
-# else
+
+# else /* !CONFIG_NO_HZ */
+static inline int tick_nohz_tick_stopped(void)
+{
+       return 0;
+}
+
 static inline void tick_nohz_idle_enter(void) { }
 static inline void tick_nohz_idle_exit(void) { }
 
index 4d358e9d10f100757176df607b502a451aafc6bb..a3ab6a814a9cb0d6093875b36d0e62207fefb09e 100644 (file)
@@ -115,8 +115,20 @@ static inline bool timespec_valid_strict(const struct timespec *ts)
        return true;
 }
 
+extern bool persistent_clock_exist;
+
+#ifdef ALWAYS_USE_PERSISTENT_CLOCK
+#define has_persistent_clock() true
+#else
+static inline bool has_persistent_clock(void)
+{
+       return persistent_clock_exist;
+}
+#endif
+
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
+extern int persistent_clock_is_local;
 extern int update_persistent_clock(struct timespec now);
 void timekeeping_init(void);
 extern int timekeeping_suspended;
@@ -158,6 +170,7 @@ extern int do_setitimer(int which, struct itimerval *value,
                        struct itimerval *ovalue);
 extern unsigned int alarm_setitimer(unsigned int seconds);
 extern int do_getitimer(int which, struct itimerval *value);
+extern int __getnstimeofday(struct timespec *tv);
 extern void getnstimeofday(struct timespec *tv);
 extern void getrawmonotonic(struct timespec *ts);
 extern void getnstime_raw_and_real(struct timespec *ts_raw,
index 44893e5ec8f74c6d3bd358cb250a24c5aea25541..3251965bf4cc704378939e7f0080f97625e2cfd3 100644 (file)
@@ -23,12 +23,15 @@ static inline void bacct_add_tsk(struct user_namespace *user_ns,
 #ifdef CONFIG_TASK_XACCT
 extern void xacct_add_tsk(struct taskstats *stats, struct task_struct *p);
 extern void acct_update_integrals(struct task_struct *tsk);
+extern void acct_account_cputime(struct task_struct *tsk);
 extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 static inline void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 {}
 static inline void acct_update_integrals(struct task_struct *tsk)
 {}
+static inline void acct_account_cputime(struct task_struct *tsk)
+{}
 static inline void acct_clear_integrals(struct task_struct *tsk)
 {}
 #endif /* CONFIG_TASK_XACCT */
index 4f628a6fc5b415cb763e9fd3b9260526649a7436..02b83db8e2c5d2f330407a7f76c42e7ff0ac11c2 100644 (file)
@@ -35,13 +35,20 @@ struct inode;
 # include <asm/uprobes.h>
 #endif
 
+#define UPROBE_HANDLER_REMOVE          1
+#define UPROBE_HANDLER_MASK            1
+
+enum uprobe_filter_ctx {
+       UPROBE_FILTER_REGISTER,
+       UPROBE_FILTER_UNREGISTER,
+       UPROBE_FILTER_MMAP,
+};
+
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
-       /*
-        * filter is optional; If a filter exists, handler is run
-        * if and only if filter returns true.
-        */
-       bool (*filter)(struct uprobe_consumer *self, struct task_struct *task);
+       bool (*filter)(struct uprobe_consumer *self,
+                               enum uprobe_filter_ctx ctx,
+                               struct mm_struct *mm);
 
        struct uprobe_consumer *next;
 };
@@ -94,6 +101,7 @@ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsign
 extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
+extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
 extern int uprobe_mmap(struct vm_area_struct *vma);
 extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end);
@@ -117,6 +125,11 @@ uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
 {
        return -ENOSYS;
 }
+static inline int
+uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool add)
+{
+       return -ENOSYS;
+}
 static inline void
 uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
 {
index 689b14b26c8d84343d8271b87d9aefca00b20904..4d22d0f6167aa49b653c8d942c2e00d61be689b8 100644 (file)
@@ -357,6 +357,8 @@ struct usb_bus {
        int bandwidth_int_reqs;         /* number of Interrupt requests */
        int bandwidth_isoc_reqs;        /* number of Isoc. requests */
 
+       unsigned resuming_ports;        /* bit array: resuming root-hub ports */
+
 #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
        struct mon_bus *mon_bus;        /* non-null when associated */
        int monitored;                  /* non-zero when monitored */
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 608050b2545f917f790fca91bc9f89042626752c..0a78df5f6cfd23d616ecd4572b6079d1f8605dd2 100644 (file)
@@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
 extern void usb_wakeup_notification(struct usb_device *hdev,
                unsigned int portnum);
 
+extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
+extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
+
 /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
 #define        usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
index bd45eb7bedc8f365ab70704c552e93041af4ac94..0e5ac93bab101bea0526ee3b54f52ed3b0f72099 100644 (file)
@@ -33,6 +33,7 @@ struct usbnet {
        wait_queue_head_t       *wait;
        struct mutex            phy_mutex;
        unsigned char           suspend_count;
+       unsigned char           pkt_cnt, pkt_err;
 
        /* i/o info: pipes etc */
        unsigned                in, out;
@@ -70,6 +71,7 @@ struct usbnet {
 #              define EVENT_DEV_OPEN   7
 #              define EVENT_DEVICE_REPORT_IDLE 8
 #              define EVENT_NO_RUNTIME_PM      9
+#              define EVENT_RX_KILL    10
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -107,6 +109,7 @@ struct driver_info {
  */
 #define FLAG_MULTI_PACKET      0x2000
 #define FLAG_RX_ASSEMBLE       0x4000  /* rx packets may span >1 frames */
+#define FLAG_NOARP             0x8000  /* device can't do ARP */
 
        /* init device ... can sleep, or cause probe() failure */
        int     (*bind)(struct usbnet *, struct usb_interface *);
index ae30ab58431ab7fd30971fbee3f655a3c8aeb2b1..71a5782d8c592fc027cd1e0ce7c4c5a99787c11f 100644 (file)
@@ -6,15 +6,46 @@ struct task_struct;
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 extern void vtime_task_switch(struct task_struct *prev);
 extern void vtime_account_system(struct task_struct *tsk);
-extern void vtime_account_system_irqsafe(struct task_struct *tsk);
 extern void vtime_account_idle(struct task_struct *tsk);
 extern void vtime_account_user(struct task_struct *tsk);
-extern void vtime_account(struct task_struct *tsk);
-#else
+extern void vtime_account_irq_enter(struct task_struct *tsk);
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
+static inline bool vtime_accounting_enabled(void) { return true; }
+#endif
+
+#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
+
 static inline void vtime_task_switch(struct task_struct *prev) { }
 static inline void vtime_account_system(struct task_struct *tsk) { }
-static inline void vtime_account_system_irqsafe(struct task_struct *tsk) { }
-static inline void vtime_account(struct task_struct *tsk) { }
+static inline void vtime_account_user(struct task_struct *tsk) { }
+static inline void vtime_account_irq_enter(struct task_struct *tsk) { }
+static inline bool vtime_accounting_enabled(void) { return false; }
+#endif
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+extern void arch_vtime_task_switch(struct task_struct *tsk);
+extern void vtime_account_irq_exit(struct task_struct *tsk);
+extern bool vtime_accounting_enabled(void);
+extern void vtime_user_enter(struct task_struct *tsk);
+static inline void vtime_user_exit(struct task_struct *tsk)
+{
+       vtime_account_user(tsk);
+}
+extern void vtime_guest_enter(struct task_struct *tsk);
+extern void vtime_guest_exit(struct task_struct *tsk);
+extern void vtime_init_idle(struct task_struct *tsk);
+#else
+static inline void vtime_account_irq_exit(struct task_struct *tsk)
+{
+       /* On hard|softirq exit we always account to hard|softirq cputime */
+       vtime_account_system(tsk);
+}
+static inline void vtime_user_enter(struct task_struct *tsk) { }
+static inline void vtime_user_exit(struct task_struct *tsk) { }
+static inline void vtime_guest_enter(struct task_struct *tsk) { }
+static inline void vtime_guest_exit(struct task_struct *tsk) { }
+static inline void vtime_init_idle(struct task_struct *tsk) { }
 #endif
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -23,25 +54,15 @@ extern void irqtime_account_irq(struct task_struct *tsk);
 static inline void irqtime_account_irq(struct task_struct *tsk) { }
 #endif
 
-static inline void vtime_account_irq_enter(struct task_struct *tsk)
+static inline void account_irq_enter_time(struct task_struct *tsk)
 {
-       /*
-        * Hardirq can interrupt idle task anytime. So we need vtime_account()
-        * that performs the idle check in CONFIG_VIRT_CPU_ACCOUNTING.
-        * Softirq can also interrupt idle task directly if it calls
-        * local_bh_enable(). Such case probably don't exist but we never know.
-        * Ksoftirqd is not concerned because idle time is flushed on context
-        * switch. Softirqs in the end of hardirqs are also not a problem because
-        * the idle time is flushed on hardirq time already.
-        */
-       vtime_account(tsk);
+       vtime_account_irq_enter(tsk);
        irqtime_account_irq(tsk);
 }
 
-static inline void vtime_account_irq_exit(struct task_struct *tsk)
+static inline void account_irq_exit_time(struct task_struct *tsk)
 {
-       /* On hard|softirq exit we always account to hard|softirq cputime */
-       vtime_account_system(tsk);
+       vtime_account_irq_exit(tsk);
        irqtime_account_irq(tsk);
 }
 
index 87490ac4bd87c72909aa8171e12ec8381af54f8c..3a9df2f43be642a7cbad15f678ef29c7f85f27e5 100644 (file)
@@ -129,7 +129,7 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
        return wdd->driver_data;
 }
 
-/* drivers/watchdog/core/watchdog_core.c */
+/* drivers/watchdog/watchdog_core.c */
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
index 0707fb9551aa4c1011c88969a42cd4482450d035..a68f838a132c522df397b9398f8f2d64646008c0 100644 (file)
@@ -143,6 +143,8 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
 extern int             ip4_datagram_connect(struct sock *sk, 
                                             struct sockaddr *uaddr, int addr_len);
 
+extern void ip4_datagram_release_cb(struct sock *sk);
+
 struct ip_reply_arg {
        struct kvec iov[1];   
        int         flags;
index d8f5b9f5216939d2053c8c99ad54925fb5a0ce5c..e98aeb3da033a38e29f745d5f043a33d3888bcc3 100644 (file)
@@ -31,6 +31,8 @@ extern void nf_conntrack_cleanup(struct net *net);
 extern int nf_conntrack_proto_init(struct net *net);
 extern void nf_conntrack_proto_fini(struct net *net);
 
+extern void nf_conntrack_cleanup_end(void);
+
 extern bool
 nf_ct_get_tuple(const struct sk_buff *skb,
                unsigned int nhoff,
index a1d83cc8bf859d356b9d4b437c4d03590fa25453..923cb20051edfbb93a3fb84c8c78b7dae0993c82 100644 (file)
@@ -71,6 +71,7 @@ struct netns_ct {
        struct hlist_head       *expect_hash;
        struct hlist_nulls_head unconfirmed;
        struct hlist_nulls_head dying;
+       struct hlist_nulls_head tmpl;
        struct ip_conntrack_stat __percpu *stat;
        struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
        struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
index 591db7d657a37d42107b38582cd8a45ad5838552..c24060ee411e9e15a91a0fc5bd189eef8425869b 100644 (file)
@@ -8,6 +8,7 @@ struct ebt_table;
 
 struct netns_xt {
        struct list_head tables[NFPROTO_NUMPROTO];
+       bool notrack_deprecated_warning;
 #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \
     defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)
        struct ebt_table *broute_table;
index 93a6745bfdb2bb14933018a9bbc497e6b1c0cde7..182ca99405adfb30e7b72181847b4a5ffd5d69ca 100644 (file)
@@ -367,7 +367,7 @@ struct sock {
        unsigned short          sk_ack_backlog;
        unsigned short          sk_max_ack_backlog;
        __u32                   sk_priority;
-#ifdef CONFIG_CGROUPS
+#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
        __u32                   sk_cgrp_prioidx;
 #endif
        struct pid              *sk_peer_pid;
index 498433dd067dd64eb6c728e566e61585093e960f..938b7fd1120477213888f9c7e61f98039bea3e03 100644 (file)
@@ -34,17 +34,17 @@ extern int                          udpv6_connect(struct sock *sk,
                                                      struct sockaddr *uaddr,
                                                      int addr_len);
 
-extern int                     datagram_recv_ctl(struct sock *sk,
-                                                 struct msghdr *msg,
-                                                 struct sk_buff *skb);
-
-extern int                     datagram_send_ctl(struct net *net,
-                                                 struct sock *sk,
-                                                 struct msghdr *msg,
-                                                 struct flowi6 *fl6,
-                                                 struct ipv6_txoptions *opt,
-                                                 int *hlimit, int *tclass,
-                                                 int *dontfrag);
+extern int                     ip6_datagram_recv_ctl(struct sock *sk,
+                                                     struct msghdr *msg,
+                                                     struct sk_buff *skb);
+
+extern int                     ip6_datagram_send_ctl(struct net *net,
+                                                     struct sock *sk,
+                                                     struct msghdr *msg,
+                                                     struct flowi6 *fl6,
+                                                     struct ipv6_txoptions *opt,
+                                                     int *hlimit, int *tclass,
+                                                     int *dontfrag);
 
 #define                LOOPBACK4_IPV6          cpu_to_be32(0x7f000006)
 
diff --git a/include/rdma/Kbuild b/include/rdma/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51..dd8c48d14ed9637b3d1264ac5b88811e9be2dae6 100644 (file)
@@ -19,7 +19,7 @@
 
 struct cs4271_platform_data {
        int gpio_nreset;        /* GPIO driving Reset pin, if any */
-       int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
+       bool amutec_eq_bmutec;  /* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
index 769e27c774a3de382ec93650766621056dc78820..bc56738cb1091b8319b2413fe7e6b2f105ba0ac8 100644 (file)
@@ -58,8 +58,9 @@
        .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
        .put = snd_soc_put_volsw_range, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = xshift, .min = xmin,\
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
+               {.reg = xreg, .rreg = xreg, .shift = xshift, \
+                .rshift = xshift,  .min = xmin, .max = xmax, \
+                .platform_max = xmax, .invert = xinvert} }
 #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -88,8 +89,9 @@
        .info = snd_soc_info_volsw_range, \
        .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = xshift, .min = xmin,\
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
+               {.reg = xreg, .rreg = xreg, .shift = xshift, \
+                .rshift = xshift, .min = xmin, .max = xmax, \
+                .platform_max = xmax, .invert = xinvert} }
 #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
        .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
index 7cae2360221eb0e32f9e3a19dceaec939ade7296..663e34a5383f269d7c54a67f80fe9e73cbff1385 100644 (file)
@@ -174,6 +174,7 @@ typedef unsigned __bitwise__ sense_reason_t;
 
 enum tcm_sense_reason_table {
 #define R(x)   (__force sense_reason_t )(x)
+       TCM_NO_SENSE                            = R(0x00),
        TCM_NON_EXISTENT_LUN                    = R(0x01),
        TCM_UNSUPPORTED_SCSI_OPCODE             = R(0x02),
        TCM_INCORRECT_AMOUNT_OF_DATA            = R(0x03),
index f6372b01136657cd5a0b9213090733c87347250e..7e8c36bc708225c0f3eb79c0b33977c1dcb17519 100644 (file)
@@ -451,7 +451,7 @@ DEFINE_EVENT(ext4__page_op, ext4_releasepage,
        TP_ARGS(page)
 );
 
-TRACE_EVENT(ext4_invalidatepage,
+DECLARE_EVENT_CLASS(ext4_invalidatepage_op,
        TP_PROTO(struct page *page, unsigned long offset),
 
        TP_ARGS(page, offset),
@@ -477,6 +477,18 @@ TRACE_EVENT(ext4_invalidatepage,
                  (unsigned long) __entry->index, __entry->offset)
 );
 
+DEFINE_EVENT(ext4_invalidatepage_op, ext4_invalidatepage,
+       TP_PROTO(struct page *page, unsigned long offset),
+
+       TP_ARGS(page, offset)
+);
+
+DEFINE_EVENT(ext4_invalidatepage_op, ext4_journalled_invalidatepage,
+       TP_PROTO(struct page *page, unsigned long offset),
+
+       TP_ARGS(page, offset)
+);
+
 TRACE_EVENT(ext4_discard_blocks,
        TP_PROTO(struct super_block *sb, unsigned long long blk,
                        unsigned long long count),
diff --git a/include/trace/events/ras.h b/include/trace/events/ras.h
new file mode 100644 (file)
index 0000000..88b8783
--- /dev/null
@@ -0,0 +1,77 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ras
+
+#if !defined(_TRACE_AER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_AER_H
+
+#include <linux/tracepoint.h>
+#include <linux/edac.h>
+
+
+/*
+ * PCIe AER Trace event
+ *
+ * These events are generated when hardware detects a corrected or
+ * uncorrected event on a PCIe device. The event report has
+ * the following structure:
+ *
+ * char * dev_name -   The name of the slot where the device resides
+ *                     ([domain:]bus:device.function).
+ * u32 status -                Either the correctable or uncorrectable register
+ *                     indicating what error or errors have been seen
+ * u8 severity -       error severity 0:NONFATAL 1:FATAL 2:CORRECTED
+ */
+
+#define aer_correctable_errors         \
+       {BIT(0),        "Receiver Error"},              \
+       {BIT(6),        "Bad TLP"},                     \
+       {BIT(7),        "Bad DLLP"},                    \
+       {BIT(8),        "RELAY_NUM Rollover"},          \
+       {BIT(12),       "Replay Timer Timeout"},        \
+       {BIT(13),       "Advisory Non-Fatal"}
+
+#define aer_uncorrectable_errors               \
+       {BIT(4),        "Data Link Protocol"},          \
+       {BIT(12),       "Poisoned TLP"},                \
+       {BIT(13),       "Flow Control Protocol"},       \
+       {BIT(14),       "Completion Timeout"},          \
+       {BIT(15),       "Completer Abort"},             \
+       {BIT(16),       "Unexpected Completion"},       \
+       {BIT(17),       "Receiver Overflow"},           \
+       {BIT(18),       "Malformed TLP"},               \
+       {BIT(19),       "ECRC"},                        \
+       {BIT(20),       "Unsupported Request"}
+
+TRACE_EVENT(aer_event,
+       TP_PROTO(const char *dev_name,
+                const u32 status,
+                const u8 severity),
+
+       TP_ARGS(dev_name, status, severity),
+
+       TP_STRUCT__entry(
+               __string(       dev_name,       dev_name        )
+               __field(        u32,            status          )
+               __field(        u8,             severity        )
+       ),
+
+       TP_fast_assign(
+               __assign_str(dev_name, dev_name);
+               __entry->status         = status;
+               __entry->severity       = severity;
+       ),
+
+       TP_printk("%s PCIe Bus Error: severity=%s, %s\n",
+               __get_str(dev_name),
+               __entry->severity == HW_EVENT_ERR_CORRECTED ? "Corrected" :
+                       __entry->severity == HW_EVENT_ERR_FATAL ?
+                       "Fatal" : "Uncorrected",
+               __entry->severity == HW_EVENT_ERR_CORRECTED ?
+               __print_flags(__entry->status, "|", aer_correctable_errors) :
+               __print_flags(__entry->status, "|", aer_uncorrectable_errors))
+);
+
+#endif /* _TRACE_AER_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index d4f559b1ec3444eada48e8e9e1d8bd85f36da5b6..1918e832da4ffce61d1a057bd706ed52f81b07ce 100644 (file)
@@ -44,8 +44,10 @@ TRACE_EVENT(rcu_utilization,
  * of a new grace period or the end of an old grace period ("cpustart"
  * and "cpuend", respectively), a CPU passing through a quiescent
  * state ("cpuqs"), a CPU coming online or going offline ("cpuonl"
- * and "cpuofl", respectively), and a CPU being kicked for being too
- * long in dyntick-idle mode ("kick").
+ * and "cpuofl", respectively), a CPU being kicked for being too
+ * long in dyntick-idle mode ("kick"), a CPU accelerating its new
+ * callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU
+ * accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB").
  */
 TRACE_EVENT(rcu_grace_period,
 
@@ -393,7 +395,7 @@ TRACE_EVENT(rcu_kfree_callback,
  */
 TRACE_EVENT(rcu_batch_start,
 
-       TP_PROTO(char *rcuname, long qlen_lazy, long qlen, int blimit),
+       TP_PROTO(char *rcuname, long qlen_lazy, long qlen, long blimit),
 
        TP_ARGS(rcuname, qlen_lazy, qlen, blimit),
 
@@ -401,7 +403,7 @@ TRACE_EVENT(rcu_batch_start,
                __field(char *, rcuname)
                __field(long, qlen_lazy)
                __field(long, qlen)
-               __field(int, blimit)
+               __field(long, blimit)
        ),
 
        TP_fast_assign(
@@ -411,7 +413,7 @@ TRACE_EVENT(rcu_batch_start,
                __entry->blimit = blimit;
        ),
 
-       TP_printk("%s CBs=%ld/%ld bl=%d",
+       TP_printk("%s CBs=%ld/%ld bl=%ld",
                  __entry->rcuname, __entry->qlen_lazy, __entry->qlen,
                  __entry->blimit)
 );
@@ -523,22 +525,30 @@ TRACE_EVENT(rcu_batch_end,
  */
 TRACE_EVENT(rcu_torture_read,
 
-       TP_PROTO(char *rcutorturename, struct rcu_head *rhp),
+       TP_PROTO(char *rcutorturename, struct rcu_head *rhp,
+                unsigned long secs, unsigned long c_old, unsigned long c),
 
-       TP_ARGS(rcutorturename, rhp),
+       TP_ARGS(rcutorturename, rhp, secs, c_old, c),
 
        TP_STRUCT__entry(
                __field(char *, rcutorturename)
                __field(struct rcu_head *, rhp)
+               __field(unsigned long, secs)
+               __field(unsigned long, c_old)
+               __field(unsigned long, c)
        ),
 
        TP_fast_assign(
                __entry->rcutorturename = rcutorturename;
                __entry->rhp = rhp;
+               __entry->secs = secs;
+               __entry->c_old = c_old;
+               __entry->c = c;
        ),
 
-       TP_printk("%s torture read %p",
-                 __entry->rcutorturename, __entry->rhp)
+       TP_printk("%s torture read %p %luus c: %lu %lu",
+                 __entry->rcutorturename, __entry->rhp,
+                 __entry->secs, __entry->c_old, __entry->c)
 );
 
 /*
@@ -608,7 +618,8 @@ TRACE_EVENT(rcu_barrier,
 #define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0)
 #define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \
        do { } while (0)
-#define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
+#define trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
+       do { } while (0)
 #define trace_rcu_barrier(name, s, cpu, cnt, done) do { } while (0)
 
 #endif /* #else #ifdef CONFIG_RCU_TRACE */
index 0a78028984def29621fac7258997c29cf22b91fc..6fae30fd16abc8cba6911d9a3bbb539410edafe5 100644 (file)
  *     SA_RESTORER     0x04000000
  */
 
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index e7f52c334005bb3b461005a4be97620048053676..d5844122ff329dabf4d5c8431f138f48a86d0ed3 100644 (file)
@@ -6,24 +6,10 @@
  *     Joonyoung Shim <jy0922.shim@samsung.com>
  *     Seung-Woo Kim <sw0312.kim@samsung.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * 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 _UAPI_EXYNOS_DRM_H_
@@ -185,6 +171,8 @@ enum drm_exynos_flip {
        EXYNOS_DRM_FLIP_NONE = (0 << 0),
        EXYNOS_DRM_FLIP_VERTICAL = (1 << 0),
        EXYNOS_DRM_FLIP_HORIZONTAL = (1 << 1),
+       EXYNOS_DRM_FLIP_BOTH = EXYNOS_DRM_FLIP_VERTICAL |
+                       EXYNOS_DRM_FLIP_HORIZONTAL,
 };
 
 enum drm_exynos_degree {
index b746a3cf5fa9b6a56d75d1a4a5cf5bafa5a46a5a..c4d2e9c74002d00b0981157d55576609ba002899 100644 (file)
@@ -307,6 +307,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PRIME_VMAP_FLUSH         21
 #define I915_PARAM_RSVD_FOR_FUTURE_USE  22
 #define I915_PARAM_HAS_SECURE_BATCHES   23
+#define I915_PARAM_HAS_PINNED_BATCHES   24
 
 typedef struct drm_i915_getparam {
        int param;
@@ -677,6 +678,15 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_SECURE               (1<<9)
 
+/** Inform the kernel that the batch is and will always be pinned. This
+ * negates the requirement for a workaround to be performed to avoid
+ * an incoherent CS (such as can be found on 830/845). If this flag is
+ * not passed, the kernel will endeavour to make sure the batch is
+ * coherent with the CS before execution. If this flag is passed,
+ * userspace assumes the responsibility for ensuring the same.
+ */
+#define I915_EXEC_IS_PINNED            (1<<10)
+
 #define I915_EXEC_CONTEXT_ID_MASK      (0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
        (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
index 76352ac45f24bf1290196327ad9af8fb504e4d69..9f096f1c0907b7056bcbe396783fdb2237724a65 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/types.h>
 #include <linux/elf-em.h>
-#include <linux/ptrace.h>
 
 /* The netlink messages for the audit system is divided into blocks:
  * 1000 - 1099 are for commanding the audit system
 #define AUDIT_MMAP             1323    /* Record showing descriptor and flags in mmap */
 #define AUDIT_NETFILTER_PKT    1324    /* Packets traversing netfilter chains */
 #define AUDIT_NETFILTER_CFG    1325    /* Netfilter chain modifications */
+#define AUDIT_SECCOMP          1326    /* Secure Computing event */
 
 #define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
index 77cdba9df274c09f2d9e8972fca63da215d1a8d9..bb991dfe134f03743a4e40c7024324289910b0e9 100644 (file)
 #define AUTOFS_MIN_PROTO_VERSION       AUTOFS_PROTO_VERSION
 
 /*
- * Architectures where both 32- and 64-bit binaries can be executed
- * on 64-bit kernels need this.  This keeps the structure format
- * uniform, and makes sure the wait_queue_token isn't too big to be
- * passed back down to the kernel.
- *
- * This assumes that on these architectures:
- * mode     32 bit    64 bit
- * -------------------------
- * int      32 bit    32 bit
- * long     32 bit    64 bit
- *
- * If so, 32-bit user-space code should be backwards compatible.
+ * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed
+ * back to the kernel via ioctl from userspace. On architectures where 32- and
+ * 64-bit userspace binaries can be executed it's important that the size of
+ * autofs_wqt_t stays constant between 32- and 64-bit Linux kernels so that we
+ * do not break the binary ABI interface by changing the structure size.
  */
-
-#if defined(__sparc__) || defined(__mips__) || defined(__x86_64__) \
- || defined(__powerpc__) || defined(__s390__)
-typedef unsigned int autofs_wqt_t;
-#else
+#if defined(__ia64__) || defined(__alpha__) /* pure 64bit architectures */
 typedef unsigned long autofs_wqt_t;
+#else
+typedef unsigned int autofs_wqt_t;
 #endif
 
 /* Packet types */
index 91e3a360f61103451986008553dd91567e68fe13..539b179b349ca02953c74cf52ffb597fe6f1ff23 100644 (file)
@@ -268,8 +268,8 @@ enum {
 
 #define DM_VERSION_MAJOR       4
 #define DM_VERSION_MINOR       23
-#define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2012-07-25)"
+#define DM_VERSION_PATCHLEVEL  1
+#define DM_VERSION_EXTRA       "-ioctl (2012-12-18)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
index 12f68c7ceba65694dba0af1149995ddc21b13283..873e086ce3a1c51bb6be6aa2851ef56e94494d66 100644 (file)
@@ -23,6 +23,7 @@
 #define EXT4_SUPER_MAGIC       0xEF53
 #define BTRFS_SUPER_MAGIC      0x9123683E
 #define NILFS_SUPER_MAGIC      0x3434
+#define F2FS_SUPER_MAGIC       0xF2F52010
 #define HPFS_SUPER_MAGIC       0xf995e849
 #define ISOFS_SUPER_MAGIC      0x9660
 #define JFFS2_SUPER_MAGIC      0x72b6
index 78dbd2f996a3668665718e5dcad7918966640281..22d95c6854e0cb0fbadaafae1c681ed9ad805780 100644 (file)
@@ -10,6 +10,7 @@
 /* msgrcv options */
 #define MSG_NOERROR     010000  /* no error if message is too big */
 #define MSG_EXCEPT      020000  /* recv any msg except of specified type.*/
+#define MSG_COPY        040000  /* copy (not remove) all queue messages */
 
 /* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct msqid_ds {
index 6b7b6f1e2fd6a697dd26427c1130a5b51823d899..ebfadc56d1b43526c439086eb294124d20bec524 100644 (file)
 #define  PCI_EXP_DEVSTA_TRPND  0x20    /* Transactions Pending */
 #define PCI_EXP_LNKCAP         12      /* Link Capabilities */
 #define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
+#define  PCI_EXP_LNKCAP_SLS_2_5GB 0x1  /* LNKCAP2 SLS Vector bit 0 (2.5GT/s) */
+#define  PCI_EXP_LNKCAP_SLS_5_0GB 0x2  /* LNKCAP2 SLS Vector bit 1 (5.0GT/s) */
 #define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
 #define  PCI_EXP_LNKCAP_ASPMS  0x00000c00 /* ASPM Support */
 #define  PCI_EXP_LNKCAP_L0SEL  0x00007000 /* L0s Exit Latency */
index 4f63c05d27c91d04569971ea4a2c4849203c36a9..9fa9c622a7f45ab6032aefd74001930b4d7ddb07 100644 (file)
@@ -579,7 +579,8 @@ enum perf_event_type {
         *      { u32                   size;
         *        char                  data[size];}&& PERF_SAMPLE_RAW
         *
-        *      { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
+        *      { u64                   nr;
+        *        { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
         *
         *      { u64                   abi; # enum perf_sample_regs_abi
         *        u64                   regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER
index 78f99d97475b50c8427607d9bd23a3457a27319a..2c6c85f18ea027440761c780134bb757b0c53c8e 100644 (file)
@@ -50,7 +50,8 @@
 #define PORT_LPC3220   22      /* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR  23      /* CIR infrared port, has its own driver */
 #define PORT_XR17V35X  24      /* Exar XR17V35x UARTs */
-#define PORT_MAX_8250  24      /* max port ID */
+#define PORT_BRCM_TRUMANAGE    24
+#define PORT_MAX_8250  25      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
index dff452ed6d00a21058a7c8ae4e94d2d1ed207d4b..e1bd50c29ded87e7011c84a0b9e222ba9b437ff2 100644 (file)
@@ -4,5 +4,7 @@
 #include <asm/signal.h>
 #include <asm/siginfo.h>
 
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
 
 #endif /* _UAPI_LINUX_SIGNAL_H */
index 50598472dc411ea1b522ac5d499bd7ac8bba37ec..f738e25377ffbc3ed8e794246f03f718bdb1bab4 100644 (file)
 #define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
 #define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
 
+/*
+ * Interface status, Figure 9-5 USB 3.0 spec
+ */
+#define USB_INTRF_STAT_FUNC_RW_CAP     1
+#define USB_INTRF_STAT_FUNC_RW         2
+
 #define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
 
 /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
index 7d30240e5bfef76aedc3a8eee2a7991abe0f0a18..7000d96574025bda58c5253cf10e92d0249de9eb 100644 (file)
@@ -20,12 +20,8 @@ config CONSTRUCTORS
        bool
        depends on !UML
 
-config HAVE_IRQ_WORK
-       bool
-
 config IRQ_WORK
        bool
-       depends on HAVE_IRQ_WORK
 
 config BUILDTIME_EXTABLE_SORT
        bool
@@ -326,10 +322,13 @@ source "kernel/time/Kconfig"
 
 menu "CPU/Task time and stats accounting"
 
+config VIRT_CPU_ACCOUNTING
+       bool
+
 choice
        prompt "Cputime accounting"
        default TICK_CPU_ACCOUNTING if !PPC64
-       default VIRT_CPU_ACCOUNTING if PPC64
+       default VIRT_CPU_ACCOUNTING_NATIVE if PPC64
 
 # Kind of a stub config for the pure tick based cputime accounting
 config TICK_CPU_ACCOUNTING
@@ -342,9 +341,10 @@ config TICK_CPU_ACCOUNTING
 
          If unsure, say Y.
 
-config VIRT_CPU_ACCOUNTING
+config VIRT_CPU_ACCOUNTING_NATIVE
        bool "Deterministic task and CPU time accounting"
        depends on HAVE_VIRT_CPU_ACCOUNTING
+       select VIRT_CPU_ACCOUNTING
        help
          Select this option to enable more accurate task and CPU time
          accounting.  This is done by reading a CPU counter on each
@@ -354,6 +354,23 @@ config VIRT_CPU_ACCOUNTING
          this also enables accounting of stolen time on logically-partitioned
          systems.
 
+config VIRT_CPU_ACCOUNTING_GEN
+       bool "Full dynticks CPU time accounting"
+       depends on HAVE_CONTEXT_TRACKING && 64BIT
+       select VIRT_CPU_ACCOUNTING
+       select CONTEXT_TRACKING
+       help
+         Select this option to enable task and CPU time accounting on full
+         dynticks systems. This accounting is implemented by watching every
+         kernel-user boundaries using the context tracking subsystem.
+         The accounting is thus performed at the expense of some significant
+         overhead.
+
+         For now this is only useful if you are working on the full
+         dynticks subsystem development.
+
+         If unsure, say N.
+
 config IRQ_TIME_ACCOUNTING
        bool "Fine granularity task level IRQ time accounting"
        depends on HAVE_IRQ_TIME_ACCOUNTING
@@ -453,7 +470,7 @@ config TREE_RCU
 
 config TREE_PREEMPT_RCU
        bool "Preemptible tree-based hierarchical RCU"
-       depends on PREEMPT && SMP
+       depends on PREEMPT
        help
          This option selects the RCU implementation that is
          designed for very large SMP systems with hundreds or
@@ -461,6 +478,8 @@ config TREE_PREEMPT_RCU
          is also required.  It also scales down nicely to
          smaller systems.
 
+         Select this option if you are unsure.
+
 config TINY_RCU
        bool "UP-only small-memory-footprint RCU"
        depends on !PREEMPT && !SMP
@@ -486,6 +505,14 @@ config PREEMPT_RCU
          This option enables preemptible-RCU code that is common between
          the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations.
 
+config RCU_STALL_COMMON
+       def_bool ( TREE_RCU || TREE_PREEMPT_RCU || RCU_TRACE )
+       help
+         This option enables RCU CPU stall code that is common between
+         the TINY and TREE variants of RCU.  The purpose is to allow
+         the tiny variants to disable RCU CPU stall warnings, while
+         making these warnings mandatory for the tree variants.
+
 config CONTEXT_TRACKING
        bool
 
@@ -1182,7 +1209,7 @@ config CC_OPTIMIZE_FOR_SIZE
          Enabling this option will pass "-Os" instead of "-O2" to gcc
          resulting in a smaller kernel.
 
-         If unsure, say Y.
+         If unsure, say N.
 
 config SYSCTL
        bool
@@ -1263,6 +1290,7 @@ config HOTPLUG
 config PRINTK
        default y
        bool "Enable support for printk" if EXPERT
+       select IRQ_WORK
        help
          This option enables normal printk support. Removing it
          eliminates most of the message strings from the kernel image
index 5e4ded51788eb81f277c0b5674f5602730220df4..f9acf71b98109434f09b396568caa4afc0ce3e16 100644 (file)
@@ -36,6 +36,10 @@ __setup("noinitrd", no_initrd);
 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
        sys_unshare(CLONE_FS | CLONE_FILES);
+       /* stdin/stdout/stderr for /linuxrc */
+       sys_open("/dev/console", O_RDWR, 0);
+       sys_dup(0);
+       sys_dup(0);
        /* move initrd over / and chdir/chroot in initrd root */
        sys_chdir("/root");
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
index 8b2f3996b035f1aa44591afd29ea2f546706fae4..ba0a7f362d9e3ffbf00a45c7baa5c2f0a2186b8f 100644 (file)
@@ -2,6 +2,8 @@
 #include <linux/export.h>
 #include <linux/mqueue.h>
 #include <linux/sched.h>
+#include <linux/sched/sysctl.h>
+#include <linux/sched/rt.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
index baf1f0f5c4611eb08b3f0eae7995c5d789f8e741..cee4b5c66d81e1362fba3c7890eb1c86ab8c1abd 100644 (file)
@@ -604,7 +604,7 @@ asmlinkage void __init start_kernel(void)
        pidmap_init();
        anon_vma_init();
 #ifdef CONFIG_X86
-       if (efi_enabled)
+       if (efi_enabled(EFI_RUNTIME_SERVICES))
                efi_enter_virtual_mode();
 #endif
        thread_info_cache_init();
@@ -632,7 +632,7 @@ asmlinkage void __init start_kernel(void)
        acpi_early_init(); /* before LAPIC and SMP init */
        sfi_init_late();
 
-       if (efi_enabled) {
+       if (efi_enabled(EFI_RUNTIME_SERVICES)) {
                efi_late_init();
                efi_free_boot_services();
        }
@@ -797,10 +797,12 @@ static void __init do_pre_smp_initcalls(void)
 static int run_init_process(const char *init_filename)
 {
        argv_init[0] = init_filename;
-       return kernel_execve(init_filename, argv_init, envp_init);
+       return do_execve(init_filename,
+               (const char __user *const __user *)argv_init,
+               (const char __user *const __user *)envp_init);
 }
 
-static void __init kernel_init_freeable(void);
+static noinline void __init kernel_init_freeable(void);
 
 static int __ref kernel_init(void *unused)
 {
@@ -843,7 +845,7 @@ static int __ref kernel_init(void *unused)
              "See Linux Documentation/init.txt for guidance.");
 }
 
-static void __init kernel_init_freeable(void)
+static noinline void __init kernel_init_freeable(void)
 {
        /*
         * Wait until kthreadd is all set-up.
index ad9518eb26e06e648c6044b95de41d39e9b076d0..2547f29dcd1b5e00ab93ed37c594e93d6e1f5b75 100644 (file)
@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
        return err;
 }
 
+long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+       struct compat_msgbuf __user *msgp = dest;
+       size_t msgsz;
+
+       if (put_user(msg->m_type, &msgp->mtype))
+               return -EFAULT;
+
+       msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+       if (store_msg(msgp->mtext, msg, msgsz))
+               return -EFAULT;
+       return msgsz;
+}
+
 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 {
@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                           int version, void __user *uptr)
 {
-       struct compat_msgbuf __user *up;
-       long type;
-       int err;
-
        if (first < 0)
                return -EINVAL;
        if (second < 0)
@@ -348,23 +358,15 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 
        if (!version) {
                struct compat_ipc_kludge ipck;
-               err = -EINVAL;
                if (!uptr)
-                       goto out;
-               err = -EFAULT;
+                       return -EINVAL;
                if (copy_from_user (&ipck, uptr, sizeof(ipck)))
-                       goto out;
+                       return -EFAULT;
                uptr = compat_ptr(ipck.msgp);
                msgtyp = ipck.msgtyp;
        }
-       up = uptr;
-       err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
-       if (err < 0)
-               goto out;
-       if (put_user(type, &up->mtype))
-               err = -EFAULT;
-out:
-       return err;
+       return do_msgrcv(first, uptr, second, msgtyp, third,
+                        compat_do_msg_fill);
 }
 #else
 long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
@@ -385,16 +387,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
 long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
                       compat_ssize_t msgsz, long msgtyp, int msgflg)
 {
-       long err, mtype;
-
-       err =  do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);
-       if (err < 0)
-               goto out;
-
-       if (put_user(mtype, &msgp->mtype))
-               err = -EFAULT;
- out:
-       return err;
+       return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg,
+                        compat_do_msg_fill);
 }
 #endif
 
index 00fba2bab87d8019739e4645f98e21559688dcbe..130dfece27ac7cc74c40a60c6b8eeceb97963deb 100644 (file)
@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 
 static int zero;
 static int one = 1;
+#ifdef CONFIG_CHECKPOINT_RESTORE
+static int int_max = INT_MAX;
+#endif
 
 static struct ctl_table ipc_kern_table[] = {
        {
@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = {
                .extra1         = &zero,
                .extra2         = &one,
        },
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       {
+               .procname       = "sem_next_id",
+               .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
+       {
+               .procname       = "msg_next_id",
+               .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
+       {
+               .procname       = "shm_next_id",
+               .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
+#endif
        {}
 };
 
index a71af5a65abf2b6a3029c4792d13594317dba8d2..950572f9d7963858d46e01998fea00e14024f26b 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -755,26 +755,91 @@ static inline int convert_mode(long *msgtyp, int msgflg)
        return SEARCH_EQUAL;
 }
 
-long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
-               size_t msgsz, long msgtyp, int msgflg)
+static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+       struct msgbuf __user *msgp = dest;
+       size_t msgsz;
+
+       if (put_user(msg->m_type, &msgp->mtype))
+               return -EFAULT;
+
+       msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+       if (store_msg(msgp->mtext, msg, msgsz))
+               return -EFAULT;
+       return msgsz;
+}
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
+/*
+ * This function creates new kernel message structure, large enough to store
+ * bufsz message bytes.
+ */
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
+                                          int msgflg, long *msgtyp,
+                                          unsigned long *copy_number)
+{
+       struct msg_msg *copy;
+
+       *copy_number = *msgtyp;
+       *msgtyp = 0;
+       /*
+        * Create dummy message to copy real message to.
+        */
+       copy = load_msg(buf, bufsz);
+       if (!IS_ERR(copy))
+               copy->m_ts = bufsz;
+       return copy;
+}
+
+static inline void free_copy(struct msg_msg *copy)
+{
+       if (copy)
+               free_msg(copy);
+}
+#else
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
+                                          int msgflg, long *msgtyp,
+                                          unsigned long *copy_number)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline void free_copy(struct msg_msg *copy)
+{
+}
+#endif
+
+long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+              int msgflg,
+              long (*msg_handler)(void __user *, struct msg_msg *, size_t))
 {
        struct msg_queue *msq;
        struct msg_msg *msg;
        int mode;
        struct ipc_namespace *ns;
+       struct msg_msg *copy = NULL;
+       unsigned long copy_number = 0;
 
-       if (msqid < 0 || (long) msgsz < 0)
+       if (msqid < 0 || (long) bufsz < 0)
                return -EINVAL;
+       if (msgflg & MSG_COPY) {
+               copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, &copy_number);
+               if (IS_ERR(copy))
+                       return PTR_ERR(copy);
+       }
        mode = convert_mode(&msgtyp, msgflg);
        ns = current->nsproxy->ipc_ns;
 
        msq = msg_lock_check(ns, msqid);
-       if (IS_ERR(msq))
+       if (IS_ERR(msq)) {
+               free_copy(copy);
                return PTR_ERR(msq);
+       }
 
        for (;;) {
                struct msg_receiver msr_d;
                struct list_head *tmp;
+               long msg_counter = 0;
 
                msg = ERR_PTR(-EACCES);
                if (ipcperms(ns, &msq->q_perm, S_IRUGO))
@@ -793,12 +858,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
                                msg = walk_msg;
                                if (mode == SEARCH_LESSEQUAL &&
                                                walk_msg->m_type != 1) {
-                                       msg = walk_msg;
                                        msgtyp = walk_msg->m_type - 1;
-                               } else {
-                                       msg = walk_msg;
+                               } else if (msgflg & MSG_COPY) {
+                                       if (copy_number == msg_counter) {
+                                               /*
+                                                * Found requested message.
+                                                * Copy it.
+                                                */
+                                               msg = copy_msg(msg, copy);
+                                               if (IS_ERR(msg))
+                                                       goto out_unlock;
+                                               break;
+                                       }
+                               } else
                                        break;
-                               }
+                               msg_counter++;
                        }
                        tmp = tmp->next;
                }
@@ -807,10 +881,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
                         * Found a suitable message.
                         * Unlink it from the queue.
                         */
-                       if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
+                       if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
                                msg = ERR_PTR(-E2BIG);
                                goto out_unlock;
                        }
+                       /*
+                        * If we are copying, then do not unlink message and do
+                        * not update queue parameters.
+                        */
+                       if (msgflg & MSG_COPY)
+                               goto out_unlock;
                        list_del(&msg->m_list);
                        msq->q_qnum--;
                        msq->q_rtime = get_seconds();
@@ -834,7 +914,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
                if (msgflg & MSG_NOERROR)
                        msr_d.r_maxsize = INT_MAX;
                else
-                       msr_d.r_maxsize = msgsz;
+                       msr_d.r_maxsize = bufsz;
                msr_d.r_msg = ERR_PTR(-EAGAIN);
                current->state = TASK_INTERRUPTIBLE;
                msg_unlock(msq);
@@ -894,32 +974,21 @@ out_unlock:
                        break;
                }
        }
-       if (IS_ERR(msg))
+       if (IS_ERR(msg)) {
+               free_copy(copy);
                return PTR_ERR(msg);
+       }
 
-       msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-       *pmtype = msg->m_type;
-       if (store_msg(mtext, msg, msgsz))
-               msgsz = -EFAULT;
-
+       bufsz = msg_handler(buf, msg, bufsz);
        free_msg(msg);
 
-       return msgsz;
+       return bufsz;
 }
 
 SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
                long, msgtyp, int, msgflg)
 {
-       long err, mtype;
-
-       err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
-       if (err < 0)
-               goto out;
-
-       if (put_user(mtype, &msgp->mtype))
-               err = -EFAULT;
-out:
-       return err;
+       return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
 }
 
 #ifdef CONFIG_PROC_FS
index 6471f1bdae96f2c6650a3c369bb77d0dc357d388..ebfcbfa8b7f25a4193dcfd196963e4b87428a6e6 100644 (file)
@@ -102,7 +102,50 @@ out_err:
        free_msg(msg);
        return ERR_PTR(err);
 }
+#ifdef CONFIG_CHECKPOINT_RESTORE
+struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+{
+       struct msg_msgseg *dst_pseg, *src_pseg;
+       int len = src->m_ts;
+       int alen;
+
+       BUG_ON(dst == NULL);
+       if (src->m_ts > dst->m_ts)
+               return ERR_PTR(-EINVAL);
 
+       alen = len;
+       if (alen > DATALEN_MSG)
+               alen = DATALEN_MSG;
+
+       dst->next = NULL;
+       dst->security = NULL;
+
+       memcpy(dst + 1, src + 1, alen);
+
+       len -= alen;
+       dst_pseg = dst->next;
+       src_pseg = src->next;
+       while (len > 0) {
+               alen = len;
+               if (alen > DATALEN_SEG)
+                       alen = DATALEN_SEG;
+               memcpy(dst_pseg + 1, src_pseg + 1, alen);
+               dst_pseg = dst_pseg->next;
+               len -= alen;
+               src_pseg = src_pseg->next;
+       }
+
+       dst->m_type = src->m_type;
+       dst->m_ts = src->m_ts;
+
+       return dst;
+}
+#else
+struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+{
+       return ERR_PTR(-ENOSYS);
+}
+#endif
 int store_msg(void __user *dest, struct msg_msg *msg, int len)
 {
        int alen;
index 72fd0785ac948b4c3813a2aac8f463ea41e7955f..74e1d9c7a98afcef566b80bf906e1398f94e7760 100644 (file)
@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)
 
        ids->in_use = 0;
        ids->seq = 0;
+       ids->next_id = -1;
        {
                int seq_limit = INT_MAX/SEQ_MULTIPLIER;
                if (seq_limit > USHRT_MAX)
@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        kuid_t euid;
        kgid_t egid;
        int id, err;
+       int next_id = ids->next_id;
 
        if (size > IPCMNI)
                size = IPCMNI;
@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        rcu_read_lock();
        spin_lock(&new->lock);
 
-       err = idr_get_new(&ids->ipcs_idr, new, &id);
+       err = idr_get_new_above(&ids->ipcs_idr, new,
+                               (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
        if (err) {
                spin_unlock(&new->lock);
                rcu_read_unlock();
@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        new->cuid = new->uid = euid;
        new->gid = new->cgid = egid;
 
-       new->seq = ids->seq++;
-       if(ids->seq > ids->seq_max)
-               ids->seq = 0;
+       if (next_id < 0) {
+               new->seq = ids->seq++;
+               if (ids->seq > ids->seq_max)
+                       ids->seq = 0;
+       } else {
+               new->seq = ipcid_to_seqx(next_id);
+               ids->next_id = -1;
+       }
 
        new->id = ipc_buildid(id, new->seq);
        return id;
index c8fe2f7631e9b616177d69c8ac614e901db669d2..eeb79a1fbd834eda23027624824faf94bfb2f459 100644 (file)
@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 #define IPC_SHM_IDS    2
 
 #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
 
 /* must be called with ids->rw_mutex acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
@@ -139,6 +140,7 @@ int ipc_parse_version (int *cmd);
 
 extern void free_msg(struct msg_msg *msg);
 extern struct msg_msg *load_msg(const void __user *src, int len);
+extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
 extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
 
 extern void recompute_msgmni(struct ipc_namespace *);
index 051e071a06e7a745a96c2fac6317d330dc33da43..e8b1627ab9c7cf21892acb45722293815ada0ede 100644 (file)
@@ -566,6 +566,7 @@ out:
 void acct_collect(long exitcode, int group_dead)
 {
        struct pacct_struct *pacct = &current->signal->pacct;
+       cputime_t utime, stime;
        unsigned long vsize = 0;
 
        if (group_dead && current->mm) {
@@ -593,8 +594,9 @@ void acct_collect(long exitcode, int group_dead)
                pacct->ac_flag |= ACORE;
        if (current->flags & PF_SIGNALED)
                pacct->ac_flag |= AXSIG;
-       pacct->ac_utime += current->utime;
-       pacct->ac_stime += current->stime;
+       task_cputime(current, &utime, &stime);
+       pacct->ac_utime += utime;
+       pacct->ac_stime += stime;
        pacct->ac_minflt += current->min_flt;
        pacct->ac_majflt += current->maj_flt;
        spin_unlock_irq(&current->sighand->siglock);
index 9d31183848582ca8da812d70d2d68364ff898f1d..6f34904a0b5357ba84ae2e8eaa9188c67b1b09d4 100644 (file)
@@ -86,18 +86,27 @@ static atomic_t entry_count;
  */
 static async_cookie_t  __lowest_in_progress(struct async_domain *running)
 {
+       async_cookie_t first_running = next_cookie;     /* infinity value */
+       async_cookie_t first_pending = next_cookie;     /* ditto */
        struct async_entry *entry;
 
+       /*
+        * Both running and pending lists are sorted but not disjoint.
+        * Take the first cookies from both and return the min.
+        */
        if (!list_empty(&running->domain)) {
                entry = list_first_entry(&running->domain, typeof(*entry), list);
-               return entry->cookie;
+               first_running = entry->cookie;
        }
 
-       list_for_each_entry(entry, &async_pending, list)
-               if (entry->running == running)
-                       return entry->cookie;
+       list_for_each_entry(entry, &async_pending, list) {
+               if (entry->running == running) {
+                       first_pending = entry->cookie;
+                       break;
+               }
+       }
 
-       return next_cookie;     /* "infinity" value */
+       return min(first_running, first_pending);
 }
 
 static async_cookie_t  lowest_in_progress(struct async_domain *running)
@@ -118,13 +127,17 @@ static void async_run_entry_fn(struct work_struct *work)
 {
        struct async_entry *entry =
                container_of(work, struct async_entry, work);
+       struct async_entry *pos;
        unsigned long flags;
        ktime_t uninitialized_var(calltime), delta, rettime;
        struct async_domain *running = entry->running;
 
-       /* 1) move self to the running queue */
+       /* 1) move self to the running queue, make sure it stays sorted */
        spin_lock_irqsave(&async_lock, flags);
-       list_move_tail(&entry->list, &running->domain);
+       list_for_each_entry_reverse(pos, &running->domain, list)
+               if (entry->cookie < pos->cookie)
+                       break;
+       list_move_tail(&entry->list, &pos->list);
        spin_unlock_irqrestore(&async_lock, flags);
 
        /* 2) run (and print duration) */
@@ -196,6 +209,9 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a
        atomic_inc(&entry_count);
        spin_unlock_irqrestore(&async_lock, flags);
 
+       /* mark that this task has queued an async job, used by module init */
+       current->flags |= PF_USED_ASYNC;
+
        /* schedule for execution */
        queue_work(system_unbound_wq, &entry->work);
 
index 40414e9143db609b194b04e95c798351118f07b7..d596e5355f153d0cac5da1bc7806239a1ec6b860 100644 (file)
@@ -272,6 +272,8 @@ static int audit_log_config_change(char *function_name, int new, int old,
        int rc = 0;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+       if (unlikely(!ab))
+               return rc;
        audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
                         old, from_kuid(&init_user_ns, loginuid), sessionid);
        if (sid) {
@@ -619,6 +621,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
        }
 
        *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+       if (unlikely(!*ab))
+               return rc;
        audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
                         task_tgid_vnr(current),
                         from_kuid(&init_user_ns, current_uid()),
@@ -1097,6 +1101,23 @@ static inline void audit_get_stamp(struct audit_context *ctx,
        }
 }
 
+/*
+ * Wait for auditd to drain the queue a little
+ */
+static void wait_for_auditd(unsigned long sleep_time)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&audit_backlog_wait, &wait);
+
+       if (audit_backlog_limit &&
+           skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
+               schedule_timeout(sleep_time);
+
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&audit_backlog_wait, &wait);
+}
+
 /* Obtain an audit buffer.  This routine does locking to obtain the
  * audit buffer, but then no locking is required for calls to
  * audit_log_*format.  If the tsk is a task that is currently in a
@@ -1142,20 +1163,13 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
 
        while (audit_backlog_limit
               && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
-               if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time
-                   && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {
+               if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) {
+                       unsigned long sleep_time;
 
-                       /* Wait for auditd to drain the queue a little */
-                       DECLARE_WAITQUEUE(wait, current);
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       add_wait_queue(&audit_backlog_wait, &wait);
-
-                       if (audit_backlog_limit &&
-                           skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
-                               schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);
-
-                       __set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&audit_backlog_wait, &wait);
+                       sleep_time = timeout_start + audit_backlog_wait_time -
+                                       jiffies;
+                       if ((long)sleep_time > 0)
+                               wait_for_auditd(sleep_time);
                        continue;
                }
                if (audit_rate_check() && printk_ratelimit())
index ed206fd88cca76e75a0d8866ab703a7f6fdf38d6..642a89c4f3d60c23cabf89b86d387f2a29b2bea9 100644 (file)
@@ -249,7 +249,7 @@ static void untag_chunk(struct node *p)
                list_del_rcu(&chunk->hash);
                spin_unlock(&hash_lock);
                spin_unlock(&entry->lock);
-               fsnotify_destroy_mark(entry);
+               fsnotify_destroy_mark(entry, audit_tree_group);
                goto out;
        }
 
@@ -291,7 +291,7 @@ static void untag_chunk(struct node *p)
                owner->root = new;
        spin_unlock(&hash_lock);
        spin_unlock(&entry->lock);
-       fsnotify_destroy_mark(entry);
+       fsnotify_destroy_mark(entry, audit_tree_group);
        fsnotify_put_mark(&new->mark);  /* drop initial reference */
        goto out;
 
@@ -331,7 +331,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
                spin_unlock(&hash_lock);
                chunk->dead = 1;
                spin_unlock(&entry->lock);
-               fsnotify_destroy_mark(entry);
+               fsnotify_destroy_mark(entry, audit_tree_group);
                fsnotify_put_mark(entry);
                return 0;
        }
@@ -412,7 +412,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
                spin_unlock(&chunk_entry->lock);
                spin_unlock(&old_entry->lock);
 
-               fsnotify_destroy_mark(chunk_entry);
+               fsnotify_destroy_mark(chunk_entry, audit_tree_group);
 
                fsnotify_put_mark(chunk_entry);
                fsnotify_put_mark(old_entry);
@@ -443,17 +443,32 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
        spin_unlock(&hash_lock);
        spin_unlock(&chunk_entry->lock);
        spin_unlock(&old_entry->lock);
-       fsnotify_destroy_mark(old_entry);
+       fsnotify_destroy_mark(old_entry, audit_tree_group);
        fsnotify_put_mark(chunk_entry); /* drop initial reference */
        fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
        return 0;
 }
 
+static void audit_log_remove_rule(struct audit_krule *rule)
+{
+       struct audit_buffer *ab;
+
+       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+       if (unlikely(!ab))
+               return;
+       audit_log_format(ab, "op=");
+       audit_log_string(ab, "remove rule");
+       audit_log_format(ab, " dir=");
+       audit_log_untrustedstring(ab, rule->tree->pathname);
+       audit_log_key(ab, rule->filterkey);
+       audit_log_format(ab, " list=%d res=1", rule->listnr);
+       audit_log_end(ab);
+}
+
 static void kill_rules(struct audit_tree *tree)
 {
        struct audit_krule *rule, *next;
        struct audit_entry *entry;
-       struct audit_buffer *ab;
 
        list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
                entry = container_of(rule, struct audit_entry, rule);
@@ -461,14 +476,7 @@ static void kill_rules(struct audit_tree *tree)
                list_del_init(&rule->rlist);
                if (rule->tree) {
                        /* not a half-baked one */
-                       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-                       audit_log_format(ab, "op=");
-                       audit_log_string(ab, "remove rule");
-                       audit_log_format(ab, " dir=");
-                       audit_log_untrustedstring(ab, rule->tree->pathname);
-                       audit_log_key(ab, rule->filterkey);
-                       audit_log_format(ab, " list=%d res=1", rule->listnr);
-                       audit_log_end(ab);
+                       audit_log_remove_rule(rule);
                        rule->tree = NULL;
                        list_del_rcu(&entry->list);
                        list_del(&entry->rule.list);
index 9a9ae6e3d290025179a964c577de517f24fbe75c..22831c4d369c67d988b1f0702f9db51bac6275bf 100644 (file)
@@ -240,6 +240,8 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc
        if (audit_enabled) {
                struct audit_buffer *ab;
                ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
+               if (unlikely(!ab))
+                       return;
                audit_log_format(ab, "auid=%u ses=%u op=",
                                 from_kuid(&init_user_ns, audit_get_loginuid(current)),
                                 audit_get_sessionid(current));
@@ -350,7 +352,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
        }
        mutex_unlock(&audit_filter_mutex);
 
-       fsnotify_destroy_mark(&parent->mark);
+       fsnotify_destroy_mark(&parent->mark, audit_watch_group);
 }
 
 /* Get path information necessary for adding watches. */
@@ -457,7 +459,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 
                if (list_empty(&parent->watches)) {
                        audit_get_parent(parent);
-                       fsnotify_destroy_mark(&parent->mark);
+                       fsnotify_destroy_mark(&parent->mark, audit_watch_group);
                        audit_put_parent(parent);
                }
        }
index 7f19f23d38a3347373ec00a629c6c0b39a8f770a..f9fc54bbe06faa3e845e19871d15ace3e6c5e1b3 100644 (file)
@@ -1144,7 +1144,6 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
  * audit_receive_filter - apply all rules to the specified message type
  * @type: audit message type
  * @pid: target pid for netlink audit messages
- * @uid: target uid for netlink audit messages
  * @seq: netlink audit message sequence (serial) number
  * @data: payload data
  * @datasz: size of payload data
index e37e6a12c5e32c204ca93b4422c52ffaee72aad3..a371f857a0a908a40a960511bf047d81ade471a9 100644 (file)
@@ -1464,14 +1464,14 @@ static void show_special(struct audit_context *context, int *call_panic)
                        audit_log_end(ab);
                        ab = audit_log_start(context, GFP_KERNEL,
                                             AUDIT_IPC_SET_PERM);
+                       if (unlikely(!ab))
+                               return;
                        audit_log_format(ab,
                                "qbytes=%lx ouid=%u ogid=%u mode=%#ho",
                                context->ipc.qbytes,
                                context->ipc.perm_uid,
                                context->ipc.perm_gid,
                                context->ipc.perm_mode);
-                       if (!ab)
-                               return;
                }
                break; }
        case AUDIT_MQ_OPEN: {
@@ -2675,7 +2675,7 @@ void __audit_mmap_fd(int fd, int flags)
        context->type = AUDIT_MMAP;
 }
 
-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+static void audit_log_task(struct audit_buffer *ab)
 {
        kuid_t auid, uid;
        kgid_t gid;
@@ -2693,6 +2693,11 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
        audit_log_task_context(ab);
        audit_log_format(ab, " pid=%d comm=", current->pid);
        audit_log_untrustedstring(ab, current->comm);
+}
+
+static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+{
+       audit_log_task(ab);
        audit_log_format(ab, " reason=");
        audit_log_string(ab, reason);
        audit_log_format(ab, " sig=%ld", signr);
@@ -2715,6 +2720,8 @@ void audit_core_dumps(long signr)
                return;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+       if (unlikely(!ab))
+               return;
        audit_log_abend(ab, "memory violation", signr);
        audit_log_end(ab);
 }
@@ -2723,8 +2730,11 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
 {
        struct audit_buffer *ab;
 
-       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-       audit_log_abend(ab, "seccomp", signr);
+       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
+       if (unlikely(!ab))
+               return;
+       audit_log_task(ab);
+       audit_log_format(ab, " sig=%ld", signr);
        audit_log_format(ab, " syscall=%ld", syscall);
        audit_log_format(ab, " compat=%d", is_compat_task());
        audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
index f6150e92dfc9366488ce45a2b91e98b9fbd7e150..36700e9e2be9125f976963cb1fca4316460dee00 100644 (file)
@@ -535,9 +535,11 @@ asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru)
        return 0;
 }
 
-asmlinkage long
-compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
-       struct compat_rusage __user *ru)
+COMPAT_SYSCALL_DEFINE4(wait4,
+       compat_pid_t, pid,
+       compat_uint_t __user *, stat_addr,
+       int, options,
+       struct compat_rusage __user *, ru)
 {
        if (!ru) {
                return sys_wait4(pid, stat_addr, options, NULL);
@@ -564,9 +566,10 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
        }
 }
 
-asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
-               struct compat_siginfo __user *uinfo, int options,
-               struct compat_rusage __user *uru)
+COMPAT_SYSCALL_DEFINE5(waitid,
+               int, which, compat_pid_t, pid,
+               struct compat_siginfo __user *, uinfo, int, options,
+               struct compat_rusage __user *, uru)
 {
        siginfo_t info;
        struct rusage ru;
@@ -584,7 +587,11 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
                return ret;
 
        if (uru) {
-               ret = put_compat_rusage(&ru, uru);
+               /* sys_waitid() overwrites everything in ru */
+               if (COMPAT_USE_64BIT_TIME)
+                       ret = copy_to_user(uru, &ru, sizeof(ru));
+               else
+                       ret = put_compat_rusage(&ru, uru);
                if (ret)
                        return ret;
        }
@@ -994,7 +1001,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
        sigset_from_compat(&s, &s32);
 
        if (uts) {
-               if (get_compat_timespec(&t, uts))
+               if (compat_get_timespec(&t, uts))
                        return -EFAULT;
        }
 
index e0e07fd55508eeca456e7c8e6567dec1d25a9586..65349f07b8782a19f13014e66b8ff8ac0e7a5ecf 100644 (file)
@@ -1,29 +1,41 @@
+/*
+ * Context tracking: Probe on high level context boundaries such as kernel
+ * and userspace. This includes syscalls and exceptions entry/exit.
+ *
+ * This is used by RCU to remove its dependency on the timer tick while a CPU
+ * runs in userspace.
+ *
+ *  Started by Frederic Weisbecker:
+ *
+ * Copyright (C) 2012 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
+ *
+ * Many thanks to Gilad Ben-Yossef, Paul McKenney, Ingo Molnar, Andrew Morton,
+ * Steven Rostedt, Peter Zijlstra for suggestions and improvements.
+ *
+ */
+
 #include <linux/context_tracking.h>
+#include <linux/kvm_host.h>
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
-#include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/export.h>
 
-struct context_tracking {
-       /*
-        * When active is false, hooks are not set to
-        * minimize overhead: TIF flags are cleared
-        * and calls to user_enter/exit are ignored. This
-        * may be further optimized using static keys.
-        */
-       bool active;
-       enum {
-               IN_KERNEL = 0,
-               IN_USER,
-       } state;
-};
-
-static DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
+DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
 #ifdef CONFIG_CONTEXT_TRACKING_FORCE
        .active = true,
 #endif
 };
 
+/**
+ * user_enter - Inform the context tracking that the CPU is going to
+ *              enter userspace mode.
+ *
+ * This function must be called right before we switch from the kernel
+ * to userspace, when it's guaranteed the remaining kernel instructions
+ * to execute won't use any RCU read side critical section because this
+ * function sets RCU in extended quiescent state.
+ */
 void user_enter(void)
 {
        unsigned long flags;
@@ -39,40 +51,90 @@ void user_enter(void)
        if (in_interrupt())
                return;
 
+       /* Kernel threads aren't supposed to go to userspace */
        WARN_ON_ONCE(!current->mm);
 
        local_irq_save(flags);
        if (__this_cpu_read(context_tracking.active) &&
            __this_cpu_read(context_tracking.state) != IN_USER) {
-               __this_cpu_write(context_tracking.state, IN_USER);
+               /*
+                * At this stage, only low level arch entry code remains and
+                * then we'll run in userspace. We can assume there won't be
+                * any RCU read-side critical section until the next call to
+                * user_exit() or rcu_irq_enter(). Let's remove RCU's dependency
+                * on the tick.
+                */
+               vtime_user_enter(current);
                rcu_user_enter();
+               __this_cpu_write(context_tracking.state, IN_USER);
        }
        local_irq_restore(flags);
 }
 
+
+/**
+ * user_exit - Inform the context tracking that the CPU is
+ *             exiting userspace mode and entering the kernel.
+ *
+ * This function must be called after we entered the kernel from userspace
+ * before any use of RCU read side critical section. This potentially include
+ * any high level kernel code like syscalls, exceptions, signal handling, etc...
+ *
+ * This call supports re-entrancy. This way it can be called from any exception
+ * handler without needing to know if we came from userspace or not.
+ */
 void user_exit(void)
 {
        unsigned long flags;
 
-       /*
-        * Some contexts may involve an exception occuring in an irq,
-        * leading to that nesting:
-        * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
-        * This would mess up the dyntick_nesting count though. And rcu_irq_*()
-        * helpers are enough to protect RCU uses inside the exception. So
-        * just return immediately if we detect we are in an IRQ.
-        */
        if (in_interrupt())
                return;
 
        local_irq_save(flags);
        if (__this_cpu_read(context_tracking.state) == IN_USER) {
-               __this_cpu_write(context_tracking.state, IN_KERNEL);
+               /*
+                * We are going to run code that may use RCU. Inform
+                * RCU core about that (ie: we may need the tick again).
+                */
                rcu_user_exit();
+               vtime_user_exit(current);
+               __this_cpu_write(context_tracking.state, IN_KERNEL);
        }
        local_irq_restore(flags);
 }
 
+void guest_enter(void)
+{
+       if (vtime_accounting_enabled())
+               vtime_guest_enter(current);
+       else
+               __guest_enter();
+}
+EXPORT_SYMBOL_GPL(guest_enter);
+
+void guest_exit(void)
+{
+       if (vtime_accounting_enabled())
+               vtime_guest_exit(current);
+       else
+               __guest_exit();
+}
+EXPORT_SYMBOL_GPL(guest_exit);
+
+
+/**
+ * context_tracking_task_switch - context switch the syscall callbacks
+ * @prev: the task that is being switched out
+ * @next: the task that is being switched in
+ *
+ * The context tracking uses the syscall slow path to implement its user-kernel
+ * boundaries probes on syscalls. This way it doesn't impact the syscall fast
+ * path on CPUs that don't do context tracking.
+ *
+ * But we need to clear the flag on the previous task because it may later
+ * migrate to some CPU that doesn't do the context tracking. As such the TIF
+ * flag may not be desired there.
+ */
 void context_tracking_task_switch(struct task_struct *prev,
                             struct task_struct *next)
 {
index 3046a503242c8eb67f031d445713a9e55c986e73..b5e4ab2d427e874404347c7e20186ed4cfd2f488 100644 (file)
@@ -224,11 +224,13 @@ void clear_tasks_mm_cpumask(int cpu)
 static inline void check_for_tasks(int cpu)
 {
        struct task_struct *p;
+       cputime_t utime, stime;
 
        write_lock_irq(&tasklist_lock);
        for_each_process(p) {
+               task_cputime(p, &utime, &stime);
                if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
-                   (p->utime || p->stime))
+                   (utime || stime))
                        printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d "
                                "(state = %ld, flags = %x)\n",
                                p->comm, task_pid_nr(p), cpu,
@@ -254,6 +256,8 @@ static int __ref take_cpu_down(void *_param)
                return err;
 
        cpu_notify(CPU_DYING | param->mod, param->hcpu);
+       /* Park the stopper thread */
+       kthread_park(current);
        return 0;
 }
 
index 4d5f8d5612f349389fee0c22442267b6545c3931..8875254120b66f9a0a6e784d83fc6a1e76f6f4c0 100644 (file)
@@ -1970,6 +1970,8 @@ static int kdb_lsmod(int argc, const char **argv)
 
        kdb_printf("Module                  Size  modstruct     Used by\n");
        list_for_each_entry(mod, kdb_modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
 
                kdb_printf("%-20s%8u  0x%p ", mod->name,
                           mod->core_size, (void *)mod);
index 418b3f7053aaad32cef7d6082e833e5f33fdd6b7..d473988c1d0bc7505db5cbd17f637787bcdd3d1c 100644 (file)
@@ -106,6 +106,7 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
        unsigned long long t2, t3;
        unsigned long flags;
        struct timespec ts;
+       cputime_t utime, stime, stimescaled, utimescaled;
 
        /* Though tsk->delays accessed later, early exit avoids
         * unnecessary returning of other data
@@ -114,12 +115,14 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
                goto done;
 
        tmp = (s64)d->cpu_run_real_total;
-       cputime_to_timespec(tsk->utime + tsk->stime, &ts);
+       task_cputime(tsk, &utime, &stime);
+       cputime_to_timespec(utime + stime, &ts);
        tmp += timespec_to_ns(&ts);
        d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp;
 
        tmp = (s64)d->cpu_scaled_run_real_total;
-       cputime_to_timespec(tsk->utimescaled + tsk->stimescaled, &ts);
+       task_cputime_scaled(tsk, &utimescaled, &stimescaled);
+       cputime_to_timespec(utimescaled + stimescaled, &ts);
        tmp += timespec_to_ns(&ts);
        d->cpu_scaled_run_real_total =
                (tmp < (s64)d->cpu_scaled_run_real_total) ? 0 : tmp;
index 301079d06f24ebe44081a286766436de104a3a91..5c75791d7269e87c19a86fe711364f2c3c2793f2 100644 (file)
@@ -907,6 +907,15 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
                ctx->nr_stat++;
 }
 
+/*
+ * Initialize event state based on the perf_event_attr::disabled.
+ */
+static inline void perf_event__state_init(struct perf_event *event)
+{
+       event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF :
+                                             PERF_EVENT_STATE_INACTIVE;
+}
+
 /*
  * Called at perf_event creation and when events are attached/detached from a
  * group.
@@ -6162,11 +6171,14 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
        if (task) {
                event->attach_state = PERF_ATTACH_TASK;
+
+               if (attr->type == PERF_TYPE_TRACEPOINT)
+                       event->hw.tp_target = task;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
                /*
                 * hw_breakpoint is a bit difficult here..
                 */
-               if (attr->type == PERF_TYPE_BREAKPOINT)
+               else if (attr->type == PERF_TYPE_BREAKPOINT)
                        event->hw.bp_target = task;
 #endif
        }
@@ -6179,8 +6191,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        event->overflow_handler = overflow_handler;
        event->overflow_handler_context = context;
 
-       if (attr->disabled)
-               event->state = PERF_EVENT_STATE_OFF;
+       perf_event__state_init(event);
 
        pmu = NULL;
 
@@ -6609,9 +6620,17 @@ SYSCALL_DEFINE5(perf_event_open,
 
                mutex_lock(&gctx->mutex);
                perf_remove_from_context(group_leader);
+
+               /*
+                * Removing from the context ends up with disabled
+                * event. What we want here is event in the initial
+                * startup state, ready to be add into new context.
+                */
+               perf_event__state_init(group_leader);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
                        perf_remove_from_context(sibling);
+                       perf_event__state_init(sibling);
                        put_ctx(gctx);
                }
                mutex_unlock(&gctx->mutex);
index fe8a916507ed278cf545196561878a842547a865..a64f8aeb5c1f5adae53fde406b3d904e1485aa80 100644 (file)
@@ -676,7 +676,7 @@ int __init init_hw_breakpoint(void)
  err_alloc:
        for_each_possible_cpu(err_cpu) {
                for (i = 0; i < TYPE_MAX; i++)
-                       kfree(per_cpu(nr_task_bp_pinned[i], cpu));
+                       kfree(per_cpu(nr_task_bp_pinned[i], err_cpu));
                if (err_cpu == cpu)
                        break;
        }
index dea7acfbb0710889bf19e5fcb6584da4c5302f5d..a567c8c7ef31fa8c7d9416c8a255717f6b978932 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pagemap.h>     /* read_mapping_page */
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/rmap.h>                /* anon_vma_prepare */
 #include <linux/mmu_notifier.h>        /* set_pte_at_notify */
 #include <linux/swap.h>                /* try_to_free_swap */
 #define MAX_UPROBE_XOL_SLOTS           UINSNS_PER_PAGE
 
 static struct rb_root uprobes_tree = RB_ROOT;
-
-static DEFINE_SPINLOCK(uprobes_treelock);      /* serialize rbtree access */
-
-#define UPROBES_HASH_SZ        13
-
 /*
- * We need separate register/unregister and mmap/munmap lock hashes because
- * of mmap_sem nesting.
- *
- * uprobe_register() needs to install probes on (potentially) all processes
- * and thus needs to acquire multiple mmap_sems (consequtively, not
- * concurrently), whereas uprobe_mmap() is called while holding mmap_sem
- * for the particular process doing the mmap.
- *
- * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem
- * because of lock order against i_mmap_mutex. This means there's a hole in
- * the register vma iteration where a mmap() can happen.
- *
- * Thus uprobe_register() can race with uprobe_mmap() and we can try and
- * install a probe where one is already installed.
+ * allows us to skip the uprobe_mmap if there are no uprobe events active
+ * at this time.  Probably a fine grained per inode count is better?
  */
+#define no_uprobe_events()     RB_EMPTY_ROOT(&uprobes_tree)
 
-/* serialize (un)register */
-static struct mutex uprobes_mutex[UPROBES_HASH_SZ];
-
-#define uprobes_hash(v)                (&uprobes_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ])
+static DEFINE_SPINLOCK(uprobes_treelock);      /* serialize rbtree access */
 
+#define UPROBES_HASH_SZ        13
 /* serialize uprobe->pending_list */
 static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
 #define uprobes_mmap_hash(v)   (&uprobes_mmap_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ])
 
 static struct percpu_rw_semaphore dup_mmap_sem;
 
-/*
- * uprobe_events allows us to skip the uprobe_mmap if there are no uprobe
- * events active at this time.  Probably a fine grained per inode count is
- * better?
- */
-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
+#define UPROBE_SKIP_SSTEP      1
 
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
+       struct rw_semaphore     register_rwsem;
        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 */
@@ -430,9 +404,6 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
        u = __insert_uprobe(uprobe);
        spin_unlock(&uprobes_treelock);
 
-       /* For now assume that the instruction need not be single-stepped */
-       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
-
        return u;
 }
 
@@ -452,8 +423,10 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
 
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
+       init_rwsem(&uprobe->register_rwsem);
        init_rwsem(&uprobe->consumer_rwsem);
-       mutex_init(&uprobe->copy_mutex);
+       /* For now assume that the instruction need not be single-stepped */
+       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -463,38 +436,17 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
                kfree(uprobe);
                uprobe = cur_uprobe;
                iput(inode);
-       } else {
-               atomic_inc(&uprobe_events);
        }
 
        return uprobe;
 }
 
-static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
-{
-       struct uprobe_consumer *uc;
-
-       if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
-               return;
-
-       down_read(&uprobe->consumer_rwsem);
-       for (uc = uprobe->consumers; uc; uc = uc->next) {
-               if (!uc->filter || uc->filter(uc, current))
-                       uc->handler(uc, regs);
-       }
-       up_read(&uprobe->consumer_rwsem);
-}
-
-/* Returns the previous consumer */
-static struct uprobe_consumer *
-consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc)
+static void consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
        down_write(&uprobe->consumer_rwsem);
        uc->next = uprobe->consumers;
        uprobe->consumers = uc;
        up_write(&uprobe->consumer_rwsem);
-
-       return uc->next;
 }
 
 /*
@@ -588,7 +540,8 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
        if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
                return ret;
 
-       mutex_lock(&uprobe->copy_mutex);
+       /* TODO: move this into _register, until then we abuse this sem. */
+       down_write(&uprobe->consumer_rwsem);
        if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
                goto out;
 
@@ -612,7 +565,30 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
        set_bit(UPROBE_COPY_INSN, &uprobe->flags);
 
  out:
-       mutex_unlock(&uprobe->copy_mutex);
+       up_write(&uprobe->consumer_rwsem);
+
+       return ret;
+}
+
+static inline bool consumer_filter(struct uprobe_consumer *uc,
+                                  enum uprobe_filter_ctx ctx, struct mm_struct *mm)
+{
+       return !uc->filter || uc->filter(uc, ctx, mm);
+}
+
+static bool filter_chain(struct uprobe *uprobe,
+                        enum uprobe_filter_ctx ctx, struct mm_struct *mm)
+{
+       struct uprobe_consumer *uc;
+       bool ret = false;
+
+       down_read(&uprobe->consumer_rwsem);
+       for (uc = uprobe->consumers; uc; uc = uc->next) {
+               ret = consumer_filter(uc, ctx, mm);
+               if (ret)
+                       break;
+       }
+       up_read(&uprobe->consumer_rwsem);
 
        return ret;
 }
@@ -624,16 +600,6 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        bool first_uprobe;
        int ret;
 
-       /*
-        * If probe is being deleted, unregister thread could be done with
-        * the vma-rmap-walk through. Adding a probe now can be fatal since
-        * nobody will be able to cleanup. Also we could be from fork or
-        * mremap path, where the probe might have already been inserted.
-        * Hence behave as if probe already existed.
-        */
-       if (!uprobe->consumers)
-               return 0;
-
        ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
        if (ret)
                return ret;
@@ -658,14 +624,14 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 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 0;
-
        set_bit(MMF_RECALC_UPROBES, &mm->flags);
        return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
 
+static inline bool uprobe_is_active(struct uprobe *uprobe)
+{
+       return !RB_EMPTY_NODE(&uprobe->rb_node);
+}
 /*
  * There could be threads that have already hit the breakpoint. They
  * will recheck the current insn and restart if find_uprobe() fails.
@@ -673,12 +639,15 @@ remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vad
  */
 static void delete_uprobe(struct uprobe *uprobe)
 {
+       if (WARN_ON(!uprobe_is_active(uprobe)))
+               return;
+
        spin_lock(&uprobes_treelock);
        rb_erase(&uprobe->rb_node, &uprobes_tree);
        spin_unlock(&uprobes_treelock);
+       RB_CLEAR_NODE(&uprobe->rb_node); /* for uprobe_is_active() */
        iput(uprobe->inode);
        put_uprobe(uprobe);
-       atomic_dec(&uprobe_events);
 }
 
 struct map_info {
@@ -764,8 +733,10 @@ build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
        return curr;
 }
 
-static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
+static int
+register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 {
+       bool is_register = !!new;
        struct map_info *info;
        int err = 0;
 
@@ -794,10 +765,16 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                    vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
                        goto unlock;
 
-               if (is_register)
-                       err = install_breakpoint(uprobe, mm, vma, info->vaddr);
-               else
-                       err |= remove_breakpoint(uprobe, mm, info->vaddr);
+               if (is_register) {
+                       /* consult only the "caller", new consumer. */
+                       if (consumer_filter(new,
+                                       UPROBE_FILTER_REGISTER, mm))
+                               err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+               } else if (test_bit(MMF_HAS_UPROBES, &mm->flags)) {
+                       if (!filter_chain(uprobe,
+                                       UPROBE_FILTER_UNREGISTER, mm))
+                               err |= remove_breakpoint(uprobe, mm, info->vaddr);
+               }
 
  unlock:
                up_write(&mm->mmap_sem);
@@ -810,17 +787,23 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
        return err;
 }
 
-static int __uprobe_register(struct uprobe *uprobe)
+static int __uprobe_register(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
-       return register_for_each_vma(uprobe, true);
+       consumer_add(uprobe, uc);
+       return register_for_each_vma(uprobe, uc);
 }
 
-static void __uprobe_unregister(struct uprobe *uprobe)
+static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
-       if (!register_for_each_vma(uprobe, false))
-               delete_uprobe(uprobe);
+       int err;
+
+       if (!consumer_del(uprobe, uc))  /* WARN? */
+               return;
 
+       err = register_for_each_vma(uprobe, NULL);
        /* TODO : cant unregister? schedule a worker thread */
+       if (!uprobe->consumers && !err)
+               delete_uprobe(uprobe);
 }
 
 /*
@@ -845,31 +828,59 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        struct uprobe *uprobe;
        int ret;
 
-       if (!inode || !uc || uc->next)
-               return -EINVAL;
-
+       /* Racy, just to catch the obvious mistakes */
        if (offset > i_size_read(inode))
                return -EINVAL;
 
-       ret = 0;
-       mutex_lock(uprobes_hash(inode));
+ retry:
        uprobe = alloc_uprobe(inode, offset);
-
-       if (!uprobe) {
-               ret = -ENOMEM;
-       } else if (!consumer_add(uprobe, uc)) {
-               ret = __uprobe_register(uprobe);
-               if (ret) {
-                       uprobe->consumers = NULL;
-                       __uprobe_unregister(uprobe);
-               } else {
-                       set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
-               }
+       if (!uprobe)
+               return -ENOMEM;
+       /*
+        * We can race with uprobe_unregister()->delete_uprobe().
+        * Check uprobe_is_active() and retry if it is false.
+        */
+       down_write(&uprobe->register_rwsem);
+       ret = -EAGAIN;
+       if (likely(uprobe_is_active(uprobe))) {
+               ret = __uprobe_register(uprobe, uc);
+               if (ret)
+                       __uprobe_unregister(uprobe, uc);
        }
+       up_write(&uprobe->register_rwsem);
+       put_uprobe(uprobe);
 
-       mutex_unlock(uprobes_hash(inode));
-       if (uprobe)
-               put_uprobe(uprobe);
+       if (unlikely(ret == -EAGAIN))
+               goto retry;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(uprobe_register);
+
+/*
+ * uprobe_apply - unregister a already registered probe.
+ * @inode: the file in which the probe has to be removed.
+ * @offset: offset from the start of the file.
+ * @uc: consumer which wants to add more or remove some breakpoints
+ * @add: add or remove the breakpoints
+ */
+int uprobe_apply(struct inode *inode, loff_t offset,
+                       struct uprobe_consumer *uc, bool add)
+{
+       struct uprobe *uprobe;
+       struct uprobe_consumer *con;
+       int ret = -ENOENT;
+
+       uprobe = find_uprobe(inode, offset);
+       if (!uprobe)
+               return ret;
+
+       down_write(&uprobe->register_rwsem);
+       for (con = uprobe->consumers; con && con != uc ; con = con->next)
+               ;
+       if (con)
+               ret = register_for_each_vma(uprobe, add ? uc : NULL);
+       up_write(&uprobe->register_rwsem);
+       put_uprobe(uprobe);
 
        return ret;
 }
@@ -884,25 +895,42 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
 {
        struct uprobe *uprobe;
 
-       if (!inode || !uc)
-               return;
-
        uprobe = find_uprobe(inode, offset);
        if (!uprobe)
                return;
 
-       mutex_lock(uprobes_hash(inode));
+       down_write(&uprobe->register_rwsem);
+       __uprobe_unregister(uprobe, uc);
+       up_write(&uprobe->register_rwsem);
+       put_uprobe(uprobe);
+}
+EXPORT_SYMBOL_GPL(uprobe_unregister);
 
-       if (consumer_del(uprobe, uc)) {
-               if (!uprobe->consumers) {
-                       __uprobe_unregister(uprobe);
-                       clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
-               }
+static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
+{
+       struct vm_area_struct *vma;
+       int err = 0;
+
+       down_read(&mm->mmap_sem);
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               unsigned long vaddr;
+               loff_t offset;
+
+               if (!valid_vma(vma, false) ||
+                   vma->vm_file->f_mapping->host != uprobe->inode)
+                       continue;
+
+               offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
+               if (uprobe->offset <  offset ||
+                   uprobe->offset >= offset + vma->vm_end - vma->vm_start)
+                       continue;
+
+               vaddr = offset_to_vaddr(vma, uprobe->offset);
+               err |= remove_breakpoint(uprobe, mm, vaddr);
        }
+       up_read(&mm->mmap_sem);
 
-       mutex_unlock(uprobes_hash(inode));
-       if (uprobe)
-               put_uprobe(uprobe);
+       return err;
 }
 
 static struct rb_node *
@@ -979,7 +1007,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
        struct uprobe *uprobe, *u;
        struct inode *inode;
 
-       if (!atomic_read(&uprobe_events) || !valid_vma(vma, true))
+       if (no_uprobe_events() || !valid_vma(vma, true))
                return 0;
 
        inode = vma->vm_file->f_mapping->host;
@@ -988,9 +1016,14 @@ int uprobe_mmap(struct vm_area_struct *vma)
 
        mutex_lock(uprobes_mmap_hash(inode));
        build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list);
-
+       /*
+        * We can race with uprobe_unregister(), this uprobe can be already
+        * removed. But in this case filter_chain() must return false, all
+        * consumers have gone away.
+        */
        list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
-               if (!fatal_signal_pending(current)) {
+               if (!fatal_signal_pending(current) &&
+                   filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) {
                        unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
                        install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
                }
@@ -1025,7 +1058,7 @@ vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long e
  */
 void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
-       if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
+       if (no_uprobe_events() || !valid_vma(vma, false))
                return;
 
        if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
@@ -1042,22 +1075,14 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
 /* Slot allocation for XOL */
 static int xol_add_vma(struct xol_area *area)
 {
-       struct mm_struct *mm;
-       int ret;
-
-       area->page = alloc_page(GFP_HIGHUSER);
-       if (!area->page)
-               return -ENOMEM;
-
-       ret = -EALREADY;
-       mm = current->mm;
+       struct mm_struct *mm = current->mm;
+       int ret = -EALREADY;
 
        down_write(&mm->mmap_sem);
        if (mm->uprobes_state.xol_area)
                goto fail;
 
        ret = -ENOMEM;
-
        /* Try to map as high as possible, this is only a hint. */
        area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
        if (area->vaddr & ~PAGE_MASK) {
@@ -1073,54 +1098,53 @@ static int xol_add_vma(struct xol_area *area)
        smp_wmb();      /* pairs with get_xol_area() */
        mm->uprobes_state.xol_area = area;
        ret = 0;
-
-fail:
+ fail:
        up_write(&mm->mmap_sem);
-       if (ret)
-               __free_page(area->page);
 
        return ret;
 }
 
-static struct xol_area *get_xol_area(struct mm_struct *mm)
-{
-       struct xol_area *area;
-
-       area = mm->uprobes_state.xol_area;
-       smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
-
-       return area;
-}
-
 /*
- * xol_alloc_area - Allocate process's xol_area.
- * This area will be used for storing instructions for execution out of
- * line.
+ * get_xol_area - Allocate process's xol_area if necessary.
+ * This area will be used for storing instructions for execution out of line.
  *
  * Returns the allocated area or NULL.
  */
-static struct xol_area *xol_alloc_area(void)
+static struct xol_area *get_xol_area(void)
 {
+       struct mm_struct *mm = current->mm;
        struct xol_area *area;
 
+       area = mm->uprobes_state.xol_area;
+       if (area)
+               goto ret;
+
        area = kzalloc(sizeof(*area), GFP_KERNEL);
        if (unlikely(!area))
-               return NULL;
+               goto out;
 
        area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
-
        if (!area->bitmap)
-               goto fail;
+               goto free_area;
+
+       area->page = alloc_page(GFP_HIGHUSER);
+       if (!area->page)
+               goto free_bitmap;
 
        init_waitqueue_head(&area->wq);
        if (!xol_add_vma(area))
                return area;
 
-fail:
+       __free_page(area->page);
+ free_bitmap:
        kfree(area->bitmap);
+ free_area:
        kfree(area);
-
-       return get_xol_area(current->mm);
+ out:
+       area = mm->uprobes_state.xol_area;
+ ret:
+       smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
+       return area;
 }
 
 /*
@@ -1186,33 +1210,26 @@ static unsigned long xol_take_insn_slot(struct xol_area *area)
 }
 
 /*
- * xol_get_insn_slot - If was not allocated a slot, then
- * allocate a slot.
+ * xol_get_insn_slot - allocate a slot for xol.
  * Returns the allocated slot address or 0.
  */
-static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr)
+static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 {
        struct xol_area *area;
        unsigned long offset;
+       unsigned long xol_vaddr;
        void *vaddr;
 
-       area = get_xol_area(current->mm);
-       if (!area) {
-               area = xol_alloc_area();
-               if (!area)
-                       return 0;
-       }
-       current->utask->xol_vaddr = xol_take_insn_slot(area);
+       area = get_xol_area();
+       if (!area)
+               return 0;
 
-       /*
-        * Initialize the slot if xol_vaddr points to valid
-        * instruction slot.
-        */
-       if (unlikely(!current->utask->xol_vaddr))
+       xol_vaddr = xol_take_insn_slot(area);
+       if (unlikely(!xol_vaddr))
                return 0;
 
-       current->utask->vaddr = slot_addr;
-       offset = current->utask->xol_vaddr & ~PAGE_MASK;
+       /* Initialize the slot */
+       offset = xol_vaddr & ~PAGE_MASK;
        vaddr = kmap_atomic(area->page);
        memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES);
        kunmap_atomic(vaddr);
@@ -1222,7 +1239,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot
         */
        flush_dcache_page(area->page);
 
-       return current->utask->xol_vaddr;
+       return xol_vaddr;
 }
 
 /*
@@ -1240,8 +1257,7 @@ static void xol_free_insn_slot(struct task_struct *tsk)
                return;
 
        slot_addr = tsk->utask->xol_vaddr;
-
-       if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr)))
+       if (unlikely(!slot_addr))
                return;
 
        area = tsk->mm->uprobes_state.xol_area;
@@ -1303,33 +1319,48 @@ void uprobe_copy_process(struct task_struct *t)
 }
 
 /*
- * Allocate a uprobe_task object for the task.
- * Called when the thread hits a breakpoint for the first time.
+ * Allocate a uprobe_task object for the task if if necessary.
+ * Called when the thread hits a breakpoint.
  *
  * Returns:
  * - pointer to new uprobe_task on success
  * - NULL otherwise
  */
-static struct uprobe_task *add_utask(void)
+static struct uprobe_task *get_utask(void)
 {
-       struct uprobe_task *utask;
-
-       utask = kzalloc(sizeof *utask, GFP_KERNEL);
-       if (unlikely(!utask))
-               return NULL;
-
-       current->utask = utask;
-       return utask;
+       if (!current->utask)
+               current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
+       return current->utask;
 }
 
 /* Prepare to single-step probed instruction out of line. */
 static int
-pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr)
+pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 {
-       if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs))
-               return 0;
+       struct uprobe_task *utask;
+       unsigned long xol_vaddr;
+       int err;
+
+       utask = get_utask();
+       if (!utask)
+               return -ENOMEM;
+
+       xol_vaddr = xol_get_insn_slot(uprobe);
+       if (!xol_vaddr)
+               return -ENOMEM;
+
+       utask->xol_vaddr = xol_vaddr;
+       utask->vaddr = bp_vaddr;
+
+       err = arch_uprobe_pre_xol(&uprobe->arch, regs);
+       if (unlikely(err)) {
+               xol_free_insn_slot(current);
+               return err;
+       }
 
-       return -EFAULT;
+       utask->active_uprobe = uprobe;
+       utask->state = UTASK_SSTEP;
+       return 0;
 }
 
 /*
@@ -1391,6 +1422,7 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
                 * This is not strictly accurate, we can race with
                 * uprobe_unregister() and see the already removed
                 * uprobe if delete_uprobe() was not yet called.
+                * Or this uprobe can be filtered out.
                 */
                if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end))
                        return;
@@ -1452,13 +1484,33 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
        return uprobe;
 }
 
+static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
+{
+       struct uprobe_consumer *uc;
+       int remove = UPROBE_HANDLER_REMOVE;
+
+       down_read(&uprobe->register_rwsem);
+       for (uc = uprobe->consumers; uc; uc = uc->next) {
+               int rc = uc->handler(uc, regs);
+
+               WARN(rc & ~UPROBE_HANDLER_MASK,
+                       "bad rc=0x%x from %pf()\n", rc, uc->handler);
+               remove &= rc;
+       }
+
+       if (remove && uprobe->consumers) {
+               WARN_ON(!uprobe_is_active(uprobe));
+               unapply_uprobe(uprobe, current->mm);
+       }
+       up_read(&uprobe->register_rwsem);
+}
+
 /*
  * Run handler and ask thread to singlestep.
  * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
  */
 static void handle_swbp(struct pt_regs *regs)
 {
-       struct uprobe_task *utask;
        struct uprobe *uprobe;
        unsigned long bp_vaddr;
        int uninitialized_var(is_swbp);
@@ -1483,6 +1535,10 @@ static void handle_swbp(struct pt_regs *regs)
                }
                return;
        }
+
+       /* change it in advance for ->handler() and restart */
+       instruction_pointer_set(regs, bp_vaddr);
+
        /*
         * TODO: move copy_insn/etc into _register and remove this hack.
         * After we hit the bp, _unregister + _register can install the
@@ -1490,32 +1546,16 @@ static void handle_swbp(struct pt_regs *regs)
         */
        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 restart;
-       }
+               goto out;
 
        handler_chain(uprobe, regs);
        if (can_skip_sstep(uprobe, regs))
                goto out;
 
-       if (!pre_ssout(uprobe, regs, bp_vaddr)) {
-               utask->active_uprobe = uprobe;
-               utask->state = UTASK_SSTEP;
+       if (!pre_ssout(uprobe, regs, bp_vaddr))
                return;
-       }
 
-restart:
-       /*
-        * cannot singlestep; cannot skip instruction;
-        * re-execute the instruction.
-        */
-       instruction_pointer_set(regs, bp_vaddr);
+       /* can_skip_sstep() succeeded, or restart if can't singlestep */
 out:
        put_uprobe(uprobe);
 }
@@ -1609,10 +1649,8 @@ static int __init init_uprobes(void)
 {
        int i;
 
-       for (i = 0; i < UPROBES_HASH_SZ; i++) {
-               mutex_init(&uprobes_mutex[i]);
+       for (i = 0; i < UPROBES_HASH_SZ; i++)
                mutex_init(&uprobes_mmap_mutex[i]);
-       }
 
        if (percpu_init_rwsem(&dup_mmap_sem))
                return -ENOMEM;
index b4df21937216e1704670d89e8ef8fe8aa9aee810..7dd20408707ce5845bf5fd63185b0980e1c9827a 100644 (file)
@@ -85,6 +85,7 @@ static void __exit_signal(struct task_struct *tsk)
        bool group_dead = thread_group_leader(tsk);
        struct sighand_struct *sighand;
        struct tty_struct *uninitialized_var(tty);
+       cputime_t utime, stime;
 
        sighand = rcu_dereference_check(tsk->sighand,
                                        lockdep_tasklist_lock_is_held());
@@ -123,9 +124,10 @@ static void __exit_signal(struct task_struct *tsk)
                 * We won't ever get here for the group leader, since it
                 * will have been the last reference on the signal_struct.
                 */
-               sig->utime += tsk->utime;
-               sig->stime += tsk->stime;
-               sig->gtime += tsk->gtime;
+               task_cputime(tsk, &utime, &stime);
+               sig->utime += utime;
+               sig->stime += stime;
+               sig->gtime += task_gtime(tsk);
                sig->min_flt += tsk->min_flt;
                sig->maj_flt += tsk->maj_flt;
                sig->nvcsw += tsk->nvcsw;
@@ -1092,7 +1094,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                sig = p->signal;
                psig->cutime += tgutime + sig->cutime;
                psig->cstime += tgstime + sig->cstime;
-               psig->cgtime += p->gtime + sig->gtime + sig->cgtime;
+               psig->cgtime += task_gtime(p) + sig->gtime + sig->cgtime;
                psig->cmin_flt +=
                        p->min_flt + sig->min_flt + sig->cmin_flt;
                psig->cmaj_flt +=
index 85f6d536608d282c97988701951d82afb20d5ba7..4133876d8cd23838037bb62540197f2308578685 100644 (file)
@@ -1166,6 +1166,14 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                                current->signal->flags & SIGNAL_UNKILLABLE)
                return ERR_PTR(-EINVAL);
 
+       /*
+        * If the new process will be in a different pid namespace
+        * don't allow the creation of threads.
+        */
+       if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) &&
+           (task_active_pid_ns(current) != current->nsproxy->pid_ns))
+               return ERR_PTR(-EINVAL);
+
        retval = security_task_create(clone_flags);
        if (retval)
                goto fork_out;
@@ -1225,6 +1233,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
        p->prev_cputime.utime = p->prev_cputime.stime = 0;
 #endif
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+       seqlock_init(&p->vtime_seqlock);
+       p->vtime_snap = 0;
+       p->vtime_snap_whence = VTIME_SLEEPING;
+#endif
+
 #if defined(SPLIT_RSS_COUNTING)
        memset(&p->rss_stat, 0, sizeof(p->rss_stat));
 #endif
@@ -1613,7 +1627,6 @@ long do_fork(unsigned long clone_flags,
        return nr;
 }
 
-#ifdef CONFIG_GENERIC_KERNEL_THREAD
 /*
  * Create a kernel thread.
  */
@@ -1622,7 +1635,6 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
        return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
                (unsigned long)arg, NULL, NULL);
 }
-#endif
 
 #ifdef __ARCH_WANT_SYS_FORK
 SYSCALL_DEFINE0(fork)
@@ -1662,8 +1674,10 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                 int, tls_val)
 #endif
 {
-       return do_fork(clone_flags, newsp, 0,
-               parent_tidptr, child_tidptr);
+       long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
+       asmlinkage_protect(5, ret, clone_flags, newsp,
+                       parent_tidptr, child_tidptr, tls_val);
+       return ret;
 }
 #endif
 
index 19eb089ca003a7f7a09347eb393d5241cc93342e..9618b6e9fb367b2881ca2ccd28d88f46858e346d 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
 #include <linux/ptrace.h>
+#include <linux/sched/rt.h>
 
 #include <asm/futex.h>
 
index 6db7a5ed52b58727d33293853053c0fee1d049fe..cc47812d3feb0c86cbcf8f03e6ee81340ef7c57c 100644 (file)
@@ -44,6 +44,8 @@
 #include <linux/err.h>
 #include <linux/debugobjects.h>
 #include <linux/sched.h>
+#include <linux/sched/sysctl.h>
+#include <linux/sched/rt.h>
 #include <linux/timer.h>
 
 #include <asm/uaccess.h>
@@ -640,21 +642,9 @@ static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
  * and expiry check is done in the hrtimer_interrupt or in the softirq.
  */
 static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
-                                           struct hrtimer_clock_base *base,
-                                           int wakeup)
+                                           struct hrtimer_clock_base *base)
 {
-       if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
-               if (wakeup) {
-                       raw_spin_unlock(&base->cpu_base->lock);
-                       raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-                       raw_spin_lock(&base->cpu_base->lock);
-               } else
-                       __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-
-               return 1;
-       }
-
-       return 0;
+       return base->cpu_base->hres_active && hrtimer_reprogram(timer, base);
 }
 
 static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
@@ -735,8 +725,7 @@ static inline int hrtimer_switch_to_hres(void) { return 0; }
 static inline void
 hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
 static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
-                                           struct hrtimer_clock_base *base,
-                                           int wakeup)
+                                           struct hrtimer_clock_base *base)
 {
        return 0;
 }
@@ -995,8 +984,21 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
         *
         * XXX send_remote_softirq() ?
         */
-       if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
-               hrtimer_enqueue_reprogram(timer, new_base, wakeup);
+       if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)
+               && hrtimer_enqueue_reprogram(timer, new_base)) {
+               if (wakeup) {
+                       /*
+                        * We need to drop cpu_base->lock to avoid a
+                        * lock ordering issue vs. rq->lock.
+                        */
+                       raw_spin_unlock(&new_base->cpu_base->lock);
+                       raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+                       local_irq_restore(flags);
+                       return ret;
+               } else {
+                       __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+               }
+       }
 
        unlock_hrtimer_base(timer, &flags);
 
index 3aca9f29d30ef4c5089ad97740588a31462fd22d..cbd97ce0b0007c0daaa15255e3417bda9140b688 100644 (file)
@@ -90,26 +90,40 @@ int irq_set_handler_data(unsigned int irq, void *data)
 EXPORT_SYMBOL(irq_set_handler_data);
 
 /**
- *     irq_set_msi_desc - set MSI descriptor data for an irq
- *     @irq:   Interrupt number
- *     @entry: Pointer to MSI descriptor data
+ *     irq_set_msi_desc_off - set MSI descriptor data for an irq at offset
+ *     @irq_base:      Interrupt number base
+ *     @irq_offset:    Interrupt number offset
+ *     @entry:         Pointer to MSI descriptor data
  *
- *     Set the MSI descriptor entry for an irq
+ *     Set the MSI descriptor entry for an irq at offset
  */
-int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
+int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
+                        struct msi_desc *entry)
 {
        unsigned long flags;
-       struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
+       struct irq_desc *desc = irq_get_desc_lock(irq_base + irq_offset, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
        if (!desc)
                return -EINVAL;
        desc->irq_data.msi_desc = entry;
-       if (entry)
-               entry->irq = irq;
+       if (entry && !irq_offset)
+               entry->irq = irq_base;
        irq_put_desc_unlock(desc, flags);
        return 0;
 }
 
+/**
+ *     irq_set_msi_desc - set MSI descriptor data for an irq
+ *     @irq:   Interrupt number
+ *     @entry: Pointer to MSI descriptor data
+ *
+ *     Set the MSI descriptor entry for an irq
+ */
+int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
+{
+       return irq_set_msi_desc_off(irq, 0, entry);
+}
+
 /**
  *     irq_set_chip_data - set irq chip data for an irq
  *     @irq:   Interrupt number
index e49a288fa479036ebb25b907787b34568d421964..fa17855ca65a235bd5c1f9a7daa042b57722b924 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/task_work.h>
 
 #include "internals.h"
@@ -1524,6 +1525,7 @@ void enable_percpu_irq(unsigned int irq, unsigned int type)
 out:
        irq_put_desc_unlock(desc, flags);
 }
+EXPORT_SYMBOL_GPL(enable_percpu_irq);
 
 void disable_percpu_irq(unsigned int irq)
 {
@@ -1537,6 +1539,7 @@ void disable_percpu_irq(unsigned int irq)
        irq_percpu_disable(desc, cpu);
        irq_put_desc_unlock(desc, flags);
 }
+EXPORT_SYMBOL_GPL(disable_percpu_irq);
 
 /*
  * Internal function to unregister a percpu irqaction.
index 611cd6003c453951d82e12d6d03a044f7f285275..7b5f012bde9d73ff246652fe48d49e5b1aebc12c 100644 (file)
@@ -80,13 +80,11 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
 
        /*
         * All handlers must agree on IRQF_SHARED, so we test just the
-        * first. Check for action->next as well.
+        * first.
         */
        action = desc->action;
        if (!action || !(action->flags & IRQF_SHARED) ||
-           (action->flags & __IRQF_TIMER) ||
-           (action->handler(irq, action->dev_id) == IRQ_HANDLED) ||
-           !action->next)
+           (action->flags & __IRQF_TIMER))
                goto out;
 
        /* Already running on another processor */
@@ -104,6 +102,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
        do {
                if (handle_irq_event(desc) == IRQ_HANDLED)
                        ret = IRQ_HANDLED;
+               /* Make sure that there is still a valid action */
                action = desc->action;
        } while ((desc->istate & IRQS_PENDING) && action);
        desc->istate &= ~IRQS_POLL_INPROGRESS;
index 1588e3b2871b9e28a68316f91ca418d44a75cba2..55fcce6065cf6bc3213829fd8188cae90b61b778 100644 (file)
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 #include <asm/processor.h>
 
-/*
- * An entry can be in one of four states:
- *
- * free             NULL, 0 -> {claimed}       : free to be used
- * claimed   NULL, 3 -> {pending}       : claimed to be enqueued
- * pending   next, 3 -> {busy}          : queued, pending callback
- * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
- */
-
-#define IRQ_WORK_PENDING       1UL
-#define IRQ_WORK_BUSY          2UL
-#define IRQ_WORK_FLAGS         3UL
 
 static DEFINE_PER_CPU(struct llist_head, irq_work_list);
+static DEFINE_PER_CPU(int, irq_work_raised);
 
 /*
  * Claim the entry so that no one else will poke at it.
  */
 static bool irq_work_claim(struct irq_work *work)
 {
-       unsigned long flags, nflags;
+       unsigned long flags, oflags, nflags;
 
+       /*
+        * Start with our best wish as a premise but only trust any
+        * flag value after cmpxchg() result.
+        */
+       flags = work->flags & ~IRQ_WORK_PENDING;
        for (;;) {
-               flags = work->flags;
-               if (flags & IRQ_WORK_PENDING)
-                       return false;
                nflags = flags | IRQ_WORK_FLAGS;
-               if (cmpxchg(&work->flags, flags, nflags) == flags)
+               oflags = cmpxchg(&work->flags, flags, nflags);
+               if (oflags == flags)
                        break;
+               if (oflags & IRQ_WORK_PENDING)
+                       return false;
+               flags = oflags;
                cpu_relax();
        }
 
@@ -57,57 +56,69 @@ void __weak arch_irq_work_raise(void)
 }
 
 /*
- * Queue the entry and raise the IPI if needed.
+ * Enqueue the irq_work @entry unless it's already pending
+ * somewhere.
+ *
+ * Can be re-enqueued while the callback is still in progress.
  */
-static void __irq_work_queue(struct irq_work *work)
+void irq_work_queue(struct irq_work *work)
 {
-       bool empty;
+       /* Only queue if not already pending */
+       if (!irq_work_claim(work))
+               return;
 
+       /* Queue the entry and raise the IPI if needed. */
        preempt_disable();
 
-       empty = llist_add(&work->llnode, &__get_cpu_var(irq_work_list));
-       /* The list was empty, raise self-interrupt to start processing. */
-       if (empty)
-               arch_irq_work_raise();
+       llist_add(&work->llnode, &__get_cpu_var(irq_work_list));
+
+       /*
+        * If the work is not "lazy" or the tick is stopped, raise the irq
+        * work interrupt (if supported by the arch), otherwise, just wait
+        * for the next tick.
+        */
+       if (!(work->flags & IRQ_WORK_LAZY) || tick_nohz_tick_stopped()) {
+               if (!this_cpu_cmpxchg(irq_work_raised, 0, 1))
+                       arch_irq_work_raise();
+       }
 
        preempt_enable();
 }
+EXPORT_SYMBOL_GPL(irq_work_queue);
 
-/*
- * Enqueue the irq_work @entry, returns true on success, failure when the
- * @entry was already enqueued by someone else.
- *
- * Can be re-enqueued while the callback is still in progress.
- */
-bool irq_work_queue(struct irq_work *work)
+bool irq_work_needs_cpu(void)
 {
-       if (!irq_work_claim(work)) {
-               /*
-                * Already enqueued, can't do!
-                */
+       struct llist_head *this_list;
+
+       this_list = &__get_cpu_var(irq_work_list);
+       if (llist_empty(this_list))
                return false;
-       }
 
-       __irq_work_queue(work);
+       /* All work should have been flushed before going offline */
+       WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
+
        return true;
 }
-EXPORT_SYMBOL_GPL(irq_work_queue);
 
-/*
- * Run the irq_work entries on this cpu. Requires to be ran from hardirq
- * context with local IRQs disabled.
- */
-void irq_work_run(void)
+static void __irq_work_run(void)
 {
+       unsigned long flags;
        struct irq_work *work;
        struct llist_head *this_list;
        struct llist_node *llnode;
 
+
+       /*
+        * Reset the "raised" state right before we check the list because
+        * an NMI may enqueue after we find the list empty from the runner.
+        */
+       __this_cpu_write(irq_work_raised, 0);
+       barrier();
+
        this_list = &__get_cpu_var(irq_work_list);
        if (llist_empty(this_list))
                return;
 
-       BUG_ON(!in_irq());
        BUG_ON(!irqs_disabled());
 
        llnode = llist_del_all(this_list);
@@ -119,16 +130,31 @@ void irq_work_run(void)
                /*
                 * Clear the PENDING bit, after this point the @work
                 * can be re-used.
+                * Make it immediately visible so that other CPUs trying
+                * to claim that work don't rely on us to handle their data
+                * while we are in the middle of the func.
                 */
-               work->flags = IRQ_WORK_BUSY;
+               flags = work->flags & ~IRQ_WORK_PENDING;
+               xchg(&work->flags, flags);
+
                work->func(work);
                /*
                 * Clear the BUSY bit and return to the free state if
                 * no-one else claimed it meanwhile.
                 */
-               (void)cmpxchg(&work->flags, IRQ_WORK_BUSY, 0);
+               (void)cmpxchg(&work->flags, flags, flags & ~IRQ_WORK_BUSY);
        }
 }
+
+/*
+ * Run the irq_work entries on this cpu. Requires to be ran from hardirq
+ * context with local IRQs disabled.
+ */
+void irq_work_run(void)
+{
+       BUG_ON(!in_irq());
+       __irq_work_run();
+}
 EXPORT_SYMBOL_GPL(irq_work_run);
 
 /*
@@ -143,3 +169,35 @@ void irq_work_sync(struct irq_work *work)
                cpu_relax();
 }
 EXPORT_SYMBOL_GPL(irq_work_sync);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int irq_work_cpu_notify(struct notifier_block *self,
+                              unsigned long action, void *hcpu)
+{
+       long cpu = (long)hcpu;
+
+       switch (action) {
+       case CPU_DYING:
+               /* Called from stop_machine */
+               if (WARN_ON_ONCE(cpu != smp_processor_id()))
+                       break;
+               __irq_work_run();
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block cpu_notify;
+
+static __init int irq_work_init_cpu_notifier(void)
+{
+       cpu_notify.notifier_call = irq_work_cpu_notify;
+       cpu_notify.priority = 0;
+       register_cpu_notifier(&cpu_notify);
+       return 0;
+}
+device_initcall(irq_work_init_cpu_notifier);
+
+#endif /* CONFIG_HOTPLUG_CPU */
index 30b7b225306c6d425179cfcdf2beb249376a6cac..e30ac0fe61c3ded5533cb4db8e95b2d41dcf2ac8 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/string.h>
 #include <linux/random.h>
 #include <linux/module.h>
+#include <linux/ptrace.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/cache.h>
index 1c317e386831869a3c4ff17a675a06b3b985c06d..0023a87e8de69357b043ab58c072417200433a29 100644 (file)
@@ -219,9 +219,9 @@ static int ____call_usermodehelper(void *data)
 
        commit_creds(new);
 
-       retval = kernel_execve(sub_info->path,
-                              (const char *const *)sub_info->argv,
-                              (const char *const *)sub_info->envp);
+       retval = do_execve(sub_info->path,
+                          (const char __user *const __user *)sub_info->argv,
+                          (const char __user *const __user *)sub_info->envp);
        if (!retval)
                return 0;
 
index 098f396aa40984d0b49f246b45dd059b88e9acdf..f423c3ef4a82938f4e81165cb70378787b6fbb02 100644 (file)
@@ -919,7 +919,7 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p)
 }
 #endif /* CONFIG_OPTPROBES */
 
-#ifdef KPROBES_CAN_USE_FTRACE
+#ifdef CONFIG_KPROBES_ON_FTRACE
 static struct ftrace_ops kprobe_ftrace_ops __read_mostly = {
        .func = kprobe_ftrace_handler,
        .flags = FTRACE_OPS_FL_SAVE_REGS,
@@ -964,7 +964,7 @@ static void __kprobes disarm_kprobe_ftrace(struct kprobe *p)
                           (unsigned long)p->addr, 1, 0);
        WARN(ret < 0, "Failed to disarm kprobe-ftrace at %p (%d)\n", p->addr, ret);
 }
-#else  /* !KPROBES_CAN_USE_FTRACE */
+#else  /* !CONFIG_KPROBES_ON_FTRACE */
 #define prepare_kprobe(p)      arch_prepare_kprobe(p)
 #define arm_kprobe_ftrace(p)   do {} while (0)
 #define disarm_kprobe_ftrace(p)        do {} while (0)
@@ -1414,12 +1414,12 @@ static __kprobes int check_kprobe_address_safe(struct kprobe *p,
         */
        ftrace_addr = ftrace_location((unsigned long)p->addr);
        if (ftrace_addr) {
-#ifdef KPROBES_CAN_USE_FTRACE
+#ifdef CONFIG_KPROBES_ON_FTRACE
                /* Given address is not on the instruction boundary */
                if ((unsigned long)p->addr != ftrace_addr)
                        return -EILSEQ;
                p->flags |= KPROBE_FLAG_FTRACE;
-#else  /* !KPROBES_CAN_USE_FTRACE */
+#else  /* !CONFIG_KPROBES_ON_FTRACE */
                return -EINVAL;
 #endif
        }
index 045504fffbb2657bd81f9c1165941edc19a8dce1..2b6e69909c394440b015e771ff0f3f4eab1a1a28 100644 (file)
@@ -34,18 +34,15 @@ static __init int module_verify_init(void)
 {
        pr_notice("Initialise module verification\n");
 
-       modsign_keyring = key_alloc(&key_type_keyring, ".module_sign",
-                                   KUIDT_INIT(0), KGIDT_INIT(0),
-                                   current_cred(),
-                                   (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                                   KEY_USR_VIEW | KEY_USR_READ,
-                                   KEY_ALLOC_NOT_IN_QUOTA);
+       modsign_keyring = keyring_alloc(".module_sign",
+                                       KUIDT_INIT(0), KGIDT_INIT(0),
+                                       current_cred(),
+                                       ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                                        KEY_USR_VIEW | KEY_USR_READ),
+                                       KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(modsign_keyring))
                panic("Can't allocate module signing keyring\n");
 
-       if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0)
-               panic("Can't instantiate module signing keyring\n");
-
        return 0;
 }
 
index 250092c1d57d6cf582ef801f70a10969e19abab2..eab08274ec9bf9a1e5b8c83de0f925da0aeaf761 100644 (file)
@@ -188,6 +188,7 @@ struct load_info {
    ongoing or failed initialization etc. */
 static inline int strong_try_module_get(struct module *mod)
 {
+       BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
        if (mod && mod->state == MODULE_STATE_COMING)
                return -EBUSY;
        if (try_module_get(mod))
@@ -343,6 +344,9 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
 #endif
                };
 
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
+
                if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
                        return true;
        }
@@ -450,16 +454,24 @@ const struct kernel_symbol *find_symbol(const char *name,
 EXPORT_SYMBOL_GPL(find_symbol);
 
 /* Search for module by name: must hold module_mutex. */
-struct module *find_module(const char *name)
+static struct module *find_module_all(const char *name,
+                                     bool even_unformed)
 {
        struct module *mod;
 
        list_for_each_entry(mod, &modules, list) {
+               if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (strcmp(mod->name, name) == 0)
                        return mod;
        }
        return NULL;
 }
+
+struct module *find_module(const char *name)
+{
+       return find_module_all(name, false);
+}
 EXPORT_SYMBOL_GPL(find_module);
 
 #ifdef CONFIG_SMP
@@ -525,6 +537,8 @@ bool is_module_percpu_address(unsigned long addr)
        preempt_disable();
 
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (!mod->percpu_size)
                        continue;
                for_each_possible_cpu(cpu) {
@@ -1048,6 +1062,8 @@ static ssize_t show_initstate(struct module_attribute *mattr,
        case MODULE_STATE_GOING:
                state = "going";
                break;
+       default:
+               BUG();
        }
        return sprintf(buffer, "%s\n", state);
 }
@@ -1786,6 +1802,8 @@ void set_all_modules_text_rw(void)
 
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if ((mod->module_core) && (mod->core_text_size)) {
                        set_page_attributes(mod->module_core,
                                                mod->module_core + mod->core_text_size,
@@ -1807,6 +1825,8 @@ void set_all_modules_text_ro(void)
 
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if ((mod->module_core) && (mod->core_text_size)) {
                        set_page_attributes(mod->module_core,
                                                mod->module_core + mod->core_text_size,
@@ -2527,6 +2547,13 @@ static int copy_module_from_fd(int fd, struct load_info *info)
                err = -EFBIG;
                goto out;
        }
+
+       /* Don't hand 0 to vmalloc, it whines. */
+       if (stat.size == 0) {
+               err = -EINVAL;
+               goto out;
+       }
+
        info->hdr = vmalloc(stat.size);
        if (!info->hdr) {
                err = -ENOMEM;
@@ -2990,8 +3017,9 @@ static bool finished_loading(const char *name)
        bool ret;
 
        mutex_lock(&module_mutex);
-       mod = find_module(name);
-       ret = !mod || mod->state != MODULE_STATE_COMING;
+       mod = find_module_all(name, true);
+       ret = !mod || mod->state == MODULE_STATE_LIVE
+               || mod->state == MODULE_STATE_GOING;
        mutex_unlock(&module_mutex);
 
        return ret;
@@ -3013,6 +3041,12 @@ static int do_init_module(struct module *mod)
 {
        int ret = 0;
 
+       /*
+        * We want to find out whether @mod uses async during init.  Clear
+        * PF_USED_ASYNC.  async_schedule*() will set it.
+        */
+       current->flags &= ~PF_USED_ASYNC;
+
        blocking_notifier_call_chain(&module_notify_list,
                        MODULE_STATE_COMING, mod);
 
@@ -3058,8 +3092,25 @@ static int do_init_module(struct module *mod)
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_LIVE, mod);
 
-       /* We need to finish all async code before the module init sequence is done */
-       async_synchronize_full();
+       /*
+        * We need to finish all async code before the module init sequence
+        * is done.  This has potential to deadlock.  For example, a newly
+        * detected block device can trigger request_module() of the
+        * default iosched from async probing task.  Once userland helper
+        * reaches here, async_synchronize_full() will wait on the async
+        * task waiting on request_module() and deadlock.
+        *
+        * This deadlock is avoided by perfomring async_synchronize_full()
+        * iff module init queued any async jobs.  This isn't a full
+        * solution as it will deadlock the same if module loading from
+        * async jobs nests more than once; however, due to the various
+        * constraints, this hack seems to be the best option for now.
+        * Please refer to the following thread for details.
+        *
+        * http://thread.gmane.org/gmane.linux.kernel/1420814
+        */
+       if (current->flags & PF_USED_ASYNC)
+               async_synchronize_full();
 
        mutex_lock(&module_mutex);
        /* Drop initial reference. */
@@ -3113,6 +3164,32 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto free_copy;
        }
 
+       /*
+        * We try to place it in the list now to make sure it's unique
+        * before we dedicate too many resources.  In particular,
+        * temporary percpu memory exhaustion.
+        */
+       mod->state = MODULE_STATE_UNFORMED;
+again:
+       mutex_lock(&module_mutex);
+       if ((old = find_module_all(mod->name, true)) != NULL) {
+               if (old->state == MODULE_STATE_COMING
+                   || old->state == MODULE_STATE_UNFORMED) {
+                       /* Wait in case it fails to load. */
+                       mutex_unlock(&module_mutex);
+                       err = wait_event_interruptible(module_wq,
+                                              finished_loading(mod->name));
+                       if (err)
+                               goto free_module;
+                       goto again;
+               }
+               err = -EEXIST;
+               mutex_unlock(&module_mutex);
+               goto free_module;
+       }
+       list_add_rcu(&mod->list, &modules);
+       mutex_unlock(&module_mutex);
+
 #ifdef CONFIG_MODULE_SIG
        mod->sig_ok = info->sig_ok;
        if (!mod->sig_ok)
@@ -3122,7 +3199,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        /* Now module is in final location, initialize linked lists, etc. */
        err = module_unload_init(mod);
        if (err)
-               goto free_module;
+               goto unlink_mod;
 
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
@@ -3157,54 +3234,33 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto free_arch_cleanup;
        }
 
-       /* Mark state as coming so strong_try_module_get() ignores us. */
-       mod->state = MODULE_STATE_COMING;
-
-       /* Now sew it into the lists so we can get lockdep and oops
-        * info during argument parsing.  No one should access us, since
-        * strong_try_module_get() will fail.
-        * lockdep/oops can run asynchronous, so use the RCU list insertion
-        * function to insert in a way safe to concurrent readers.
-        * The mutex protects against concurrent writers.
-        */
-again:
-       mutex_lock(&module_mutex);
-       if ((old = find_module(mod->name)) != NULL) {
-               if (old->state == MODULE_STATE_COMING) {
-                       /* Wait in case it fails to load. */
-                       mutex_unlock(&module_mutex);
-                       err = wait_event_interruptible(module_wq,
-                                              finished_loading(mod->name));
-                       if (err)
-                               goto free_arch_cleanup;
-                       goto again;
-               }
-               err = -EEXIST;
-               goto unlock;
-       }
-
-       /* This has to be done once we're sure module name is unique. */
        dynamic_debug_setup(info->debug, info->num_debug);
 
-       /* Find duplicate symbols */
+       mutex_lock(&module_mutex);
+       /* Find duplicate symbols (must be called under lock). */
        err = verify_export_symbols(mod);
        if (err < 0)
-               goto ddebug;
+               goto ddebug_cleanup;
 
+       /* This relies on module_mutex for list integrity. */
        module_bug_finalize(info->hdr, info->sechdrs, mod);
-       list_add_rcu(&mod->list, &modules);
+
+       /* Mark state as coming so strong_try_module_get() ignores us,
+        * but kallsyms etc. can see us. */
+       mod->state = MODULE_STATE_COMING;
+
        mutex_unlock(&module_mutex);
 
        /* Module is ready to execute: parsing args may do that. */
        err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
                         -32768, 32767, &ddebug_dyndbg_module_param_cb);
        if (err < 0)
-               goto unlink;
+               goto bug_cleanup;
 
        /* Link in to syfs. */
        err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
-               goto unlink;
+               goto bug_cleanup;
 
        /* Get rid of temporary copy. */
        free_copy(info);
@@ -3214,16 +3270,13 @@ again:
 
        return do_init_module(mod);
 
- unlink:
+ bug_cleanup:
+       /* module_bug_cleanup needs module_mutex protection */
        mutex_lock(&module_mutex);
-       /* Unlink carefully: kallsyms could be walking list. */
-       list_del_rcu(&mod->list);
        module_bug_cleanup(mod);
-       wake_up_all(&module_wq);
- ddebug:
-       dynamic_debug_remove(info->debug);
- unlock:
+ ddebug_cleanup:
        mutex_unlock(&module_mutex);
+       dynamic_debug_remove(info->debug);
        synchronize_sched();
        kfree(mod->args);
  free_arch_cleanup:
@@ -3232,6 +3285,12 @@ again:
        free_modinfo(mod);
  free_unload:
        module_unload_free(mod);
+ unlink_mod:
+       mutex_lock(&module_mutex);
+       /* Unlink carefully: kallsyms could be walking list. */
+       list_del_rcu(&mod->list);
+       wake_up_all(&module_wq);
+       mutex_unlock(&module_mutex);
  free_module:
        module_deallocate(mod, info);
  free_copy:
@@ -3354,6 +3413,8 @@ const char *module_address_lookup(unsigned long addr,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        if (modname)
@@ -3377,6 +3438,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        const char *sym;
@@ -3401,6 +3464,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        const char *sym;
@@ -3428,6 +3493,8 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (symnum < mod->num_symtab) {
                        *value = mod->symtab[symnum].st_value;
                        *type = mod->symtab[symnum].st_info;
@@ -3470,9 +3537,12 @@ unsigned long module_kallsyms_lookup_name(const char *name)
                        ret = mod_find_symname(mod, colon+1);
                *colon = ':';
        } else {
-               list_for_each_entry_rcu(mod, &modules, list)
+               list_for_each_entry_rcu(mod, &modules, list) {
+                       if (mod->state == MODULE_STATE_UNFORMED)
+                               continue;
                        if ((ret = mod_find_symname(mod, name)) != 0)
                                break;
+               }
        }
        preempt_enable();
        return ret;
@@ -3487,6 +3557,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
        int ret;
 
        list_for_each_entry(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                for (i = 0; i < mod->num_symtab; i++) {
                        ret = fn(data, mod->strtab + mod->symtab[i].st_name,
                                 mod, mod->symtab[i].st_value);
@@ -3502,6 +3574,7 @@ static char *module_flags(struct module *mod, char *buf)
 {
        int bx = 0;
 
+       BUG_ON(mod->state == MODULE_STATE_UNFORMED);
        if (mod->taints ||
            mod->state == MODULE_STATE_GOING ||
            mod->state == MODULE_STATE_COMING) {
@@ -3543,6 +3616,10 @@ static int m_show(struct seq_file *m, void *p)
        struct module *mod = list_entry(p, struct module, list);
        char buf[8];
 
+       /* We always ignore unformed modules. */
+       if (mod->state == MODULE_STATE_UNFORMED)
+               return 0;
+
        seq_printf(m, "%s %u",
                   mod->name, mod->init_size + mod->core_size);
        print_unload_info(m, mod);
@@ -3603,6 +3680,8 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (mod->num_exentries == 0)
                        continue;
 
@@ -3651,10 +3730,13 @@ struct module *__module_address(unsigned long addr)
        if (addr < module_addr_min || addr > module_addr_max)
                return NULL;
 
-       list_for_each_entry_rcu(mod, &modules, list)
+       list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_core(addr, mod)
                    || within_module_init(addr, mod))
                        return mod;
+       }
        return NULL;
 }
 EXPORT_SYMBOL_GPL(__module_address);
@@ -3707,8 +3789,11 @@ void print_modules(void)
        printk(KERN_DEFAULT "Modules linked in:");
        /* Most callers should already have preempt disabled, but make sure */
        preempt_disable();
-       list_for_each_entry_rcu(mod, &modules, list)
+       list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                printk(" %s%s", mod->name, module_flags(mod, buf));
+       }
        preempt_enable();
        if (last_unloaded_module[0])
                printk(" [last unloaded: %s]", last_unloaded_module);
index a307cc9c9526e7c5a5514cfb0988d804e6300f7c..52f23011b6e0f1001eeaa01a6d2f821206cf588b 100644 (file)
@@ -19,6 +19,7 @@
  */
 #include <linux/mutex.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
index 36aa02ff17d6c9cf67dcf39b0434898c700915ae..f2c6a68250989d4223b788bd368b6dd7a80e4e7d 100644 (file)
@@ -270,7 +270,6 @@ void free_pid(struct pid *pid)
                        wake_up_process(ns->child_reaper);
                        break;
                case 0:
-                       ns->nr_hashed = -1;
                        schedule_work(&ns->proc_work);
                        break;
                }
@@ -319,7 +318,7 @@ struct pid *alloc_pid(struct pid_namespace *ns)
 
        upid = pid->numbers + ns->level;
        spin_lock_irq(&pidmap_lock);
-       if (ns->nr_hashed < 0)
+       if (!(ns->nr_hashed & PIDNS_HASH_ADDING))
                goto out_unlock;
        for ( ; upid >= pid->numbers; --upid) {
                hlist_add_head_rcu(&upid->pid_chain,
@@ -332,7 +331,7 @@ out:
        return pid;
 
 out_unlock:
-       spin_unlock(&pidmap_lock);
+       spin_unlock_irq(&pidmap_lock);
 out_free:
        while (++i <= ns->level)
                free_pidmap(pid->numbers + i);
@@ -342,6 +341,13 @@ out_free:
        goto out;
 }
 
+void disable_pid_allocation(struct pid_namespace *ns)
+{
+       spin_lock_irq(&pidmap_lock);
+       ns->nr_hashed &= ~PIDNS_HASH_ADDING;
+       spin_unlock_irq(&pidmap_lock);
+}
+
 struct pid *find_pid_ns(int nr, struct pid_namespace *ns)
 {
        struct hlist_node *elem;
@@ -573,6 +579,9 @@ void __init pidhash_init(void)
 
 void __init pidmap_init(void)
 {
+       /* Veryify no one has done anything silly */
+       BUILD_BUG_ON(PID_MAX_LIMIT >= PIDNS_HASH_ADDING);
+
        /* bump default and minimum pid_max based on number of cpus */
        pid_max = min(pid_max_max, max_t(int, pid_max,
                                PIDS_PER_CPU_DEFAULT * num_possible_cpus()));
@@ -584,7 +593,7 @@ void __init pidmap_init(void)
        /* Reserve PID 0. We never call free_pidmap(0) */
        set_bit(0, init_pid_ns.pidmap[0].page);
        atomic_dec(&init_pid_ns.pidmap[0].nr_free);
-       init_pid_ns.nr_hashed = 1;
+       init_pid_ns.nr_hashed = PIDNS_HASH_ADDING;
 
        init_pid_ns.pid_cachep = KMEM_CACHE(pid,
                        SLAB_HWCACHE_ALIGN | SLAB_PANIC);
index fdbd0cdf271ae4ce6ad016f8b826510865fe3600..c1c3dc1c60233f337a01ff13587f1a5a7f57f1cd 100644 (file)
@@ -115,6 +115,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
        ns->level = level;
        ns->parent = get_pid_ns(parent_pid_ns);
        ns->user_ns = get_user_ns(user_ns);
+       ns->nr_hashed = PIDNS_HASH_ADDING;
        INIT_WORK(&ns->proc_work, proc_cleanup_work);
 
        set_bit(0, ns->pidmap[0].page);
@@ -181,6 +182,9 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
        int rc;
        struct task_struct *task, *me = current;
 
+       /* Don't allow any more processes into the pid namespace */
+       disable_pid_allocation(pid_ns);
+
        /* Ignore SIGCHLD causing any terminated children to autoreap */
        spin_lock_irq(&me->sighand->siglock);
        me->sighand->action[SIGCHLD - 1].sa.sa_handler = SIG_IGN;
index a278cad1d5d6225a52e6bf00b2fd90f98bbe916e..8fd709c9bb5843bbad0e7e3fd1e1b00075413b29 100644 (file)
@@ -155,11 +155,19 @@ static void bump_cpu_timer(struct k_itimer *timer,
 
 static inline cputime_t prof_ticks(struct task_struct *p)
 {
-       return p->utime + p->stime;
+       cputime_t utime, stime;
+
+       task_cputime(p, &utime, &stime);
+
+       return utime + stime;
 }
 static inline cputime_t virt_ticks(struct task_struct *p)
 {
-       return p->utime;
+       cputime_t utime;
+
+       task_cputime(p, &utime, NULL);
+
+       return utime;
 }
 
 static int
@@ -471,18 +479,23 @@ static void cleanup_timers(struct list_head *head,
  */
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
+       cputime_t utime, stime;
+
        add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
                                                sizeof(unsigned long long));
+       task_cputime(tsk, &utime, &stime);
        cleanup_timers(tsk->cpu_timers,
-                      tsk->utime, tsk->stime, tsk->se.sum_exec_runtime);
+                      utime, stime, tsk->se.sum_exec_runtime);
 
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
 {
        struct signal_struct *const sig = tsk->signal;
+       cputime_t utime, stime;
 
+       task_cputime(tsk, &utime, &stime);
        cleanup_timers(tsk->signal->cpu_timers,
-                      tsk->utime + sig->utime, tsk->stime + sig->stime,
+                      utime + sig->utime, stime + sig->stime,
                       tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
 }
 
@@ -1226,11 +1239,14 @@ static inline int task_cputime_expired(const struct task_cputime *sample,
 static inline int fastpath_timer_check(struct task_struct *tsk)
 {
        struct signal_struct *sig;
+       cputime_t utime, stime;
+
+       task_cputime(tsk, &utime, &stime);
 
        if (!task_cputime_zero(&tsk->cputime_expires)) {
                struct task_cputime task_sample = {
-                       .utime = tsk->utime,
-                       .stime = tsk->stime,
+                       .utime = utime,
+                       .stime = stime,
                        .sum_exec_runtime = tsk->se.sum_exec_runtime
                };
 
@@ -1401,8 +1417,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                while (!signal_pending(current)) {
                        if (timer.it.cpu.expires.sched == 0) {
                                /*
-                                * Our timer fired and was reset.
+                                * Our timer fired and was reset, below
+                                * deletion can not fail.
                                 */
+                               posix_cpu_timer_del(&timer);
                                spin_unlock_irq(&timer.it_lock);
                                return 0;
                        }
@@ -1420,9 +1438,26 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                 * We were interrupted by a signal.
                 */
                sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-               posix_cpu_timer_set(&timer, 0, &zero_it, it);
+               error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+               if (!error) {
+                       /*
+                        * Timer is now unarmed, deletion can not fail.
+                        */
+                       posix_cpu_timer_del(&timer);
+               }
                spin_unlock_irq(&timer.it_lock);
 
+               while (error == TIMER_RETRY) {
+                       /*
+                        * We need to handle case when timer was or is in the
+                        * middle of firing. In other cases we already freed
+                        * resources.
+                        */
+                       spin_lock_irq(&timer.it_lock);
+                       error = posix_cpu_timer_del(&timer);
+                       spin_unlock_irq(&timer.it_lock);
+               }
+
                if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
                        /*
                         * It actually did fire already.
index 69185ae6b701742de8977760234c5accda366dfd..10349d5f2ec311afe81c17ff533aec6ddbd83d09 100644 (file)
@@ -997,7 +997,7 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
 
        err = kc->clock_adj(which_clock, &ktx);
 
-       if (!err && copy_to_user(utx, &ktx, sizeof(ktx)))
+       if (err >= 0 && copy_to_user(utx, &ktx, sizeof(ktx)))
                return -EFAULT;
 
        return err;
index 19c0d7bcf24a77e0f6de246a30fab029cf3a30cc..f24633afa46a5e7c8c3ae9010548fc95c122d825 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/notifier.h>
 #include <linux/rculist.h>
 #include <linux/poll.h>
+#include <linux/irq_work.h>
 
 #include <asm/uaccess.h>
 
@@ -87,12 +88,6 @@ static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
-#ifdef CONFIG_LOCKDEP
-static struct lockdep_map console_lock_dep_map = {
-       .name = "console_lock"
-};
-#endif
-
 /*
  * This is used for debugging the mess that is the VT code by
  * keeping track if we have the console semaphore held. It's
@@ -870,10 +865,11 @@ static size_t print_time(u64 ts, char *buf)
        if (!printk_time)
                return 0;
 
+       rem_nsec = do_div(ts, 1000000000);
+
        if (!buf)
-               return 15;
+               return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts);
 
-       rem_nsec = do_div(ts, 1000000000);
        return sprintf(buf, "[%5lu.%06lu] ",
                       (unsigned long)ts, rem_nsec / 1000);
 }
@@ -1923,7 +1919,6 @@ void console_lock(void)
                return;
        console_locked = 1;
        console_may_schedule = 1;
-       mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
 }
 EXPORT_SYMBOL(console_lock);
 
@@ -1945,7 +1940,6 @@ int console_trylock(void)
        }
        console_locked = 1;
        console_may_schedule = 0;
-       mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
        return 1;
 }
 EXPORT_SYMBOL(console_trylock);
@@ -1966,30 +1960,32 @@ int is_console_locked(void)
 static DEFINE_PER_CPU(int, printk_pending);
 static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
 
-void printk_tick(void)
+static void wake_up_klogd_work_func(struct irq_work *irq_work)
 {
-       if (__this_cpu_read(printk_pending)) {
-               int pending = __this_cpu_xchg(printk_pending, 0);
-               if (pending & PRINTK_PENDING_SCHED) {
-                       char *buf = __get_cpu_var(printk_sched_buf);
-                       printk(KERN_WARNING "[sched_delayed] %s", buf);
-               }
-               if (pending & PRINTK_PENDING_WAKEUP)
-                       wake_up_interruptible(&log_wait);
+       int pending = __this_cpu_xchg(printk_pending, 0);
+
+       if (pending & PRINTK_PENDING_SCHED) {
+               char *buf = __get_cpu_var(printk_sched_buf);
+               printk(KERN_WARNING "[sched_delayed] %s", buf);
        }
-}
 
-int printk_needs_cpu(int cpu)
-{
-       if (cpu_is_offline(cpu))
-               printk_tick();
-       return __this_cpu_read(printk_pending);
+       if (pending & PRINTK_PENDING_WAKEUP)
+               wake_up_interruptible(&log_wait);
 }
 
+static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
+       .func = wake_up_klogd_work_func,
+       .flags = IRQ_WORK_LAZY,
+};
+
 void wake_up_klogd(void)
 {
-       if (waitqueue_active(&log_wait))
+       preempt_disable();
+       if (waitqueue_active(&log_wait)) {
                this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
+               irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
+       }
+       preempt_enable();
 }
 
 static void console_cont_flush(char *text, size_t size)
@@ -2106,7 +2102,6 @@ skip:
                local_irq_restore(flags);
        }
        console_locked = 0;
-       mutex_release(&console_lock_dep_map, 1, _RET_IP_);
 
        /* Release the exclusive_console once it is used */
        if (unlikely(exclusive_console))
@@ -2470,6 +2465,7 @@ int printk_sched(const char *fmt, ...)
        va_end(args);
 
        __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
+       irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
        local_irq_restore(flags);
 
        return r;
index 1f391819c42fe6d6539f5ba5e66e6f365b877f6d..dc3384ee874e4ed5a0344395757744adc268c9bc 100644 (file)
@@ -37,9 +37,6 @@ struct profile_hit {
 #define NR_PROFILE_HIT         (PAGE_SIZE/sizeof(struct profile_hit))
 #define NR_PROFILE_GRP         (NR_PROFILE_HIT/PROFILE_GRPSZ)
 
-/* Oprofile timer tick hook */
-static int (*timer_hook)(struct pt_regs *) __read_mostly;
-
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
 
@@ -208,25 +205,6 @@ int profile_event_unregister(enum profile_type type, struct notifier_block *n)
 }
 EXPORT_SYMBOL_GPL(profile_event_unregister);
 
-int register_timer_hook(int (*hook)(struct pt_regs *))
-{
-       if (timer_hook)
-               return -EBUSY;
-       timer_hook = hook;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(register_timer_hook);
-
-void unregister_timer_hook(int (*hook)(struct pt_regs *))
-{
-       WARN_ON(hook != timer_hook);
-       timer_hook = NULL;
-       /* make sure all CPUs see the NULL hook */
-       synchronize_sched();  /* Allow ongoing interrupts to complete. */
-}
-EXPORT_SYMBOL_GPL(unregister_timer_hook);
-
-
 #ifdef CONFIG_SMP
 /*
  * Each cpu has a pair of open-addressed hashtables for pending
@@ -436,8 +414,6 @@ void profile_tick(int type)
 {
        struct pt_regs *regs = get_irq_regs();
 
-       if (type == CPU_PROFILING && timer_hook)
-               timer_hook(regs);
        if (!user_mode(regs) && prof_cpu_mask != NULL &&
            cpumask_test_cpu(smp_processor_id(), prof_cpu_mask))
                profile_hit(type, (void *)profile_pc(regs));
index 1599157336a6c2be56037a510b7c2c28648201b8..acbd28424d812040e060a82ae2d6f28e156e5fe1 100644 (file)
@@ -117,11 +117,45 @@ void __ptrace_unlink(struct task_struct *child)
         * TASK_KILLABLE sleeps.
         */
        if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child))
-               signal_wake_up(child, task_is_traced(child));
+               ptrace_signal_wake_up(child, true);
 
        spin_unlock(&child->sighand->siglock);
 }
 
+/* Ensure that nothing can wake it up, even SIGKILL */
+static bool ptrace_freeze_traced(struct task_struct *task)
+{
+       bool ret = false;
+
+       /* Lockless, nobody but us can set this flag */
+       if (task->jobctl & JOBCTL_LISTENING)
+               return ret;
+
+       spin_lock_irq(&task->sighand->siglock);
+       if (task_is_traced(task) && !__fatal_signal_pending(task)) {
+               task->state = __TASK_TRACED;
+               ret = true;
+       }
+       spin_unlock_irq(&task->sighand->siglock);
+
+       return ret;
+}
+
+static void ptrace_unfreeze_traced(struct task_struct *task)
+{
+       if (task->state != __TASK_TRACED)
+               return;
+
+       WARN_ON(!task->ptrace || task->parent != current);
+
+       spin_lock_irq(&task->sighand->siglock);
+       if (__fatal_signal_pending(task))
+               wake_up_state(task, __TASK_TRACED);
+       else
+               task->state = TASK_TRACED;
+       spin_unlock_irq(&task->sighand->siglock);
+}
+
 /**
  * ptrace_check_attach - check whether ptracee is ready for ptrace operation
  * @child: ptracee to check for
@@ -139,7 +173,7 @@ void __ptrace_unlink(struct task_struct *child)
  * RETURNS:
  * 0 on success, -ESRCH if %child is not ready.
  */
-int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
        int ret = -ESRCH;
 
@@ -151,24 +185,29 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
         * be changed by us so it's not changing right after this.
         */
        read_lock(&tasklist_lock);
-       if ((child->ptrace & PT_PTRACED) && child->parent == current) {
+       if (child->ptrace && child->parent == current) {
+               WARN_ON(child->state == __TASK_TRACED);
                /*
                 * child->sighand can't be NULL, release_task()
                 * does ptrace_unlink() before __exit_signal().
                 */
-               spin_lock_irq(&child->sighand->siglock);
-               WARN_ON_ONCE(task_is_stopped(child));
-               if (ignore_state || (task_is_traced(child) &&
-                                    !(child->jobctl & JOBCTL_LISTENING)))
+               if (ignore_state || ptrace_freeze_traced(child))
                        ret = 0;
-               spin_unlock_irq(&child->sighand->siglock);
        }
        read_unlock(&tasklist_lock);
 
-       if (!ret && !ignore_state)
-               ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
+       if (!ret && !ignore_state) {
+               if (!wait_task_inactive(child, __TASK_TRACED)) {
+                       /*
+                        * This can only happen if may_ptrace_stop() fails and
+                        * ptrace_stop() changes ->state back to TASK_RUNNING,
+                        * so we should not worry about leaking __TASK_TRACED.
+                        */
+                       WARN_ON(child->state == __TASK_TRACED);
+                       ret = -ESRCH;
+               }
+       }
 
-       /* All systems go.. */
        return ret;
 }
 
@@ -317,7 +356,7 @@ static int ptrace_attach(struct task_struct *task, long request,
         */
        if (task_is_stopped(task) &&
            task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
-               signal_wake_up(task, 1);
+               signal_wake_up_state(task, __TASK_STOPPED);
 
        spin_unlock(&task->sighand->siglock);
 
@@ -673,6 +712,12 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
                                             kiov->iov_len, kiov->iov_base);
 }
 
+/*
+ * This is declared in linux/regset.h and defined in machine-dependent
+ * code.  We put the export here, near the primary machine-neutral use,
+ * to ensure no machine forgets it.
+ */
+EXPORT_SYMBOL_GPL(task_user_regset_view);
 #endif
 
 int ptrace_request(struct task_struct *child, long request,
@@ -737,7 +782,7 @@ int ptrace_request(struct task_struct *child, long request,
                 * tracee into STOP.
                 */
                if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
-                       signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
+                       ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
 
                unlock_task_sighand(child, &flags);
                ret = 0;
@@ -763,7 +808,7 @@ int ptrace_request(struct task_struct *child, long request,
                         * start of this trap and now.  Trigger re-trap.
                         */
                        if (child->jobctl & JOBCTL_TRAP_NOTIFY)
-                               signal_wake_up(child, true);
+                               ptrace_signal_wake_up(child, true);
                        ret = 0;
                }
                unlock_task_sighand(child, &flags);
@@ -900,6 +945,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
                goto out_put_task_struct;
 
        ret = arch_ptrace(child, request, addr, data);
+       if (ret || request != PTRACE_DETACH)
+               ptrace_unfreeze_traced(child);
 
  out_put_task_struct:
        put_task_struct(child);
@@ -1039,8 +1086,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 
        ret = ptrace_check_attach(child, request == PTRACE_KILL ||
                                  request == PTRACE_INTERRUPT);
-       if (!ret)
+       if (!ret) {
                ret = compat_arch_ptrace(child, request, addr, data);
+               if (ret || request != PTRACE_DETACH)
+                       ptrace_unfreeze_traced(child);
+       }
 
  out_put_task_struct:
        put_task_struct(child);
index 20dfba576c2b7efde60815321b5dce1c7e049e37..7f8e7590e3e5d414141f3f778caaf58f8b0f6717 100644 (file)
@@ -111,4 +111,11 @@ static inline bool __rcu_reclaim(char *rn, struct rcu_head *head)
 
 extern int rcu_expedited;
 
+#ifdef CONFIG_RCU_STALL_COMMON
+
+extern int rcu_cpu_stall_suppress;
+int rcu_jiffies_till_stall_check(void);
+
+#endif /* #ifdef CONFIG_RCU_STALL_COMMON */
+
 #endif /* __LINUX_RCU_H */
index a2cf76177b443d33bb30b19052524db385cb4fc9..48ab70384a4cda7533a65c02915ef253ea767645 100644 (file)
@@ -404,11 +404,65 @@ EXPORT_SYMBOL_GPL(rcuhead_debug_descr);
 #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE)
-void do_trace_rcu_torture_read(char *rcutorturename, struct rcu_head *rhp)
+void do_trace_rcu_torture_read(char *rcutorturename, struct rcu_head *rhp,
+                              unsigned long secs,
+                              unsigned long c_old, unsigned long c)
 {
-       trace_rcu_torture_read(rcutorturename, rhp);
+       trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c);
 }
 EXPORT_SYMBOL_GPL(do_trace_rcu_torture_read);
 #else
-#define do_trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
+#define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
+       do { } while (0)
 #endif
+
+#ifdef CONFIG_RCU_STALL_COMMON
+
+#ifdef CONFIG_PROVE_RCU
+#define RCU_STALL_DELAY_DELTA         (5 * HZ)
+#else
+#define RCU_STALL_DELAY_DELTA         0
+#endif
+
+int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
+int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
+
+module_param(rcu_cpu_stall_suppress, int, 0644);
+module_param(rcu_cpu_stall_timeout, int, 0644);
+
+int rcu_jiffies_till_stall_check(void)
+{
+       int till_stall_check = ACCESS_ONCE(rcu_cpu_stall_timeout);
+
+       /*
+        * Limit check must be consistent with the Kconfig limits
+        * for CONFIG_RCU_CPU_STALL_TIMEOUT.
+        */
+       if (till_stall_check < 3) {
+               ACCESS_ONCE(rcu_cpu_stall_timeout) = 3;
+               till_stall_check = 3;
+       } else if (till_stall_check > 300) {
+               ACCESS_ONCE(rcu_cpu_stall_timeout) = 300;
+               till_stall_check = 300;
+       }
+       return till_stall_check * HZ + RCU_STALL_DELAY_DELTA;
+}
+
+static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
+{
+       rcu_cpu_stall_suppress = 1;
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block rcu_panic_block = {
+       .notifier_call = rcu_panic,
+};
+
+static int __init check_cpu_stall_init(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
+       return 0;
+}
+early_initcall(check_cpu_stall_init);
+
+#endif /* #ifdef CONFIG_RCU_STALL_COMMON */
index e7dce58f9c2aa3fba2b6b3035d9d1f42d3598399..a0714a51b6d710e8030c33ddaadffe73fe30e07c 100644 (file)
@@ -51,10 +51,10 @@ static void __call_rcu(struct rcu_head *head,
                       void (*func)(struct rcu_head *rcu),
                       struct rcu_ctrlblk *rcp);
 
-#include "rcutiny_plugin.h"
-
 static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
 
+#include "rcutiny_plugin.h"
+
 /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */
 static void rcu_idle_enter_common(long long newval)
 {
@@ -193,7 +193,7 @@ EXPORT_SYMBOL(rcu_is_cpu_idle);
  * interrupts don't count, we must be running at the first interrupt
  * level.
  */
-int rcu_is_cpu_rrupt_from_idle(void)
+static int rcu_is_cpu_rrupt_from_idle(void)
 {
        return rcu_dynticks_nesting <= 1;
 }
@@ -205,6 +205,7 @@ int rcu_is_cpu_rrupt_from_idle(void)
  */
 static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
 {
+       reset_cpu_stall_ticks(rcp);
        if (rcp->rcucblist != NULL &&
            rcp->donetail != rcp->curtail) {
                rcp->donetail = rcp->curtail;
@@ -251,6 +252,7 @@ void rcu_bh_qs(int cpu)
  */
 void rcu_check_callbacks(int cpu, int user)
 {
+       check_cpu_stalls();
        if (user || rcu_is_cpu_rrupt_from_idle())
                rcu_sched_qs(cpu);
        else if (!in_softirq())
index f85016a2309b94c08121f0e3346c1c24d81d4c18..8a233002faeba228d6195481f0812af703b7e9f3 100644 (file)
@@ -33,6 +33,9 @@ struct rcu_ctrlblk {
        struct rcu_head **donetail;     /* ->next pointer of last "done" CB. */
        struct rcu_head **curtail;      /* ->next pointer of last CB. */
        RCU_TRACE(long qlen);           /* Number of pending CBs. */
+       RCU_TRACE(unsigned long gp_start); /* Start time for stalls. */
+       RCU_TRACE(unsigned long ticks_this_gp); /* Statistic for stalls. */
+       RCU_TRACE(unsigned long jiffies_stall); /* Jiffies at next stall. */
        RCU_TRACE(char *name);          /* Name of RCU type. */
 };
 
@@ -54,6 +57,51 @@ int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+#ifdef CONFIG_RCU_TRACE
+
+static void check_cpu_stall(struct rcu_ctrlblk *rcp)
+{
+       unsigned long j;
+       unsigned long js;
+
+       if (rcu_cpu_stall_suppress)
+               return;
+       rcp->ticks_this_gp++;
+       j = jiffies;
+       js = rcp->jiffies_stall;
+       if (*rcp->curtail && ULONG_CMP_GE(j, js)) {
+               pr_err("INFO: %s stall on CPU (%lu ticks this GP) idle=%llx (t=%lu jiffies q=%ld)\n",
+                      rcp->name, rcp->ticks_this_gp, rcu_dynticks_nesting,
+                      jiffies - rcp->gp_start, rcp->qlen);
+               dump_stack();
+       }
+       if (*rcp->curtail && ULONG_CMP_GE(j, js))
+               rcp->jiffies_stall = jiffies +
+                       3 * rcu_jiffies_till_stall_check() + 3;
+       else if (ULONG_CMP_GE(j, js))
+               rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+}
+
+static void check_cpu_stall_preempt(void);
+
+#endif /* #ifdef CONFIG_RCU_TRACE */
+
+static void reset_cpu_stall_ticks(struct rcu_ctrlblk *rcp)
+{
+#ifdef CONFIG_RCU_TRACE
+       rcp->ticks_this_gp = 0;
+       rcp->gp_start = jiffies;
+       rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+#endif /* #ifdef CONFIG_RCU_TRACE */
+}
+
+static void check_cpu_stalls(void)
+{
+       RCU_TRACE(check_cpu_stall(&rcu_bh_ctrlblk));
+       RCU_TRACE(check_cpu_stall(&rcu_sched_ctrlblk));
+       RCU_TRACE(check_cpu_stall_preempt());
+}
+
 #ifdef CONFIG_TINY_PREEMPT_RCU
 
 #include <linux/delay.h>
@@ -448,6 +496,7 @@ static void rcu_preempt_start_gp(void)
                /* Official start of GP. */
                rcu_preempt_ctrlblk.gpnum++;
                RCU_TRACE(rcu_preempt_ctrlblk.n_grace_periods++);
+               reset_cpu_stall_ticks(&rcu_preempt_ctrlblk.rcb);
 
                /* Any blocked RCU readers block new GP. */
                if (rcu_preempt_blocked_readers_any())
@@ -1054,4 +1103,11 @@ MODULE_AUTHOR("Paul E. McKenney");
 MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation");
 MODULE_LICENSE("GPL");
 
+static void check_cpu_stall_preempt(void)
+{
+#ifdef CONFIG_TINY_PREEMPT_RCU
+       check_cpu_stall(&rcu_preempt_ctrlblk.rcb);
+#endif /* #ifdef CONFIG_TINY_PREEMPT_RCU */
+}
+
 #endif /* #ifdef CONFIG_RCU_TRACE */
index 31dea01c85fd50fb3297627dc81556a146f249c5..e1f3a8c96724374be64e1cf252a40f2e9eac5a70 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/stat.h>
 #include <linux/srcu.h>
 #include <linux/slab.h>
+#include <linux/trace_clock.h>
 #include <asm/byteorder.h>
 
 MODULE_LICENSE("GPL");
@@ -207,6 +208,20 @@ MODULE_PARM_DESC(rcutorture_runnable, "Start rcutorture at boot");
 #define rcu_can_boost() 0
 #endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
 
+#ifdef CONFIG_RCU_TRACE
+static u64 notrace rcu_trace_clock_local(void)
+{
+       u64 ts = trace_clock_local();
+       unsigned long __maybe_unused ts_rem = do_div(ts, NSEC_PER_USEC);
+       return ts;
+}
+#else /* #ifdef CONFIG_RCU_TRACE */
+static u64 notrace rcu_trace_clock_local(void)
+{
+       return 0ULL;
+}
+#endif /* #else #ifdef CONFIG_RCU_TRACE */
+
 static unsigned long shutdown_time;    /* jiffies to system shutdown. */
 static unsigned long boost_starttime;  /* jiffies of next boost test start. */
 DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
@@ -845,7 +860,7 @@ static int rcu_torture_boost(void *arg)
                /* Wait for the next test interval. */
                oldstarttime = boost_starttime;
                while (ULONG_CMP_LT(jiffies, oldstarttime)) {
-                       schedule_timeout_uninterruptible(1);
+                       schedule_timeout_interruptible(oldstarttime - jiffies);
                        rcu_stutter_wait("rcu_torture_boost");
                        if (kthread_should_stop() ||
                            fullstop != FULLSTOP_DONTSTOP)
@@ -1028,7 +1043,6 @@ void rcutorture_trace_dump(void)
                return;
        if (atomic_xchg(&beenhere, 1) != 0)
                return;
-       do_trace_rcu_torture_read(cur_ops->name, (struct rcu_head *)~0UL);
        ftrace_dump(DUMP_ALL);
 }
 
@@ -1042,13 +1056,16 @@ static void rcu_torture_timer(unsigned long unused)
 {
        int idx;
        int completed;
+       int completed_end;
        static DEFINE_RCU_RANDOM(rand);
        static DEFINE_SPINLOCK(rand_lock);
        struct rcu_torture *p;
        int pipe_count;
+       unsigned long long ts;
 
        idx = cur_ops->readlock();
        completed = cur_ops->completed();
+       ts = rcu_trace_clock_local();
        p = rcu_dereference_check(rcu_torture_current,
                                  rcu_read_lock_bh_held() ||
                                  rcu_read_lock_sched_held() ||
@@ -1058,7 +1075,6 @@ static void rcu_torture_timer(unsigned long unused)
                cur_ops->readunlock(idx);
                return;
        }
-       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
        if (p->rtort_mbtest == 0)
                atomic_inc(&n_rcu_torture_mberror);
        spin_lock(&rand_lock);
@@ -1071,10 +1087,14 @@ static void rcu_torture_timer(unsigned long unused)
                /* Should not happen, but... */
                pipe_count = RCU_TORTURE_PIPE_LEN;
        }
-       if (pipe_count > 1)
+       completed_end = cur_ops->completed();
+       if (pipe_count > 1) {
+               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
+                                         completed, completed_end);
                rcutorture_trace_dump();
+       }
        __this_cpu_inc(rcu_torture_count[pipe_count]);
-       completed = cur_ops->completed() - completed;
+       completed = completed_end - completed;
        if (completed > RCU_TORTURE_PIPE_LEN) {
                /* Should not happen, but... */
                completed = RCU_TORTURE_PIPE_LEN;
@@ -1094,11 +1114,13 @@ static int
 rcu_torture_reader(void *arg)
 {
        int completed;
+       int completed_end;
        int idx;
        DEFINE_RCU_RANDOM(rand);
        struct rcu_torture *p;
        int pipe_count;
        struct timer_list t;
+       unsigned long long ts;
 
        VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
        set_user_nice(current, 19);
@@ -1112,6 +1134,7 @@ rcu_torture_reader(void *arg)
                }
                idx = cur_ops->readlock();
                completed = cur_ops->completed();
+               ts = rcu_trace_clock_local();
                p = rcu_dereference_check(rcu_torture_current,
                                          rcu_read_lock_bh_held() ||
                                          rcu_read_lock_sched_held() ||
@@ -1122,7 +1145,6 @@ rcu_torture_reader(void *arg)
                        schedule_timeout_interruptible(HZ);
                        continue;
                }
-               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
                if (p->rtort_mbtest == 0)
                        atomic_inc(&n_rcu_torture_mberror);
                cur_ops->read_delay(&rand);
@@ -1132,10 +1154,14 @@ rcu_torture_reader(void *arg)
                        /* Should not happen, but... */
                        pipe_count = RCU_TORTURE_PIPE_LEN;
                }
-               if (pipe_count > 1)
+               completed_end = cur_ops->completed();
+               if (pipe_count > 1) {
+                       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
+                                                 ts, completed, completed_end);
                        rcutorture_trace_dump();
+               }
                __this_cpu_inc(rcu_torture_count[pipe_count]);
-               completed = cur_ops->completed() - completed;
+               completed = completed_end - completed;
                if (completed > RCU_TORTURE_PIPE_LEN) {
                        /* Should not happen, but... */
                        completed = RCU_TORTURE_PIPE_LEN;
@@ -1301,19 +1327,35 @@ static void rcu_torture_shuffle_tasks(void)
                                set_cpus_allowed_ptr(reader_tasks[i],
                                                     shuffle_tmp_mask);
        }
-
        if (fakewriter_tasks) {
                for (i = 0; i < nfakewriters; i++)
                        if (fakewriter_tasks[i])
                                set_cpus_allowed_ptr(fakewriter_tasks[i],
                                                     shuffle_tmp_mask);
        }
-
        if (writer_task)
                set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
-
        if (stats_task)
                set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
+       if (stutter_task)
+               set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
+       if (fqs_task)
+               set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
+       if (shutdown_task)
+               set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
+#ifdef CONFIG_HOTPLUG_CPU
+       if (onoff_task)
+               set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+       if (stall_task)
+               set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
+       if (barrier_cbs_tasks)
+               for (i = 0; i < n_barrier_cbs; i++)
+                       if (barrier_cbs_tasks[i])
+                               set_cpus_allowed_ptr(barrier_cbs_tasks[i],
+                                                    shuffle_tmp_mask);
+       if (barrier_task)
+               set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
 
        if (rcu_idle_cpu == -1)
                rcu_idle_cpu = num_online_cpus() - 1;
@@ -1749,7 +1791,7 @@ static int rcu_torture_barrier_init(void)
        barrier_cbs_wq =
                kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
                        GFP_KERNEL);
-       if (barrier_cbs_tasks == NULL || barrier_cbs_wq == 0)
+       if (barrier_cbs_tasks == NULL || !barrier_cbs_wq)
                return -ENOMEM;
        for (i = 0; i < n_barrier_cbs; i++) {
                init_waitqueue_head(&barrier_cbs_wq[i]);
index e441b77b614e1eb74b1f764710dc13f2398de17a..5b8ad827fd86e74932a0b42b40c8f5c27e370228 100644 (file)
@@ -105,7 +105,7 @@ int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
  * The rcu_scheduler_active variable transitions from zero to one just
  * before the first task is spawned.  So when this variable is zero, RCU
  * can assume that there is but one task, allowing RCU to (for example)
- * optimized synchronize_sched() to a simple barrier().  When this variable
+ * optimize synchronize_sched() to a simple barrier().  When this variable
  * is one, RCU must actually do all the hard work required to detect real
  * grace periods.  This variable is also used to suppress boot-time false
  * positives from lockdep-RCU error checking.
@@ -217,12 +217,6 @@ module_param(blimit, long, 0444);
 module_param(qhimark, long, 0444);
 module_param(qlowmark, long, 0444);
 
-int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
-int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
-
-module_param(rcu_cpu_stall_suppress, int, 0644);
-module_param(rcu_cpu_stall_timeout, int, 0644);
-
 static ulong jiffies_till_first_fqs = RCU_JIFFIES_TILL_FORCE_QS;
 static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS;
 
@@ -305,17 +299,27 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
 }
 
 /*
- * Does the current CPU require a yet-as-unscheduled grace period?
+ * Does the current CPU require a not-yet-started grace period?
+ * The caller must have disabled interrupts to prevent races with
+ * normal callback registry.
  */
 static int
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       struct rcu_head **ntp;
+       int i;
 
-       ntp = rdp->nxttail[RCU_DONE_TAIL +
-                          (ACCESS_ONCE(rsp->completed) != rdp->completed)];
-       return rdp->nxttail[RCU_DONE_TAIL] && ntp && *ntp &&
-              !rcu_gp_in_progress(rsp);
+       if (rcu_gp_in_progress(rsp))
+               return 0;  /* No, a grace period is already in progress. */
+       if (!rdp->nxttail[RCU_NEXT_TAIL])
+               return 0;  /* No, this is a no-CBs (or offline) CPU. */
+       if (*rdp->nxttail[RCU_NEXT_READY_TAIL])
+               return 1;  /* Yes, this CPU has newly registered callbacks. */
+       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++)
+               if (rdp->nxttail[i - 1] != rdp->nxttail[i] &&
+                   ULONG_CMP_LT(ACCESS_ONCE(rsp->completed),
+                                rdp->nxtcompleted[i]))
+                       return 1;  /* Yes, CBs for future grace period. */
+       return 0; /* No grace period needed. */
 }
 
 /*
@@ -336,7 +340,7 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp)
 static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
                                bool user)
 {
-       trace_rcu_dyntick("Start", oldval, 0);
+       trace_rcu_dyntick("Start", oldval, rdtp->dynticks_nesting);
        if (!user && !is_idle_task(current)) {
                struct task_struct *idle = idle_task(smp_processor_id());
 
@@ -727,7 +731,7 @@ EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
  * interrupt from idle, return true.  The caller must have at least
  * disabled preemption.
  */
-int rcu_is_cpu_rrupt_from_idle(void)
+static int rcu_is_cpu_rrupt_from_idle(void)
 {
        return __get_cpu_var(rcu_dynticks).dynticks_nesting <= 1;
 }
@@ -793,28 +797,10 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
        return 0;
 }
 
-static int jiffies_till_stall_check(void)
-{
-       int till_stall_check = ACCESS_ONCE(rcu_cpu_stall_timeout);
-
-       /*
-        * Limit check must be consistent with the Kconfig limits
-        * for CONFIG_RCU_CPU_STALL_TIMEOUT.
-        */
-       if (till_stall_check < 3) {
-               ACCESS_ONCE(rcu_cpu_stall_timeout) = 3;
-               till_stall_check = 3;
-       } else if (till_stall_check > 300) {
-               ACCESS_ONCE(rcu_cpu_stall_timeout) = 300;
-               till_stall_check = 300;
-       }
-       return till_stall_check * HZ + RCU_STALL_DELAY_DELTA;
-}
-
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
        rsp->gp_start = jiffies;
-       rsp->jiffies_stall = jiffies + jiffies_till_stall_check();
+       rsp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
 }
 
 /*
@@ -857,7 +843,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
-       rsp->jiffies_stall = jiffies + 3 * jiffies_till_stall_check() + 3;
+       rsp->jiffies_stall = jiffies + 3 * rcu_jiffies_till_stall_check() + 3;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        /*
@@ -935,7 +921,7 @@ static void print_cpu_stall(struct rcu_state *rsp)
        raw_spin_lock_irqsave(&rnp->lock, flags);
        if (ULONG_CMP_GE(jiffies, rsp->jiffies_stall))
                rsp->jiffies_stall = jiffies +
-                                    3 * jiffies_till_stall_check() + 3;
+                                    3 * rcu_jiffies_till_stall_check() + 3;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        set_need_resched();  /* kick ourselves to get things going. */
@@ -966,12 +952,6 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 }
 
-static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
-{
-       rcu_cpu_stall_suppress = 1;
-       return NOTIFY_DONE;
-}
-
 /**
  * rcu_cpu_stall_reset - prevent further stall warnings in current grace period
  *
@@ -989,15 +969,6 @@ void rcu_cpu_stall_reset(void)
                rsp->jiffies_stall = jiffies + ULONG_MAX / 2;
 }
 
-static struct notifier_block rcu_panic_block = {
-       .notifier_call = rcu_panic,
-};
-
-static void __init check_cpu_stall_init(void)
-{
-       atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
-}
-
 /*
  * Update CPU-local rcu_data state to record the newly noticed grace period.
  * This is used both when we started the grace period and when we notice
@@ -1070,6 +1041,145 @@ static void init_callback_list(struct rcu_data *rdp)
        init_nocb_callback_list(rdp);
 }
 
+/*
+ * Determine the value that ->completed will have at the end of the
+ * next subsequent grace period.  This is used to tag callbacks so that
+ * a CPU can invoke callbacks in a timely fashion even if that CPU has
+ * been dyntick-idle for an extended period with callbacks under the
+ * influence of RCU_FAST_NO_HZ.
+ *
+ * The caller must hold rnp->lock with interrupts disabled.
+ */
+static unsigned long rcu_cbs_completed(struct rcu_state *rsp,
+                                      struct rcu_node *rnp)
+{
+       /*
+        * If RCU is idle, we just wait for the next grace period.
+        * But we can only be sure that RCU is idle if we are looking
+        * at the root rcu_node structure -- otherwise, a new grace
+        * period might have started, but just not yet gotten around
+        * to initializing the current non-root rcu_node structure.
+        */
+       if (rcu_get_root(rsp) == rnp && rnp->gpnum == rnp->completed)
+               return rnp->completed + 1;
+
+       /*
+        * Otherwise, wait for a possible partial grace period and
+        * then the subsequent full grace period.
+        */
+       return rnp->completed + 2;
+}
+
+/*
+ * If there is room, assign a ->completed number to any callbacks on
+ * this CPU that have not already been assigned.  Also accelerate any
+ * callbacks that were previously assigned a ->completed number that has
+ * since proven to be too conservative, which can happen if callbacks get
+ * assigned a ->completed number while RCU is idle, but with reference to
+ * a non-root rcu_node structure.  This function is idempotent, so it does
+ * not hurt to call it repeatedly.
+ *
+ * The caller must hold rnp->lock with interrupts disabled.
+ */
+static void rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
+                              struct rcu_data *rdp)
+{
+       unsigned long c;
+       int i;
+
+       /* If the CPU has no callbacks, nothing to do. */
+       if (!rdp->nxttail[RCU_NEXT_TAIL] || !*rdp->nxttail[RCU_DONE_TAIL])
+               return;
+
+       /*
+        * Starting from the sublist containing the callbacks most
+        * recently assigned a ->completed number and working down, find the
+        * first sublist that is not assignable to an upcoming grace period.
+        * Such a sublist has something in it (first two tests) and has
+        * a ->completed number assigned that will complete sooner than
+        * the ->completed number for newly arrived callbacks (last test).
+        *
+        * The key point is that any later sublist can be assigned the
+        * same ->completed number as the newly arrived callbacks, which
+        * means that the callbacks in any of these later sublist can be
+        * grouped into a single sublist, whether or not they have already
+        * been assigned a ->completed number.
+        */
+       c = rcu_cbs_completed(rsp, rnp);
+       for (i = RCU_NEXT_TAIL - 1; i > RCU_DONE_TAIL; i--)
+               if (rdp->nxttail[i] != rdp->nxttail[i - 1] &&
+                   !ULONG_CMP_GE(rdp->nxtcompleted[i], c))
+                       break;
+
+       /*
+        * If there are no sublist for unassigned callbacks, leave.
+        * At the same time, advance "i" one sublist, so that "i" will
+        * index into the sublist where all the remaining callbacks should
+        * be grouped into.
+        */
+       if (++i >= RCU_NEXT_TAIL)
+               return;
+
+       /*
+        * Assign all subsequent callbacks' ->completed number to the next
+        * full grace period and group them all in the sublist initially
+        * indexed by "i".
+        */
+       for (; i <= RCU_NEXT_TAIL; i++) {
+               rdp->nxttail[i] = rdp->nxttail[RCU_NEXT_TAIL];
+               rdp->nxtcompleted[i] = c;
+       }
+
+       /* Trace depending on how much we were able to accelerate. */
+       if (!*rdp->nxttail[RCU_WAIT_TAIL])
+               trace_rcu_grace_period(rsp->name, rdp->gpnum, "AccWaitCB");
+       else
+               trace_rcu_grace_period(rsp->name, rdp->gpnum, "AccReadyCB");
+}
+
+/*
+ * Move any callbacks whose grace period has completed to the
+ * RCU_DONE_TAIL sublist, then compact the remaining sublists and
+ * assign ->completed numbers to any callbacks in the RCU_NEXT_TAIL
+ * sublist.  This function is idempotent, so it does not hurt to
+ * invoke it repeatedly.  As long as it is not invoked -too- often...
+ *
+ * The caller must hold rnp->lock with interrupts disabled.
+ */
+static void rcu_advance_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
+                           struct rcu_data *rdp)
+{
+       int i, j;
+
+       /* If the CPU has no callbacks, nothing to do. */
+       if (!rdp->nxttail[RCU_NEXT_TAIL] || !*rdp->nxttail[RCU_DONE_TAIL])
+               return;
+
+       /*
+        * Find all callbacks whose ->completed numbers indicate that they
+        * are ready to invoke, and put them into the RCU_DONE_TAIL sublist.
+        */
+       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++) {
+               if (ULONG_CMP_LT(rnp->completed, rdp->nxtcompleted[i]))
+                       break;
+               rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[i];
+       }
+       /* Clean up any sublist tail pointers that were misordered above. */
+       for (j = RCU_WAIT_TAIL; j < i; j++)
+               rdp->nxttail[j] = rdp->nxttail[RCU_DONE_TAIL];
+
+       /* Copy down callbacks to fill in empty sublists. */
+       for (j = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++, j++) {
+               if (rdp->nxttail[j] == rdp->nxttail[RCU_NEXT_TAIL])
+                       break;
+               rdp->nxttail[j] = rdp->nxttail[i];
+               rdp->nxtcompleted[j] = rdp->nxtcompleted[i];
+       }
+
+       /* Classify any remaining callbacks. */
+       rcu_accelerate_cbs(rsp, rnp, rdp);
+}
+
 /*
  * Advance this CPU's callbacks, but only if the current grace period
  * has ended.  This may be called only from the CPU to whom the rdp
@@ -1080,12 +1190,15 @@ static void
 __rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp)
 {
        /* Did another grace period end? */
-       if (rdp->completed != rnp->completed) {
+       if (rdp->completed == rnp->completed) {
 
-               /* Advance callbacks.  No harm if list empty. */
-               rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL];
-               rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL];
-               rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+               /* No, so just accelerate recent callbacks. */
+               rcu_accelerate_cbs(rsp, rnp, rdp);
+
+       } else {
+
+               /* Advance callbacks. */
+               rcu_advance_cbs(rsp, rnp, rdp);
 
                /* Remember that we saw this grace-period completion. */
                rdp->completed = rnp->completed;
@@ -1392,17 +1505,10 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
        /*
         * Because there is no grace period in progress right now,
         * any callbacks we have up to this point will be satisfied
-        * by the next grace period.  So promote all callbacks to be
-        * handled after the end of the next grace period.  If the
-        * CPU is not yet aware of the end of the previous grace period,
-        * we need to allow for the callback advancement that will
-        * occur when it does become aware.  Deadlock prevents us from
-        * making it aware at this point: We cannot acquire a leaf
-        * rcu_node ->lock while holding the root rcu_node ->lock.
+        * by the next grace period.  So this is a good place to
+        * assign a grace period number to recently posted callbacks.
         */
-       rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
-       if (rdp->completed == rsp->completed)
-               rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+       rcu_accelerate_cbs(rsp, rnp, rdp);
 
        rsp->gp_flags = RCU_GP_FLAG_INIT;
        raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
@@ -1527,7 +1633,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
                 * This GP can't end until cpu checks in, so all of our
                 * callbacks can be processed during the next GP.
                 */
-               rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+               rcu_accelerate_cbs(rsp, rnp, rdp);
 
                rcu_report_qs_rnp(mask, rsp, rnp, flags); /* rlses rnp->lock */
        }
@@ -1779,7 +1885,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
        long bl, count, count_lazy;
        int i;
 
-       /* If no callbacks are ready, just return.*/
+       /* If no callbacks are ready, just return. */
        if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
                trace_rcu_batch_start(rsp->name, rdp->qlen_lazy, rdp->qlen, 0);
                trace_rcu_batch_end(rsp->name, 0, !!ACCESS_ONCE(rdp->nxtlist),
@@ -2008,19 +2114,19 @@ __rcu_process_callbacks(struct rcu_state *rsp)
 
        WARN_ON_ONCE(rdp->beenonline == 0);
 
-       /*
-        * Advance callbacks in response to end of earlier grace
-        * period that some other CPU ended.
-        */
+       /* Handle the end of a grace period that some other CPU ended.  */
        rcu_process_gp_end(rsp, rdp);
 
        /* Update RCU state based on any recent quiescent states. */
        rcu_check_quiescent_state(rsp, rdp);
 
        /* Does this CPU require a not-yet-started grace period? */
+       local_irq_save(flags);
        if (cpu_needs_another_gp(rsp, rdp)) {
-               raw_spin_lock_irqsave(&rcu_get_root(rsp)->lock, flags);
+               raw_spin_lock(&rcu_get_root(rsp)->lock); /* irqs disabled. */
                rcu_start_gp(rsp, flags);  /* releases above lock */
+       } else {
+               local_irq_restore(flags);
        }
 
        /* If there are callbacks ready, invoke them. */
@@ -2719,9 +2825,6 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
        WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE);
        WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1);
-#ifdef CONFIG_RCU_USER_QS
-       WARN_ON_ONCE(rdp->dynticks->in_user);
-#endif
        rdp->cpu = cpu;
        rdp->rsp = rsp;
        rcu_boot_init_nocb_percpu_data(rdp);
@@ -2938,6 +3041,10 @@ static void __init rcu_init_one(struct rcu_state *rsp,
 
        BUILD_BUG_ON(MAX_RCU_LVLS > ARRAY_SIZE(buf));  /* Fix buf[] init! */
 
+       /* Silence gcc 4.8 warning about array index out of range. */
+       if (rcu_num_lvls > RCU_NUM_LVLS)
+               panic("rcu_init_one: rcu_num_lvls overflow");
+
        /* Initialize the level-tracking arrays. */
 
        for (i = 0; i < rcu_num_lvls; i++)
@@ -3074,7 +3181,6 @@ void __init rcu_init(void)
        cpu_notifier(rcu_cpu_notify, 0);
        for_each_online_cpu(cpu)
                rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
-       check_cpu_stall_init();
 }
 
 #include "rcutree_plugin.h"
index 4b69291b093d7157d638da01d342c2ee3d1f2d16..c896b5045d9dcb5c67665b4caf1d222e103d56ff 100644 (file)
@@ -102,10 +102,6 @@ struct rcu_dynticks {
                                    /* idle-period nonlazy_posted snapshot. */
        int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
-#ifdef CONFIG_RCU_USER_QS
-       bool ignore_user_qs;        /* Treat userspace as extended QS or not */
-       bool in_user;               /* Is the CPU in userland from RCU POV? */
-#endif
 };
 
 /* RCU's kthread states for tracing. */
@@ -282,6 +278,8 @@ struct rcu_data {
         */
        struct rcu_head *nxtlist;
        struct rcu_head **nxttail[RCU_NEXT_SIZE];
+       unsigned long   nxtcompleted[RCU_NEXT_SIZE];
+                                       /* grace periods for sublists. */
        long            qlen_lazy;      /* # of lazy queued callbacks */
        long            qlen;           /* # of queued callbacks, incl lazy */
        long            qlen_last_fqs_check;
@@ -343,11 +341,6 @@ struct rcu_data {
 
 #define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
 
-#ifdef CONFIG_PROVE_RCU
-#define RCU_STALL_DELAY_DELTA         (5 * HZ)
-#else
-#define RCU_STALL_DELAY_DELTA         0
-#endif
 #define RCU_STALL_RAT_DELAY            2       /* Allow other CPUs time */
                                                /*  to take at least one */
                                                /*  scheduling clock irq */
index f6e5ec2932b4aed0ff40016e8fdf77e5b9c1f366..c1cc7e17ff9d9dc29db596bca0468056bd3f0665 100644 (file)
@@ -40,8 +40,7 @@
 #ifdef CONFIG_RCU_NOCB_CPU
 static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
 static bool have_rcu_nocb_mask;            /* Was rcu_nocb_mask allocated? */
-static bool rcu_nocb_poll;         /* Offload kthread are to poll. */
-module_param(rcu_nocb_poll, bool, 0444);
+static bool __read_mostly rcu_nocb_poll;    /* Offload kthread are to poll. */
 static char __initdata nocb_buf[NR_CPUS * 5];
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
@@ -2159,6 +2158,13 @@ static int __init rcu_nocb_setup(char *str)
 }
 __setup("rcu_nocbs=", rcu_nocb_setup);
 
+static int __init parse_rcu_nocb_poll(char *arg)
+{
+       rcu_nocb_poll = 1;
+       return 0;
+}
+early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
+
 /* Is the specified CPU a no-CPUs CPU? */
 static bool is_nocb_cpu(int cpu)
 {
@@ -2366,10 +2372,11 @@ static int rcu_nocb_kthread(void *arg)
        for (;;) {
                /* If not polling, wait for next batch of callbacks. */
                if (!rcu_nocb_poll)
-                       wait_event(rdp->nocb_wq, rdp->nocb_head);
+                       wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
                list = ACCESS_ONCE(rdp->nocb_head);
                if (!list) {
                        schedule_timeout_interruptible(1);
+                       flush_signals(current);
                        continue;
                }
 
index 16502d3a71c8af4f726eb8ea3e5f9ea6e6e943c5..13b243a323fa0a5dfcfd965a0eb39f7d4e35fe45 100644 (file)
@@ -17,6 +17,7 @@
  * See rt.c in preempt-rt for proper credits and further information
  */
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
index 98ec494754608a18b93625bf54f53fb2e0617bf0..7890b10084a71e4deff2a1ed652c7011358fc3b4 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kthread.h>
 #include <linux/export.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
index a242e691c993038f35ace870d245487d44b5bc16..1e09308bf2a1e5f46c3f68d02bc4bcb346b42ec5 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/export.h>
 #include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include <linux/timer.h>
 
 #include "rtmutex_common.h"
index 6850f53e02d82e023954df56f5230b4033e80b73..b3c6c3fcd8474237a2e41ab4db87ee04c2435b7b 100644 (file)
@@ -116,6 +116,16 @@ void down_read_nested(struct rw_semaphore *sem, int subclass)
 
 EXPORT_SYMBOL(down_read_nested);
 
+void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
+{
+       might_sleep();
+       rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
+
+       LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
+}
+
+EXPORT_SYMBOL(_down_write_nest_lock);
+
 void down_write_nested(struct rw_semaphore *sem, int subclass)
 {
        might_sleep();
index 257002c13bb02acad92c74347e3b38ca3bc881b1..4a88f1d51563509986aff62244b863eb140b89c5 100644 (file)
@@ -1523,7 +1523,8 @@ out:
  */
 int wake_up_process(struct task_struct *p)
 {
-       return try_to_wake_up(p, TASK_ALL, 0);
+       WARN_ON(task_is_stopped_or_traced(p));
+       return try_to_wake_up(p, TASK_NORMAL, 0);
 }
 EXPORT_SYMBOL(wake_up_process);
 
@@ -4370,7 +4371,7 @@ bool __sched yield_to(struct task_struct *p, bool preempt)
        struct task_struct *curr = current;
        struct rq *rq, *p_rq;
        unsigned long flags;
-       bool yielded = 0;
+       int yielded = 0;
 
        local_irq_save(flags);
        rq = this_rq();
@@ -4666,6 +4667,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
         */
        idle->sched_class = &idle_sched_class;
        ftrace_graph_init_idle_task(idle, cpu);
+       vtime_init_idle(idle);
 #if defined(CONFIG_SMP)
        sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
 #endif
@@ -7507,6 +7509,25 @@ static int sched_rt_global_constraints(void)
 }
 #endif /* CONFIG_RT_GROUP_SCHED */
 
+int sched_rr_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos)
+{
+       int ret;
+       static DEFINE_MUTEX(mutex);
+
+       mutex_lock(&mutex);
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+       /* make sure that internally we keep jiffies */
+       /* also, writing zero resets timeslice to default */
+       if (!ret && write) {
+               sched_rr_timeslice = sched_rr_timeslice <= 0 ?
+                       RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice);
+       }
+       mutex_unlock(&mutex);
+       return ret;
+}
+
 int sched_rt_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)
index 23aa789c53ee5c6e061c6bf2b0f8181292695044..1095e878a46fdbe4a7224eb07a68cf1fc90c2530 100644 (file)
@@ -28,6 +28,8 @@
  */
 
 #include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
 #include "cpupri.h"
 
 /* Convert between a 140 based task->prio, and our 102 based cpupri */
index 293b202fcf79e1ba577d0672598ba59f4e8ebf56..9857329ed2804a6b3255bd402a73722b8ae33ecc 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/tsacct_kern.h>
 #include <linux/kernel_stat.h>
 #include <linux/static_key.h>
+#include <linux/context_tracking.h>
 #include "sched.h"
 
 
@@ -163,7 +164,7 @@ void account_user_time(struct task_struct *p, cputime_t cputime,
        task_group_account_field(p, index, (__force u64) cputime);
 
        /* Account for user time used */
-       acct_update_integrals(p);
+       acct_account_cputime(p);
 }
 
 /*
@@ -213,7 +214,7 @@ void __account_system_time(struct task_struct *p, cputime_t cputime,
        task_group_account_field(p, index, (__force u64) cputime);
 
        /* Account for system time used */
-       acct_update_integrals(p);
+       acct_account_cputime(p);
 }
 
 /*
@@ -295,6 +296,7 @@ static __always_inline bool steal_account_process_tick(void)
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
 {
        struct signal_struct *sig = tsk->signal;
+       cputime_t utime, stime;
        struct task_struct *t;
 
        times->utime = sig->utime;
@@ -308,16 +310,15 @@ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
 
        t = tsk;
        do {
-               times->utime += t->utime;
-               times->stime += t->stime;
+               task_cputime(tsk, &utime, &stime);
+               times->utime += utime;
+               times->stime += stime;
                times->sum_exec_runtime += task_sched_runtime(t);
        } while_each_thread(tsk, t);
 out:
        rcu_read_unlock();
 }
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
 /*
  * Account a tick to a process and cpustat
@@ -382,11 +383,12 @@ static void irqtime_account_idle_ticks(int ticks)
                irqtime_account_process_tick(current, 0, rq);
 }
 #else /* CONFIG_IRQ_TIME_ACCOUNTING */
-static void irqtime_account_idle_ticks(int ticks) {}
-static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
+static inline void irqtime_account_idle_ticks(int ticks) {}
+static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
                                                struct rq *rq) {}
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
 /*
  * Account a single tick of cpu time.
  * @p: the process that the cpu time gets accounted to
@@ -397,6 +399,9 @@ void account_process_tick(struct task_struct *p, int user_tick)
        cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
        struct rq *rq = this_rq();
 
+       if (vtime_accounting_enabled())
+               return;
+
        if (sched_clock_irqtime) {
                irqtime_account_process_tick(p, user_tick, rq);
                return;
@@ -438,8 +443,7 @@ void account_idle_ticks(unsigned long ticks)
 
        account_idle_time(jiffies_to_cputime(ticks));
 }
-
-#endif
+#endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 /*
  * Use precise platform statistics if available:
@@ -461,25 +465,20 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
        *st = cputime.stime;
 }
 
-void vtime_account_system_irqsafe(struct task_struct *tsk)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       vtime_account_system(tsk);
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL_GPL(vtime_account_system_irqsafe);
-
 #ifndef __ARCH_HAS_VTIME_TASK_SWITCH
 void vtime_task_switch(struct task_struct *prev)
 {
+       if (!vtime_accounting_enabled())
+               return;
+
        if (is_idle_task(prev))
                vtime_account_idle(prev);
        else
                vtime_account_system(prev);
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        vtime_account_user(prev);
+#endif
        arch_vtime_task_switch(prev);
 }
 #endif
@@ -493,27 +492,40 @@ void vtime_task_switch(struct task_struct *prev)
  * vtime_account().
  */
 #ifndef __ARCH_HAS_VTIME_ACCOUNT
-void vtime_account(struct task_struct *tsk)
+void vtime_account_irq_enter(struct task_struct *tsk)
 {
-       if (in_interrupt() || !is_idle_task(tsk))
-               vtime_account_system(tsk);
-       else
-               vtime_account_idle(tsk);
+       if (!vtime_accounting_enabled())
+               return;
+
+       if (!in_interrupt()) {
+               /*
+                * If we interrupted user, context_tracking_in_user()
+                * is 1 because the context tracking don't hook
+                * on irq entry/exit. This way we know if
+                * we need to flush user time on kernel entry.
+                */
+               if (context_tracking_in_user()) {
+                       vtime_account_user(tsk);
+                       return;
+               }
+
+               if (is_idle_task(tsk)) {
+                       vtime_account_idle(tsk);
+                       return;
+               }
+       }
+       vtime_account_system(tsk);
 }
-EXPORT_SYMBOL_GPL(vtime_account);
+EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
 #endif /* __ARCH_HAS_VTIME_ACCOUNT */
 
-#else
-
-#ifndef nsecs_to_cputime
-# define nsecs_to_cputime(__nsecs)     nsecs_to_jiffies(__nsecs)
-#endif
+#else /* !CONFIG_VIRT_CPU_ACCOUNTING */
 
-static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total)
+static cputime_t scale_stime(cputime_t stime, cputime_t rtime, cputime_t total)
 {
        u64 temp = (__force u64) rtime;
 
-       temp *= (__force u64) utime;
+       temp *= (__force u64) stime;
 
        if (sizeof(cputime_t) == 4)
                temp = div_u64(temp, (__force u32) total);
@@ -531,10 +543,10 @@ static void cputime_adjust(struct task_cputime *curr,
                           struct cputime *prev,
                           cputime_t *ut, cputime_t *st)
 {
-       cputime_t rtime, utime, total;
+       cputime_t rtime, stime, total;
 
-       utime = curr->utime;
-       total = utime + curr->stime;
+       stime = curr->stime;
+       total = stime + curr->utime;
 
        /*
         * Tick based cputime accounting depend on random scheduling
@@ -549,17 +561,17 @@ static void cputime_adjust(struct task_cputime *curr,
        rtime = nsecs_to_cputime(curr->sum_exec_runtime);
 
        if (total)
-               utime = scale_utime(utime, rtime, total);
+               stime = scale_stime(stime, rtime, total);
        else
-               utime = rtime;
+               stime = rtime;
 
        /*
         * If the tick based count grows faster than the scheduler one,
         * the result of the scaling may go backward.
         * Let's enforce monotonicity.
         */
-       prev->utime = max(prev->utime, utime);
-       prev->stime = max(prev->stime, rtime - prev->utime);
+       prev->stime = max(prev->stime, stime);
+       prev->utime = max(prev->utime, rtime - prev->stime);
 
        *ut = prev->utime;
        *st = prev->stime;
@@ -568,11 +580,10 @@ static void cputime_adjust(struct task_cputime *curr,
 void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
 {
        struct task_cputime cputime = {
-               .utime = p->utime,
-               .stime = p->stime,
                .sum_exec_runtime = p->se.sum_exec_runtime,
        };
 
+       task_cputime(p, &cputime.utime, &cputime.stime);
        cputime_adjust(&cputime, &p->prev_cputime, ut, st);
 }
 
@@ -586,4 +597,221 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
        thread_group_cputime(p, &cputime);
        cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
 }
-#endif
+#endif /* !CONFIG_VIRT_CPU_ACCOUNTING */
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
+static unsigned long long vtime_delta(struct task_struct *tsk)
+{
+       unsigned long long clock;
+
+       clock = sched_clock();
+       if (clock < tsk->vtime_snap)
+               return 0;
+
+       return clock - tsk->vtime_snap;
+}
+
+static cputime_t get_vtime_delta(struct task_struct *tsk)
+{
+       unsigned long long delta = vtime_delta(tsk);
+
+       WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_SLEEPING);
+       tsk->vtime_snap += delta;
+
+       /* CHECKME: always safe to convert nsecs to cputime? */
+       return nsecs_to_cputime(delta);
+}
+
+static void __vtime_account_system(struct task_struct *tsk)
+{
+       cputime_t delta_cpu = get_vtime_delta(tsk);
+
+       account_system_time(tsk, irq_count(), delta_cpu, cputime_to_scaled(delta_cpu));
+}
+
+void vtime_account_system(struct task_struct *tsk)
+{
+       if (!vtime_accounting_enabled())
+               return;
+
+       write_seqlock(&tsk->vtime_seqlock);
+       __vtime_account_system(tsk);
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_account_irq_exit(struct task_struct *tsk)
+{
+       if (!vtime_accounting_enabled())
+               return;
+
+       write_seqlock(&tsk->vtime_seqlock);
+       if (context_tracking_in_user())
+               tsk->vtime_snap_whence = VTIME_USER;
+       __vtime_account_system(tsk);
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_account_user(struct task_struct *tsk)
+{
+       cputime_t delta_cpu;
+
+       if (!vtime_accounting_enabled())
+               return;
+
+       delta_cpu = get_vtime_delta(tsk);
+
+       write_seqlock(&tsk->vtime_seqlock);
+       tsk->vtime_snap_whence = VTIME_SYS;
+       account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu));
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_user_enter(struct task_struct *tsk)
+{
+       if (!vtime_accounting_enabled())
+               return;
+
+       write_seqlock(&tsk->vtime_seqlock);
+       tsk->vtime_snap_whence = VTIME_USER;
+       __vtime_account_system(tsk);
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_guest_enter(struct task_struct *tsk)
+{
+       write_seqlock(&tsk->vtime_seqlock);
+       __vtime_account_system(tsk);
+       current->flags |= PF_VCPU;
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_guest_exit(struct task_struct *tsk)
+{
+       write_seqlock(&tsk->vtime_seqlock);
+       __vtime_account_system(tsk);
+       current->flags &= ~PF_VCPU;
+       write_sequnlock(&tsk->vtime_seqlock);
+}
+
+void vtime_account_idle(struct task_struct *tsk)
+{
+       cputime_t delta_cpu = get_vtime_delta(tsk);
+
+       account_idle_time(delta_cpu);
+}
+
+bool vtime_accounting_enabled(void)
+{
+       return context_tracking_active();
+}
+
+void arch_vtime_task_switch(struct task_struct *prev)
+{
+       write_seqlock(&prev->vtime_seqlock);
+       prev->vtime_snap_whence = VTIME_SLEEPING;
+       write_sequnlock(&prev->vtime_seqlock);
+
+       write_seqlock(&current->vtime_seqlock);
+       current->vtime_snap_whence = VTIME_SYS;
+       current->vtime_snap = sched_clock();
+       write_sequnlock(&current->vtime_seqlock);
+}
+
+void vtime_init_idle(struct task_struct *t)
+{
+       unsigned long flags;
+
+       write_seqlock_irqsave(&t->vtime_seqlock, flags);
+       t->vtime_snap_whence = VTIME_SYS;
+       t->vtime_snap = sched_clock();
+       write_sequnlock_irqrestore(&t->vtime_seqlock, flags);
+}
+
+cputime_t task_gtime(struct task_struct *t)
+{
+       unsigned int seq;
+       cputime_t gtime;
+
+       do {
+               seq = read_seqbegin(&t->vtime_seqlock);
+
+               gtime = t->gtime;
+               if (t->flags & PF_VCPU)
+                       gtime += vtime_delta(t);
+
+       } while (read_seqretry(&t->vtime_seqlock, seq));
+
+       return gtime;
+}
+
+/*
+ * Fetch cputime raw values from fields of task_struct and
+ * add up the pending nohz execution time since the last
+ * cputime snapshot.
+ */
+static void
+fetch_task_cputime(struct task_struct *t,
+                  cputime_t *u_dst, cputime_t *s_dst,
+                  cputime_t *u_src, cputime_t *s_src,
+                  cputime_t *udelta, cputime_t *sdelta)
+{
+       unsigned int seq;
+       unsigned long long delta;
+
+       do {
+               *udelta = 0;
+               *sdelta = 0;
+
+               seq = read_seqbegin(&t->vtime_seqlock);
+
+               if (u_dst)
+                       *u_dst = *u_src;
+               if (s_dst)
+                       *s_dst = *s_src;
+
+               /* Task is sleeping, nothing to add */
+               if (t->vtime_snap_whence == VTIME_SLEEPING ||
+                   is_idle_task(t))
+                       continue;
+
+               delta = vtime_delta(t);
+
+               /*
+                * Task runs either in user or kernel space, add pending nohz time to
+                * the right place.
+                */
+               if (t->vtime_snap_whence == VTIME_USER || t->flags & PF_VCPU) {
+                       *udelta = delta;
+               } else {
+                       if (t->vtime_snap_whence == VTIME_SYS)
+                               *sdelta = delta;
+               }
+       } while (read_seqretry(&t->vtime_seqlock, seq));
+}
+
+
+void task_cputime(struct task_struct *t, cputime_t *utime, cputime_t *stime)
+{
+       cputime_t udelta, sdelta;
+
+       fetch_task_cputime(t, utime, stime, &t->utime,
+                          &t->stime, &udelta, &sdelta);
+       if (utime)
+               *utime += udelta;
+       if (stime)
+               *stime += sdelta;
+}
+
+void task_cputime_scaled(struct task_struct *t,
+                        cputime_t *utimescaled, cputime_t *stimescaled)
+{
+       cputime_t udelta, sdelta;
+
+       fetch_task_cputime(t, utimescaled, stimescaled,
+                          &t->utimescaled, &t->stimescaled, &udelta, &sdelta);
+       if (utimescaled)
+               *utimescaled += cputime_to_scaled(udelta);
+       if (stimescaled)
+               *stimescaled += cputime_to_scaled(sdelta);
+}
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
index 2cd3c1b4e582857eefb87fa9a98fb9cad11509a6..7ae4c4c5420e65b4aea1625d37a8a28b663072fb 100644 (file)
@@ -222,8 +222,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
                        cfs_rq->runnable_load_avg);
        SEQ_printf(m, "  .%-30s: %lld\n", "blocked_load_avg",
                        cfs_rq->blocked_load_avg);
-       SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_avg",
-                       atomic64_read(&cfs_rq->tg->load_avg));
+       SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_avg",
+                       (unsigned long long)atomic64_read(&cfs_rq->tg->load_avg));
        SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_contrib",
                        cfs_rq->tg_load_contrib);
        SEQ_printf(m, "  .%-30s: %d\n", "tg_runnable_contrib",
index 5eea8707234a15167eeaabbc5881f04cf0345ca1..7a33e5986fc522e8860a712a234b39774ee80938 100644 (file)
@@ -1680,9 +1680,7 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
        }
 
        /* ensure we never gain time by being placed backwards. */
-       vruntime = max_vruntime(se->vruntime, vruntime);
-
-       se->vruntime = vruntime;
+       se->vruntime = max_vruntime(se->vruntime, vruntime);
 }
 
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq);
@@ -2663,7 +2661,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
        hrtimer_cancel(&cfs_b->slack_timer);
 }
 
-static void unthrottle_offline_cfs_rqs(struct rq *rq)
+static void __maybe_unused unthrottle_offline_cfs_rqs(struct rq *rq)
 {
        struct cfs_rq *cfs_rq;
 
@@ -3254,25 +3252,18 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
  */
 static int select_idle_sibling(struct task_struct *p, int target)
 {
-       int cpu = smp_processor_id();
-       int prev_cpu = task_cpu(p);
        struct sched_domain *sd;
        struct sched_group *sg;
-       int i;
+       int i = task_cpu(p);
 
-       /*
-        * If the task is going to be woken-up on this cpu and if it is
-        * already idle, then it is the right target.
-        */
-       if (target == cpu && idle_cpu(cpu))
-               return cpu;
+       if (idle_cpu(target))
+               return target;
 
        /*
-        * If the task is going to be woken-up on the cpu where it previously
-        * ran and if it is currently idle, then it the right target.
+        * If the prevous cpu is cache affine and idle, don't be stupid.
         */
-       if (target == prev_cpu && idle_cpu(prev_cpu))
-               return prev_cpu;
+       if (i != target && cpus_share_cache(i, target) && idle_cpu(i))
+               return i;
 
        /*
         * Otherwise, iterate the domains and find an elegible idle cpu.
@@ -3286,7 +3277,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
                                goto next;
 
                        for_each_cpu(i, sched_group_cpus(sg)) {
-                               if (!idle_cpu(i))
+                               if (i == target || !idle_cpu(i))
                                        goto next;
                        }
 
@@ -6101,7 +6092,7 @@ static unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task
         * idle runqueue:
         */
        if (rq->cfs.load.weight)
-               rr_interval = NS_TO_JIFFIES(sched_slice(&rq->cfs, se));
+               rr_interval = NS_TO_JIFFIES(sched_slice(cfs_rq_of(se), se));
 
        return rr_interval;
 }
index 418feb01344edb7e59f11643e153e2f1866cc4ed..127a2c4cf4ab4f176bbf554be2ad34f4d597c258 100644 (file)
@@ -7,6 +7,8 @@
 
 #include <linux/slab.h>
 
+int sched_rr_timeslice = RR_TIMESLICE;
+
 static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
 
 struct rt_bandwidth def_rt_bandwidth;
@@ -566,7 +568,7 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
 static int do_balance_runtime(struct rt_rq *rt_rq)
 {
        struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
-       struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
+       struct root_domain *rd = rq_of_rt_rq(rt_rq)->rd;
        int i, weight, more = 0;
        u64 rt_period;
 
@@ -925,8 +927,8 @@ static void update_curr_rt(struct rq *rq)
                return;
 
        delta_exec = rq->clock_task - curr->se.exec_start;
-       if (unlikely((s64)delta_exec < 0))
-               delta_exec = 0;
+       if (unlikely((s64)delta_exec <= 0))
+               return;
 
        schedstat_set(curr->se.statistics.exec_max,
                      max(curr->se.statistics.exec_max, delta_exec));
@@ -1427,8 +1429,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
 static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu)
 {
        if (!task_running(rq, p) &&
-           (cpu < 0 || cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) &&
-           (p->nr_cpus_allowed > 1))
+           cpumask_test_cpu(cpu, tsk_cpus_allowed(p)))
                return 1;
        return 0;
 }
@@ -1889,8 +1890,11 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p)
         * we may need to handle the pulling of RT tasks
         * now.
         */
-       if (p->on_rq && !rq->rt.rt_nr_running)
-               pull_rt_task(rq);
+       if (!p->on_rq || rq->rt.rt_nr_running)
+               return;
+
+       if (pull_rt_task(rq))
+               resched_task(rq->curr);
 }
 
 void init_sched_rt_class(void)
@@ -1985,7 +1989,11 @@ static void watchdog(struct rq *rq, struct task_struct *p)
        if (soft != RLIM_INFINITY) {
                unsigned long next;
 
-               p->rt.timeout++;
+               if (p->rt.watchdog_stamp != jiffies) {
+                       p->rt.timeout++;
+                       p->rt.watchdog_stamp = jiffies;
+               }
+
                next = DIV_ROUND_UP(min(soft, hard), USEC_PER_SEC/HZ);
                if (p->rt.timeout > next)
                        p->cputime_expires.sched_exp = p->se.sum_exec_runtime;
@@ -2010,7 +2018,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
        if (--p->rt.time_slice)
                return;
 
-       p->rt.time_slice = RR_TIMESLICE;
+       p->rt.time_slice = sched_rr_timeslice;
 
        /*
         * Requeue to the end of queue if we (and all of our ancestors) are the
@@ -2041,7 +2049,7 @@ static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
         * Time slice is 0 for SCHED_FIFO tasks
         */
        if (task->policy == SCHED_RR)
-               return RR_TIMESLICE;
+               return sched_rr_timeslice;
        else
                return 0;
 }
index fc886441436ac29ec87cc95211e03ed32ec77e83..cc03cfdf469f6af1bda58d936539c9348b7e9501 100644 (file)
@@ -1,5 +1,7 @@
 
 #include <linux/sched.h>
+#include <linux/sched/sysctl.h>
+#include <linux/sched/rt.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
index 580a91e634710b6dbbc75f328c3bbef549b999cb..7f82adbad4800a08a5ca5e1836da455de555856a 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/nsproxy.h>
 #include <linux/user_namespace.h>
 #include <linux/uprobes.h>
+#include <linux/compat.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
 
@@ -679,23 +680,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
  * No need to set need_resched since signal event passing
  * goes through ->blocked
  */
-void signal_wake_up(struct task_struct *t, int resume)
+void signal_wake_up_state(struct task_struct *t, unsigned int state)
 {
-       unsigned int mask;
-
        set_tsk_thread_flag(t, TIF_SIGPENDING);
-
        /*
-        * For SIGKILL, we want to wake it up in the stopped/traced/killable
+        * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
         * case. We don't check t->state here because there is a race with it
         * executing another processor and just now entering stopped state.
         * By using wake_up_state, we ensure the process will wake up and
         * handle its death signal.
         */
-       mask = TASK_INTERRUPTIBLE;
-       if (resume)
-               mask |= TASK_WAKEKILL;
-       if (!wake_up_state(t, mask))
+       if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
                kick_process(t);
 }
 
@@ -843,7 +838,7 @@ static void ptrace_trap_notify(struct task_struct *t)
        assert_spin_locked(&t->sighand->siglock);
 
        task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY);
-       signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
+       ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
 }
 
 /*
@@ -1637,6 +1632,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
        unsigned long flags;
        struct sighand_struct *psig;
        bool autoreap = false;
+       cputime_t utime, stime;
 
        BUG_ON(sig == -1);
 
@@ -1674,8 +1670,9 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
                                       task_uid(tsk));
        rcu_read_unlock();
 
-       info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime);
-       info.si_stime = cputime_to_clock_t(tsk->stime + tsk->signal->stime);
+       task_cputime(tsk, &utime, &stime);
+       info.si_utime = cputime_to_clock_t(utime + tsk->signal->utime);
+       info.si_stime = cputime_to_clock_t(stime + tsk->signal->stime);
 
        info.si_status = tsk->exit_code & 0x7f;
        if (tsk->exit_code & 0x80)
@@ -1739,6 +1736,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
        unsigned long flags;
        struct task_struct *parent;
        struct sighand_struct *sighand;
+       cputime_t utime, stime;
 
        if (for_ptracer) {
                parent = tsk->parent;
@@ -1757,8 +1755,9 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
        info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk));
        rcu_read_unlock();
 
-       info.si_utime = cputime_to_clock_t(tsk->utime);
-       info.si_stime = cputime_to_clock_t(tsk->stime);
+       task_cputime(tsk, &utime, &stime);
+       info.si_utime = cputime_to_clock_t(utime);
+       info.si_stime = cputime_to_clock_t(stime);
 
        info.si_code = why;
        switch (why) {
@@ -1799,6 +1798,10 @@ static inline int may_ptrace_stop(void)
         * If SIGKILL was already sent before the caller unlocked
         * ->siglock we must see ->core_state != NULL. Otherwise it
         * is safe to enter schedule().
+        *
+        * This is almost outdated, a task with the pending SIGKILL can't
+        * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported
+        * after SIGKILL was already dequeued.
         */
        if (unlikely(current->mm->core_state) &&
            unlikely(current->mm == current->parent->mm))
@@ -1924,6 +1927,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
                if (gstop_done)
                        do_notify_parent_cldstop(current, false, why);
 
+               /* tasklist protects us from ptrace_freeze_traced() */
                __set_current_state(TASK_RUNNING);
                if (clear_code)
                        current->exit_code = 0;
@@ -2527,11 +2531,8 @@ static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset)
  */
 void set_current_blocked(sigset_t *newset)
 {
-       struct task_struct *tsk = current;
        sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP));
-       spin_lock_irq(&tsk->sighand->siglock);
-       __set_task_blocked(tsk, newset);
-       spin_unlock_irq(&tsk->sighand->siglock);
+       __set_current_blocked(newset);
 }
 
 void __set_current_blocked(const sigset_t *newset)
@@ -3094,6 +3095,80 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
 out:
        return error;
 }
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss)
+{
+       return do_sigaltstack(uss, uoss, current_user_stack_pointer());
+}
+#endif
+
+int restore_altstack(const stack_t __user *uss)
+{
+       int err = do_sigaltstack(uss, NULL, current_user_stack_pointer());
+       /* squash all but EFAULT for now */
+       return err == -EFAULT ? err : 0;
+}
+
+int __save_altstack(stack_t __user *uss, unsigned long sp)
+{
+       struct task_struct *t = current;
+       return  __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) |
+               __put_user(sas_ss_flags(sp), &uss->ss_flags) |
+               __put_user(t->sas_ss_size, &uss->ss_size);
+}
+
+#ifdef CONFIG_COMPAT
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+COMPAT_SYSCALL_DEFINE2(sigaltstack,
+                       const compat_stack_t __user *, uss_ptr,
+                       compat_stack_t __user *, uoss_ptr)
+{
+       stack_t uss, uoss;
+       int ret;
+       mm_segment_t seg;
+
+       if (uss_ptr) {
+               compat_stack_t uss32;
+
+               memset(&uss, 0, sizeof(stack_t));
+               if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
+                       return -EFAULT;
+               uss.ss_sp = compat_ptr(uss32.ss_sp);
+               uss.ss_flags = uss32.ss_flags;
+               uss.ss_size = uss32.ss_size;
+       }
+       seg = get_fs();
+       set_fs(KERNEL_DS);
+       ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
+                            (stack_t __force __user *) &uoss,
+                            compat_user_stack_pointer());
+       set_fs(seg);
+       if (ret >= 0 && uoss_ptr)  {
+               if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
+                   __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
+                   __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
+                   __put_user(uoss.ss_size, &uoss_ptr->ss_size))
+                       ret = -EFAULT;
+       }
+       return ret;
+}
+
+int compat_restore_altstack(const compat_stack_t __user *uss)
+{
+       int err = compat_sys_sigaltstack(uss, NULL);
+       /* squash all but -EFAULT for now */
+       return err == -EFAULT ? err : 0;
+}
+
+int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
+{
+       struct task_struct *t = current;
+       return  __put_user(ptr_to_compat((void __user *)t->sas_ss_sp), &uss->ss_sp) |
+               __put_user(sas_ss_flags(sp), &uss->ss_flags) |
+               __put_user(t->sas_ss_size, &uss->ss_size);
+}
+#endif
+#endif
 
 #ifdef __ARCH_WANT_SYS_SIGPENDING
 
@@ -3130,7 +3205,6 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
        if (nset) {
                if (copy_from_user(&new_set, nset, sizeof(*nset)))
                        return -EFAULT;
-               new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
 
                new_blocked = current->blocked;
 
@@ -3148,7 +3222,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
                        return -EINVAL;
                }
 
-               __set_current_blocked(&new_blocked);
+               set_current_blocked(&new_blocked);
        }
 
        if (oset) {
@@ -3212,6 +3286,7 @@ SYSCALL_DEFINE1(ssetmask, int, newmask)
        int old = current->blocked.sig[0];
        sigset_t newset;
 
+       siginitset(&newset, newmask);
        set_current_blocked(&newset);
 
        return old;
index 29dd40a9f2f403ab86f39c96ddb505851b1d36c2..69f38bd98b423a53ada73c7a6b7a2217e91a77b4 100644 (file)
@@ -33,6 +33,7 @@ struct call_function_data {
        struct call_single_data csd;
        atomic_t                refs;
        cpumask_var_t           cpumask;
+       cpumask_var_t           cpumask_ipi;
 };
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
@@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
                if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
                                cpu_to_node(cpu)))
                        return notifier_from_errno(-ENOMEM);
+               if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
+                               cpu_to_node(cpu)))
+                       return notifier_from_errno(-ENOMEM);
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
                free_cpumask_var(cfd->cpumask);
+               free_cpumask_var(cfd->cpumask_ipi);
                break;
 #endif
        };
@@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask,
                return;
        }
 
+       /*
+        * After we put an entry into the list, data->cpumask
+        * may be cleared again when another CPU sends another IPI for
+        * a SMP function call, so data->cpumask will be zero.
+        */
+       cpumask_copy(data->cpumask_ipi, data->cpumask);
        raw_spin_lock_irqsave(&call_function.lock, flags);
        /*
         * Place entry at the _HEAD_ of the list, so that any cpu still
@@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask,
        smp_mb();
 
        /* Send a message to all CPUs in the map */
-       arch_send_call_function_ipi_mask(data->cpumask);
+       arch_send_call_function_ipi_mask(data->cpumask_ipi);
 
        /* Optionally wait for the CPUs to complete */
        if (wait)
index d6c5fc0542428dae4fffc7546e06b0f6dd4ac4f5..d4abac261779e037b2396b80f5b4fe3ec6efad71 100644 (file)
@@ -183,9 +183,10 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
                kfree(td);
                return PTR_ERR(tsk);
        }
-
        get_task_struct(tsk);
        *per_cpu_ptr(ht->store, cpu) = tsk;
+       if (ht->create)
+               ht->create(cpu);
        return 0;
 }
 
@@ -225,7 +226,7 @@ static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
 {
        struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
 
-       if (tsk)
+       if (tsk && !ht->selfparking)
                kthread_park(tsk);
 }
 
index ed567babe789c10ef48a2db7b63e17e0a2192d65..f5cc25f147a646e210384d1cb98ae4a97240b3a7 100644 (file)
@@ -221,7 +221,7 @@ asmlinkage void __do_softirq(void)
        current->flags &= ~PF_MEMALLOC;
 
        pending = local_softirq_pending();
-       vtime_account_irq_enter(current);
+       account_irq_enter_time(current);
 
        __local_bh_disable((unsigned long)__builtin_return_address(0),
                                SOFTIRQ_OFFSET);
@@ -272,7 +272,7 @@ restart:
 
        lockdep_softirq_exit();
 
-       vtime_account_irq_exit(current);
+       account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
@@ -341,7 +341,7 @@ static inline void invoke_softirq(void)
  */
 void irq_exit(void)
 {
-       vtime_account_irq_exit(current);
+       account_irq_exit_time(current);
        trace_hardirq_exit();
        sub_preempt_count(IRQ_EXIT_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
index 2b859828cdc327d811627fbf877318de8dbc5595..01d5ccb8bfe3d96cf3cba70d217a8bddf0ff5f8a 100644 (file)
@@ -282,12 +282,8 @@ static int srcu_readers_active(struct srcu_struct *sp)
  */
 void cleanup_srcu_struct(struct srcu_struct *sp)
 {
-       int sum;
-
-       sum = srcu_readers_active(sp);
-       WARN_ON(sum);  /* Leakage unless caller handles error. */
-       if (sum != 0)
-               return;
+       if (WARN_ON(srcu_readers_active(sp)))
+               return; /* Leakage unless caller handles error. */
        free_percpu(sp->per_cpu_ref);
        sp->per_cpu_ref = NULL;
 }
@@ -302,9 +298,8 @@ int __srcu_read_lock(struct srcu_struct *sp)
 {
        int idx;
 
+       idx = ACCESS_ONCE(sp->completed) & 0x1;
        preempt_disable();
-       idx = rcu_dereference_index_check(sp->completed,
-                                         rcu_read_lock_sched_held()) & 0x1;
        ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) += 1;
        smp_mb(); /* B */  /* Avoid leaking the critical section. */
        ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->seq[idx]) += 1;
@@ -321,10 +316,8 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
  */
 void __srcu_read_unlock(struct srcu_struct *sp, int idx)
 {
-       preempt_disable();
        smp_mb(); /* C */  /* Avoid leaking the critical section. */
-       ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) -= 1;
-       preempt_enable();
+       this_cpu_dec(sp->per_cpu_ref->c[idx]);
 }
 EXPORT_SYMBOL_GPL(__srcu_read_unlock);
 
@@ -423,6 +416,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
                           !lock_is_held(&rcu_sched_lock_map),
                           "Illegal synchronize_srcu() in same-type SRCU (or RCU) read-side critical section");
 
+       might_sleep();
        init_completion(&rcu.completion);
 
        head->next = NULL;
@@ -455,10 +449,12 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
  * synchronize_srcu - wait for prior SRCU read-side critical-section completion
  * @sp: srcu_struct with which to synchronize.
  *
- * Flip the completed counter, and wait for the old count to drain to zero.
- * As with classic RCU, the updater must use some separate means of
- * synchronizing concurrent updates.  Can block; must be called from
- * process context.
+ * Wait for the count to drain to zero of both indexes. To avoid the
+ * possible starvation of synchronize_srcu(), it waits for the count of
+ * the index=((->completed & 1) ^ 1) to drain to zero at first,
+ * and then flip the completed and wait for the count of the other index.
+ *
+ * Can block; must be called from process context.
  *
  * Note that it is illegal to call synchronize_srcu() from the corresponding
  * SRCU read-side critical section; doing so will result in deadlock.
@@ -480,12 +476,11 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);
  * Wait for an SRCU grace period to elapse, but be more aggressive about
  * spinning rather than blocking when waiting.
  *
- * Note that it is illegal to call this function while holding any lock
- * that is acquired by a CPU-hotplug notifier.  It is also illegal to call
- * synchronize_srcu_expedited() from the corresponding SRCU read-side
- * critical section; doing so will result in deadlock.  However, it is
- * perfectly legal to call synchronize_srcu_expedited() on one srcu_struct
- * from some other srcu_struct's read-side critical section, as long as
+ * Note that it is also illegal to call synchronize_srcu_expedited()
+ * from the corresponding SRCU read-side critical section;
+ * doing so will result in deadlock.  However, it is perfectly legal
+ * to call synchronize_srcu_expedited() on one srcu_struct from some
+ * other srcu_struct's read-side critical section, as long as
  * the resulting graph of srcu_structs is acyclic.
  */
 void synchronize_srcu_expedited(struct srcu_struct *sp)
index 2f194e965715183786f2f8b640ddcbbf1b456dc4..95d178c62d5a8537c18fa2d6f1d947aed1a93448 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/stop_machine.h>
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
-
+#include <linux/smpboot.h>
 #include <linux/atomic.h>
 
 /*
@@ -37,10 +37,10 @@ struct cpu_stopper {
        spinlock_t              lock;
        bool                    enabled;        /* is this stopper enabled? */
        struct list_head        works;          /* list of pending works */
-       struct task_struct      *thread;        /* stopper thread */
 };
 
 static DEFINE_PER_CPU(struct cpu_stopper, cpu_stopper);
+static DEFINE_PER_CPU(struct task_struct *, cpu_stopper_task);
 static bool stop_machine_initialized = false;
 
 static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
@@ -62,16 +62,18 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed)
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
-static void cpu_stop_queue_work(struct cpu_stopper *stopper,
-                               struct cpu_stop_work *work)
+static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
+       struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
+       struct task_struct *p = per_cpu(cpu_stopper_task, cpu);
+
        unsigned long flags;
 
        spin_lock_irqsave(&stopper->lock, flags);
 
        if (stopper->enabled) {
                list_add_tail(&work->list, &stopper->works);
-               wake_up_process(stopper->thread);
+               wake_up_process(p);
        } else
                cpu_stop_signal_done(work->done, false);
 
@@ -108,7 +110,7 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
        struct cpu_stop_work work = { .fn = fn, .arg = arg, .done = &done };
 
        cpu_stop_init_done(&done, 1);
-       cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), &work);
+       cpu_stop_queue_work(cpu, &work);
        wait_for_completion(&done.completion);
        return done.executed ? done.ret : -ENOENT;
 }
@@ -130,7 +132,7 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
                        struct cpu_stop_work *work_buf)
 {
        *work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, };
-       cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf);
+       cpu_stop_queue_work(cpu, work_buf);
 }
 
 /* static data for stop_cpus */
@@ -159,8 +161,7 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask,
         */
        preempt_disable();
        for_each_cpu(cpu, cpumask)
-               cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu),
-                                   &per_cpu(stop_cpus_work, cpu));
+               cpu_stop_queue_work(cpu, &per_cpu(stop_cpus_work, cpu));
        preempt_enable();
 }
 
@@ -244,20 +245,25 @@ int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
        return ret;
 }
 
-static int cpu_stopper_thread(void *data)
+static int cpu_stop_should_run(unsigned int cpu)
+{
+       struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
+       unsigned long flags;
+       int run;
+
+       spin_lock_irqsave(&stopper->lock, flags);
+       run = !list_empty(&stopper->works);
+       spin_unlock_irqrestore(&stopper->lock, flags);
+       return run;
+}
+
+static void cpu_stopper_thread(unsigned int cpu)
 {
-       struct cpu_stopper *stopper = data;
+       struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
        struct cpu_stop_work *work;
        int ret;
 
 repeat:
-       set_current_state(TASK_INTERRUPTIBLE);  /* mb paired w/ kthread_stop */
-
-       if (kthread_should_stop()) {
-               __set_current_state(TASK_RUNNING);
-               return 0;
-       }
-
        work = NULL;
        spin_lock_irq(&stopper->lock);
        if (!list_empty(&stopper->works)) {
@@ -273,8 +279,6 @@ repeat:
                struct cpu_stop_done *done = work->done;
                char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
 
-               __set_current_state(TASK_RUNNING);
-
                /* cpu stop callbacks are not allowed to sleep */
                preempt_disable();
 
@@ -290,88 +294,55 @@ repeat:
                                          ksym_buf), arg);
 
                cpu_stop_signal_done(done, true);
-       } else
-               schedule();
-
-       goto repeat;
+               goto repeat;
+       }
 }
 
 extern void sched_set_stop_task(int cpu, struct task_struct *stop);
 
-/* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */
-static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
-                                          unsigned long action, void *hcpu)
+static void cpu_stop_create(unsigned int cpu)
+{
+       sched_set_stop_task(cpu, per_cpu(cpu_stopper_task, cpu));
+}
+
+static void cpu_stop_park(unsigned int cpu)
 {
-       unsigned int cpu = (unsigned long)hcpu;
        struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
-       struct task_struct *p;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               BUG_ON(stopper->thread || stopper->enabled ||
-                      !list_empty(&stopper->works));
-               p = kthread_create_on_node(cpu_stopper_thread,
-                                          stopper,
-                                          cpu_to_node(cpu),
-                                          "migration/%d", cpu);
-               if (IS_ERR(p))
-                       return notifier_from_errno(PTR_ERR(p));
-               get_task_struct(p);
-               kthread_bind(p, cpu);
-               sched_set_stop_task(cpu, p);
-               stopper->thread = p;
-               break;
-
-       case CPU_ONLINE:
-               /* strictly unnecessary, as first user will wake it */
-               wake_up_process(stopper->thread);
-               /* mark enabled */
-               spin_lock_irq(&stopper->lock);
-               stopper->enabled = true;
-               spin_unlock_irq(&stopper->lock);
-               break;
-
-#ifdef CONFIG_HOTPLUG_CPU
-       case CPU_UP_CANCELED:
-       case CPU_POST_DEAD:
-       {
-               struct cpu_stop_work *work;
-
-               sched_set_stop_task(cpu, NULL);
-               /* kill the stopper */
-               kthread_stop(stopper->thread);
-               /* drain remaining works */
-               spin_lock_irq(&stopper->lock);
-               list_for_each_entry(work, &stopper->works, list)
-                       cpu_stop_signal_done(work->done, false);
-               stopper->enabled = false;
-               spin_unlock_irq(&stopper->lock);
-               /* release the stopper */
-               put_task_struct(stopper->thread);
-               stopper->thread = NULL;
-               break;
-       }
-#endif
-       }
+       struct cpu_stop_work *work;
+       unsigned long flags;
 
-       return NOTIFY_OK;
+       /* drain remaining works */
+       spin_lock_irqsave(&stopper->lock, flags);
+       list_for_each_entry(work, &stopper->works, list)
+               cpu_stop_signal_done(work->done, false);
+       stopper->enabled = false;
+       spin_unlock_irqrestore(&stopper->lock, flags);
 }
 
-/*
- * Give it a higher priority so that cpu stopper is available to other
- * cpu notifiers.  It currently shares the same priority as sched
- * migration_notifier.
- */
-static struct notifier_block __cpuinitdata cpu_stop_cpu_notifier = {
-       .notifier_call  = cpu_stop_cpu_callback,
-       .priority       = 10,
+static void cpu_stop_unpark(unsigned int cpu)
+{
+       struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
+
+       spin_lock_irq(&stopper->lock);
+       stopper->enabled = true;
+       spin_unlock_irq(&stopper->lock);
+}
+
+static struct smp_hotplug_thread cpu_stop_threads = {
+       .store                  = &cpu_stopper_task,
+       .thread_should_run      = cpu_stop_should_run,
+       .thread_fn              = cpu_stopper_thread,
+       .thread_comm            = "migration/%u",
+       .create                 = cpu_stop_create,
+       .setup                  = cpu_stop_unpark,
+       .park                   = cpu_stop_park,
+       .unpark                 = cpu_stop_unpark,
+       .selfparking            = true,
 };
 
 static int __init cpu_stop_init(void)
 {
-       void *bcpu = (void *)(long)smp_processor_id();
        unsigned int cpu;
-       int err;
 
        for_each_possible_cpu(cpu) {
                struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
@@ -380,15 +351,8 @@ static int __init cpu_stop_init(void)
                INIT_LIST_HEAD(&stopper->works);
        }
 
-       /* start one for the boot cpu */
-       err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE,
-                                   bcpu);
-       BUG_ON(err != NOTIFY_OK);
-       cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu);
-       register_cpu_notifier(&cpu_stop_cpu_notifier);
-
+       BUG_ON(smpboot_register_percpu_thread(&cpu_stop_threads));
        stop_machine_initialized = true;
-
        return 0;
 }
 early_initcall(cpu_stop_init);
index c88878db491e44bd2b5a5ea7f381fc7242187727..4fc9be955c712ca4b68c25b18d1ac9599df2a3ae 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/kmod.h>
 #include <linux/capability.h>
 #include <linux/binfmts.h>
+#include <linux/sched/sysctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -403,6 +404,13 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = sched_rt_handler,
        },
+       {
+               .procname       = "sched_rr_timeslice_ms",
+               .data           = &sched_rr_timeslice,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = sched_rr_handler,
+       },
 #ifdef CONFIG_SCHED_AUTOGROUP
        {
                .procname       = "sched_autogroup_enabled",
index d226c6a3fd28933d02edd485a9c8353db2212c02..c2a27dd93142545369abefa1d2ee2a41a5eb8f09 100644 (file)
@@ -114,6 +114,12 @@ SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
        return 0;
 }
 
+/*
+ * Indicates if there is an offset between the system clock and the hardware
+ * clock/persistent clock/rtc.
+ */
+int persistent_clock_is_local;
+
 /*
  * Adjust the time obtained from the CMOS to be UTC time instead of
  * local time.
@@ -135,6 +141,8 @@ static inline void warp_clock(void)
        struct timespec adjust;
 
        adjust = current_kernel_time();
+       if (sys_tz.tz_minuteswest != 0)
+               persistent_clock_is_local = 1;
        adjust.tv_sec += sys_tz.tz_minuteswest * 60;
        do_settimeofday(&adjust);
 }
index 8601f0db12612a1e18a3a11968b9444630f94ad5..24510d84efd760b287f532727dfc20f0d8e57405 100644 (file)
@@ -12,6 +12,11 @@ config CLOCKSOURCE_WATCHDOG
 config ARCH_CLOCKSOURCE_DATA
        bool
 
+# Platforms has a persistent clock
+config ALWAYS_USE_PERSISTENT_CLOCK
+       bool
+       default n
+
 # Timekeeping vsyscall support
 config GENERIC_TIME_VSYSCALL
        bool
@@ -38,6 +43,10 @@ config GENERIC_CLOCKEVENTS_BUILD
        default y
        depends on GENERIC_CLOCKEVENTS
 
+# Architecture can handle broadcast in a driver-agnostic way
+config ARCH_HAS_TICK_BROADCAST
+       bool
+
 # Clockevents broadcasting infrastructure
 config GENERIC_CLOCKEVENTS_BROADCAST
        bool
index 24174b4d669b1280c632d4ed0126dc2f1bb297ef..b10a42bb0165a40a9398fd639a2da2dc0c5acd4e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/rtc.h>
 
 #include "tick-internal.h"
 
@@ -483,8 +484,7 @@ out:
        return leap;
 }
 
-#ifdef CONFIG_GENERIC_CMOS_UPDATE
-
+#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
 static void sync_cmos_clock(struct work_struct *work);
 
 static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
@@ -510,14 +510,26 @@ static void sync_cmos_clock(struct work_struct *work)
        }
 
        getnstimeofday(&now);
-       if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
-               fail = update_persistent_clock(now);
+       if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) {
+               struct timespec adjust = now;
+
+               fail = -ENODEV;
+               if (persistent_clock_is_local)
+                       adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
+               fail = update_persistent_clock(adjust);
+#endif
+#ifdef CONFIG_RTC_SYSTOHC
+               if (fail == -ENODEV)
+                       fail = rtc_set_ntp_time(adjust);
+#endif
+       }
 
        next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
        if (next.tv_nsec <= 0)
                next.tv_nsec += NSEC_PER_SEC;
 
-       if (!fail)
+       if (!fail || fail == -ENODEV)
                next.tv_sec = 659;
        else
                next.tv_sec = 0;
index f113755695e2351ad9f32b7e38a808e98c0ad5f4..2fb8cb88df8d0296e655f320bc7d5cbce1a858c8 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 
 #include "tick-internal.h"
 
@@ -86,6 +87,22 @@ int tick_is_broadcast_device(struct clock_event_device *dev)
        return (dev && tick_broadcast_device.evtdev == dev);
 }
 
+static void err_broadcast(const struct cpumask *mask)
+{
+       pr_crit_once("Failed to broadcast timer tick. Some CPUs may be unresponsive.\n");
+}
+
+static void tick_device_setup_broadcast_func(struct clock_event_device *dev)
+{
+       if (!dev->broadcast)
+               dev->broadcast = tick_broadcast;
+       if (!dev->broadcast) {
+               pr_warn_once("%s depends on broadcast, but no broadcast function available\n",
+                            dev->name);
+               dev->broadcast = err_broadcast;
+       }
+}
+
 /*
  * Check, if the device is disfunctional and a place holder, which
  * needs to be handled by the broadcast device.
@@ -105,6 +122,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
         */
        if (!tick_device_is_functional(dev)) {
                dev->event_handler = tick_handle_periodic;
+               tick_device_setup_broadcast_func(dev);
                cpumask_set_cpu(cpu, tick_get_broadcast_mask());
                tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
                ret = 1;
@@ -116,15 +134,33 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
                 */
                if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
                        int cpu = smp_processor_id();
-
                        cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
                        tick_broadcast_clear_oneshot(cpu);
+               } else {
+                       tick_device_setup_broadcast_func(dev);
                }
        }
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
        return ret;
 }
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+int tick_receive_broadcast(void)
+{
+       struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
+       struct clock_event_device *evt = td->evtdev;
+
+       if (!evt)
+               return -ENODEV;
+
+       if (!evt->event_handler)
+               return -EINVAL;
+
+       evt->event_handler(evt);
+       return 0;
+}
+#endif
+
 /*
  * Broadcast the event to the cpus, which are set in the mask (mangled).
  */
index d58e552d9fd154b39fffaa012a6028838b9955fd..314b9ee07edf076dcba956f064075ef9768e0422 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/profile.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/irq_work.h>
 
 #include <asm/irq_regs.h>
 
@@ -28,7 +29,7 @@
 /*
  * Per cpu nohz control structure
  */
-static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
 
 /*
  * The time, when the last jiffy update happened. Protected by jiffies_lock.
@@ -331,8 +332,8 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
                time_delta = timekeeping_max_deferment();
        } while (read_seqretry(&jiffies_lock, seq));
 
-       if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) ||
-           arch_needs_cpu(cpu)) {
+       if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) ||
+           arch_needs_cpu(cpu) || irq_work_needs_cpu()) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
        } else {
@@ -631,8 +632,11 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
 
 static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
 {
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        unsigned long ticks;
+
+       if (vtime_accounting_enabled())
+               return;
        /*
         * We stopped the tick in idle. Update process times would miss the
         * time we slept as update_process_times does only a 1 tick
index cbc6acb0db3fafbaa4830da34cdb22e538892764..1e35515a875e86966e08a47737c6dfb070956309 100644 (file)
@@ -29,6 +29,9 @@ static struct timekeeper timekeeper;
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
 
+/* Flag for if there is a persistent clock on this platform */
+bool __read_mostly persistent_clock_exist = false;
+
 static inline void tk_normalize_xtime(struct timekeeper *tk)
 {
        while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) {
@@ -264,19 +267,18 @@ static void timekeeping_forward_now(struct timekeeper *tk)
 }
 
 /**
- * getnstimeofday - Returns the time of day in a timespec
+ * __getnstimeofday - Returns the time of day in a timespec.
  * @ts:                pointer to the timespec to be set
  *
- * Returns the time of day in a timespec.
+ * Updates the time of day in the timespec.
+ * Returns 0 on success, or -ve when suspended (timespec will be undefined).
  */
-void getnstimeofday(struct timespec *ts)
+int __getnstimeofday(struct timespec *ts)
 {
        struct timekeeper *tk = &timekeeper;
        unsigned long seq;
        s64 nsecs = 0;
 
-       WARN_ON(timekeeping_suspended);
-
        do {
                seq = read_seqbegin(&tk->lock);
 
@@ -287,6 +289,26 @@ void getnstimeofday(struct timespec *ts)
 
        ts->tv_nsec = 0;
        timespec_add_ns(ts, nsecs);
+
+       /*
+        * Do not bail out early, in case there were callers still using
+        * the value, even in the face of the WARN_ON.
+        */
+       if (unlikely(timekeeping_suspended))
+               return -EAGAIN;
+       return 0;
+}
+EXPORT_SYMBOL(__getnstimeofday);
+
+/**
+ * getnstimeofday - Returns the time of day in a timespec.
+ * @ts:                pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec (WARN if suspended).
+ */
+void getnstimeofday(struct timespec *ts)
+{
+       WARN_ON(__getnstimeofday(ts));
 }
 EXPORT_SYMBOL(getnstimeofday);
 
@@ -640,12 +662,14 @@ void __init timekeeping_init(void)
        struct timespec now, boot, tmp;
 
        read_persistent_clock(&now);
+
        if (!timespec_valid_strict(&now)) {
                pr_warn("WARNING: Persistent clock returned invalid value!\n"
                        "         Check your CMOS/BIOS settings.\n");
                now.tv_sec = 0;
                now.tv_nsec = 0;
-       }
+       } else if (now.tv_sec || now.tv_nsec)
+               persistent_clock_exist = true;
 
        read_boot_clock(&boot);
        if (!timespec_valid_strict(&boot)) {
@@ -718,11 +742,12 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
 {
        struct timekeeper *tk = &timekeeper;
        unsigned long flags;
-       struct timespec ts;
 
-       /* Make sure we don't set the clock twice */
-       read_persistent_clock(&ts);
-       if (!(ts.tv_sec == 0 && ts.tv_nsec == 0))
+       /*
+        * Make sure we don't set the clock twice, as timekeeping_resume()
+        * already did it
+        */
+       if (has_persistent_clock())
                return;
 
        write_seqlock_irqsave(&tk->lock, flags);
index eb51d76e058a401477776e279fba95c95a315a4a..3f42652a6a3749ca2b17dbaf397e483a3f2e6667 100644 (file)
@@ -369,10 +369,8 @@ if ($hz eq '--can') {
                die "Usage: $0 HZ\n";
        }
 
-       @val = @{$canned_values{$hz}};
-       if (!defined(@val)) {
-               @val = compute_values($hz);
-       }
+       $cv = $canned_values{$hz};
+       @val = defined($cv) ? @$cv : compute_values($hz);
        output($hz, @val);
 }
 exit 0;
index 367d008584823a6fe01ed013cda8c3693fcfd761..dbf7a78a1ef14a0200a1a28835ebb292be2aae4c 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/kallsyms.h>
 #include <linux/irq_work.h>
 #include <linux/sched.h>
+#include <linux/sched/sysctl.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -1351,7 +1352,6 @@ void update_process_times(int user_tick)
        account_process_tick(p, user_tick);
        run_local_timers();
        rcu_check_callbacks(cpu, user_tick);
-       printk_tick();
 #ifdef CONFIG_IRQ_WORK
        if (in_irq())
                irq_work_run();
index 5d89335a485f7480ea4fa3924261e5d659e79ad0..36567564e221195d1a8489207fed82f27c36b85e 100644 (file)
@@ -39,6 +39,9 @@ config HAVE_DYNAMIC_FTRACE
        help
          See Documentation/trace/ftrace-design.txt
 
+config HAVE_DYNAMIC_FTRACE_WITH_REGS
+       bool
+
 config HAVE_FTRACE_MCOUNT_RECORD
        bool
        help
@@ -250,6 +253,16 @@ config FTRACE_SYSCALLS
        help
          Basic tracer to catch the syscall entry and exit events.
 
+config TRACER_SNAPSHOT
+       bool "Create a snapshot trace buffer"
+       select TRACER_MAX_TRACE
+       help
+         Allow tracing users to take snapshot of the current buffer using the
+         ftrace interface, e.g.:
+
+             echo 1 > /sys/kernel/debug/tracing/snapshot
+             cat snapshot
+
 config TRACE_BRANCH_PROFILING
        bool
        select GENERIC_TRACER
@@ -434,6 +447,11 @@ config DYNAMIC_FTRACE
          were made. If so, it runs stop_machine (stops all CPUS)
          and modifies the code to jump over the call to ftrace.
 
+config DYNAMIC_FTRACE_WITH_REGS
+       def_bool y
+       depends on DYNAMIC_FTRACE
+       depends on HAVE_DYNAMIC_FTRACE_WITH_REGS
+
 config FUNCTION_PROFILER
        bool "Kernel function profiler"
        depends on FUNCTION_TRACER
index c0bd0308741ca1a343a9cbc0b551b4a12438ddd7..71259e2b6b6167985fe0550e8c47de33a770e603 100644 (file)
@@ -147,7 +147,7 @@ void __trace_note_message(struct blk_trace *bt, const char *fmt, ...)
                return;
 
        local_irq_save(flags);
-       buf = per_cpu_ptr(bt->msg_data, smp_processor_id());
+       buf = this_cpu_ptr(bt->msg_data);
        va_start(args, fmt);
        n = vscnprintf(buf, BLK_TN_MAX_MSG, fmt, args);
        va_end(args);
index 3ffe4c5ad3f37353d45d828407fb484ab811e441..ce8c3d68292f701ac7813f4e20a19af79896fa4b 100644 (file)
@@ -111,6 +111,26 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
 #define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops)
 #endif
 
+/*
+ * Traverse the ftrace_global_list, invoking all entries.  The reason that we
+ * can use rcu_dereference_raw() is that elements removed from this list
+ * are simply leaked, so there is no need to interact with a grace-period
+ * mechanism.  The rcu_dereference_raw() calls are needed to handle
+ * concurrent insertions into the ftrace_global_list.
+ *
+ * Silly Alpha and silly pointer-speculation compiler optimizations!
+ */
+#define do_for_each_ftrace_op(op, list)                        \
+       op = rcu_dereference_raw(list);                 \
+       do
+
+/*
+ * Optimized for just a single item in the list (as that is the normal case).
+ */
+#define while_for_each_ftrace_op(op)                           \
+       while (likely(op = rcu_dereference_raw((op)->next)) &&  \
+              unlikely((op) != &ftrace_list_end))
+
 /**
  * ftrace_nr_registered_ops - return number of ops registered
  *
@@ -132,29 +152,21 @@ int ftrace_nr_registered_ops(void)
        return cnt;
 }
 
-/*
- * Traverse the ftrace_global_list, invoking all entries.  The reason that we
- * can use rcu_dereference_raw() is that elements removed from this list
- * are simply leaked, so there is no need to interact with a grace-period
- * mechanism.  The rcu_dereference_raw() calls are needed to handle
- * concurrent insertions into the ftrace_global_list.
- *
- * Silly Alpha and silly pointer-speculation compiler optimizations!
- */
 static void
 ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,
                        struct ftrace_ops *op, struct pt_regs *regs)
 {
-       if (unlikely(trace_recursion_test(TRACE_GLOBAL_BIT)))
+       int bit;
+
+       bit = trace_test_and_set_recursion(TRACE_GLOBAL_START, TRACE_GLOBAL_MAX);
+       if (bit < 0)
                return;
 
-       trace_recursion_set(TRACE_GLOBAL_BIT);
-       op = rcu_dereference_raw(ftrace_global_list); /*see above*/
-       while (op != &ftrace_list_end) {
+       do_for_each_ftrace_op(op, ftrace_global_list) {
                op->func(ip, parent_ip, op, regs);
-               op = rcu_dereference_raw(op->next); /*see above*/
-       };
-       trace_recursion_clear(TRACE_GLOBAL_BIT);
+       } while_for_each_ftrace_op(op);
+
+       trace_clear_recursion(bit);
 }
 
 static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
@@ -221,10 +233,24 @@ static void update_global_ops(void)
         * registered callers.
         */
        if (ftrace_global_list == &ftrace_list_end ||
-           ftrace_global_list->next == &ftrace_list_end)
+           ftrace_global_list->next == &ftrace_list_end) {
                func = ftrace_global_list->func;
-       else
+               /*
+                * As we are calling the function directly.
+                * If it does not have recursion protection,
+                * the function_trace_op needs to be updated
+                * accordingly.
+                */
+               if (ftrace_global_list->flags & FTRACE_OPS_FL_RECURSION_SAFE)
+                       global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
+               else
+                       global_ops.flags &= ~FTRACE_OPS_FL_RECURSION_SAFE;
+       } else {
                func = ftrace_global_list_func;
+               /* The list has its own recursion protection. */
+               global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
+       }
+
 
        /* If we filter on pids, update to use the pid function */
        if (!list_empty(&ftrace_pids)) {
@@ -337,7 +363,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
        if ((ops->flags & FL_GLOBAL_CONTROL_MASK) == FL_GLOBAL_CONTROL_MASK)
                return -EINVAL;
 
-#ifndef ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS
        /*
         * If the ftrace_ops specifies SAVE_REGS, then it only can be used
         * if the arch supports it, or SAVE_REGS_IF_SUPPORTED is also set.
@@ -3998,7 +4024,7 @@ static int ftrace_module_notify(struct notifier_block *self,
 
 struct notifier_block ftrace_module_nb = {
        .notifier_call = ftrace_module_notify,
-       .priority = 0,
+       .priority = INT_MAX,    /* Run before anything that can use kprobes */
 };
 
 extern unsigned long __start_mcount_loc[];
@@ -4090,14 +4116,11 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
         */
        preempt_disable_notrace();
        trace_recursion_set(TRACE_CONTROL_BIT);
-       op = rcu_dereference_raw(ftrace_control_list);
-       while (op != &ftrace_list_end) {
+       do_for_each_ftrace_op(op, ftrace_control_list) {
                if (!ftrace_function_local_disabled(op) &&
                    ftrace_ops_test(op, ip))
                        op->func(ip, parent_ip, op, regs);
-
-               op = rcu_dereference_raw(op->next);
-       };
+       } while_for_each_ftrace_op(op);
        trace_recursion_clear(TRACE_CONTROL_BIT);
        preempt_enable_notrace();
 }
@@ -4112,27 +4135,26 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
                       struct ftrace_ops *ignored, struct pt_regs *regs)
 {
        struct ftrace_ops *op;
+       int bit;
 
        if (function_trace_stop)
                return;
 
-       if (unlikely(trace_recursion_test(TRACE_INTERNAL_BIT)))
+       bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
+       if (bit < 0)
                return;
 
-       trace_recursion_set(TRACE_INTERNAL_BIT);
        /*
         * Some of the ops may be dynamically allocated,
         * they must be freed after a synchronize_sched().
         */
        preempt_disable_notrace();
-       op = rcu_dereference_raw(ftrace_ops_list);
-       while (op != &ftrace_list_end) {
+       do_for_each_ftrace_op(op, ftrace_ops_list) {
                if (ftrace_ops_test(op, ip))
                        op->func(ip, parent_ip, op, regs);
-               op = rcu_dereference_raw(op->next);
-       };
+       } while_for_each_ftrace_op(op);
        preempt_enable_notrace();
-       trace_recursion_clear(TRACE_INTERNAL_BIT);
+       trace_clear_recursion(bit);
 }
 
 /*
@@ -4143,8 +4165,8 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
  * Archs are to support both the regs and ftrace_ops at the same time.
  * If they support ftrace_ops, it is assumed they support regs.
  * If call backs want to use regs, they must either check for regs
- * being NULL, or ARCH_SUPPORTS_FTRACE_SAVE_REGS.
- * Note, ARCH_SUPPORT_SAVE_REGS expects a full regs to be saved.
+ * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
+ * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
  * An architecture can pass partial regs with ftrace_ops and still
  * set the ARCH_SUPPORT_FTARCE_OPS.
  */
index ce8514feedcdf29c181dda4972eb7a53cd0df04e..7244acde77b0a9a5670d401fc505c64c5d8b06c0 100644 (file)
@@ -3,8 +3,10 @@
  *
  * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
  */
+#include <linux/ftrace_event.h>
 #include <linux/ring_buffer.h>
 #include <linux/trace_clock.h>
+#include <linux/trace_seq.h>
 #include <linux/spinlock.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -21,7 +23,6 @@
 #include <linux/fs.h>
 
 #include <asm/local.h>
-#include "trace.h"
 
 static void update_pages_handler(struct work_struct *work);
 
@@ -2432,41 +2433,76 @@ rb_reserve_next_event(struct ring_buffer *buffer,
 
 #ifdef CONFIG_TRACING
 
-#define TRACE_RECURSIVE_DEPTH 16
+/*
+ * The lock and unlock are done within a preempt disable section.
+ * The current_context per_cpu variable can only be modified
+ * by the current task between lock and unlock. But it can
+ * be modified more than once via an interrupt. To pass this
+ * information from the lock to the unlock without having to
+ * access the 'in_interrupt()' functions again (which do show
+ * a bit of overhead in something as critical as function tracing,
+ * we use a bitmask trick.
+ *
+ *  bit 0 =  NMI context
+ *  bit 1 =  IRQ context
+ *  bit 2 =  SoftIRQ context
+ *  bit 3 =  normal context.
+ *
+ * This works because this is the order of contexts that can
+ * preempt other contexts. A SoftIRQ never preempts an IRQ
+ * context.
+ *
+ * When the context is determined, the corresponding bit is
+ * checked and set (if it was set, then a recursion of that context
+ * happened).
+ *
+ * On unlock, we need to clear this bit. To do so, just subtract
+ * 1 from the current_context and AND it to itself.
+ *
+ * (binary)
+ *  101 - 1 = 100
+ *  101 & 100 = 100 (clearing bit zero)
+ *
+ *  1010 - 1 = 1001
+ *  1010 & 1001 = 1000 (clearing bit 1)
+ *
+ * The least significant bit can be cleared this way, and it
+ * just so happens that it is the same bit corresponding to
+ * the current context.
+ */
+static DEFINE_PER_CPU(unsigned int, current_context);
 
-/* Keep this code out of the fast path cache */
-static noinline void trace_recursive_fail(void)
+static __always_inline int trace_recursive_lock(void)
 {
-       /* Disable all tracing before we do anything else */
-       tracing_off_permanent();
-
-       printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:"
-                   "HC[%lu]:SC[%lu]:NMI[%lu]\n",
-                   trace_recursion_buffer(),
-                   hardirq_count() >> HARDIRQ_SHIFT,
-                   softirq_count() >> SOFTIRQ_SHIFT,
-                   in_nmi());
-
-       WARN_ON_ONCE(1);
-}
+       unsigned int val = this_cpu_read(current_context);
+       int bit;
 
-static inline int trace_recursive_lock(void)
-{
-       trace_recursion_inc();
+       if (in_interrupt()) {
+               if (in_nmi())
+                       bit = 0;
+               else if (in_irq())
+                       bit = 1;
+               else
+                       bit = 2;
+       } else
+               bit = 3;
 
-       if (likely(trace_recursion_buffer() < TRACE_RECURSIVE_DEPTH))
-               return 0;
+       if (unlikely(val & (1 << bit)))
+               return 1;
 
-       trace_recursive_fail();
+       val |= (1 << bit);
+       this_cpu_write(current_context, val);
 
-       return -1;
+       return 0;
 }
 
-static inline void trace_recursive_unlock(void)
+static __always_inline void trace_recursive_unlock(void)
 {
-       WARN_ON_ONCE(!trace_recursion_buffer());
+       unsigned int val = this_cpu_read(current_context);
 
-       trace_recursion_dec();
+       val--;
+       val &= this_cpu_read(current_context);
+       this_cpu_write(current_context, val);
 }
 
 #else
@@ -3066,6 +3102,24 @@ ring_buffer_dropped_events_cpu(struct ring_buffer *buffer, int cpu)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_dropped_events_cpu);
 
+/**
+ * ring_buffer_read_events_cpu - get the number of events successfully read
+ * @buffer: The ring buffer
+ * @cpu: The per CPU buffer to get the number of events read
+ */
+unsigned long
+ring_buffer_read_events_cpu(struct ring_buffer *buffer, int cpu)
+{
+       struct ring_buffer_per_cpu *cpu_buffer;
+
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
+               return 0;
+
+       cpu_buffer = buffer->buffers[cpu];
+       return cpu_buffer->read;
+}
+EXPORT_SYMBOL_GPL(ring_buffer_read_events_cpu);
+
 /**
  * ring_buffer_entries - get the number of entries in a buffer
  * @buffer: The ring buffer
@@ -3425,7 +3479,7 @@ static void rb_advance_iter(struct ring_buffer_iter *iter)
        /* check for end of page padding */
        if ((iter->head >= rb_page_size(iter->head_page)) &&
            (iter->head_page != cpu_buffer->commit_page))
-               rb_advance_iter(iter);
+               rb_inc_iter(iter);
 }
 
 static int rb_lost_events(struct ring_buffer_per_cpu *cpu_buffer)
index e5125677efa007a8ff58d5cd14b70766117dbc92..c2e2c23103742e3a3e53cf7b318aa0c804f5e1a8 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/poll.h>
 #include <linux/nmi.h>
 #include <linux/fs.h>
+#include <linux/sched/rt.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -249,7 +250,7 @@ static unsigned long                trace_buf_size = TRACE_BUF_SIZE_DEFAULT;
 static struct tracer           *trace_types __read_mostly;
 
 /* current_trace points to the tracer that is currently active */
-static struct tracer           *current_trace __read_mostly;
+static struct tracer           *current_trace __read_mostly = &nop_trace;
 
 /*
  * trace_types_lock is used to protect the trace_types list.
@@ -709,10 +710,13 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
                return;
 
        WARN_ON_ONCE(!irqs_disabled());
-       if (!current_trace->use_max_tr) {
-               WARN_ON_ONCE(1);
+
+       if (!current_trace->allocated_snapshot) {
+               /* Only the nop tracer should hit this when disabling */
+               WARN_ON_ONCE(current_trace != &nop_trace);
                return;
        }
+
        arch_spin_lock(&ftrace_max_lock);
 
        tr->buffer = max_tr.buffer;
@@ -739,10 +743,8 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
                return;
 
        WARN_ON_ONCE(!irqs_disabled());
-       if (!current_trace->use_max_tr) {
-               WARN_ON_ONCE(1);
+       if (WARN_ON_ONCE(!current_trace->allocated_snapshot))
                return;
-       }
 
        arch_spin_lock(&ftrace_max_lock);
 
@@ -862,10 +864,13 @@ int register_tracer(struct tracer *type)
 
                current_trace = type;
 
-               /* If we expanded the buffers, make sure the max is expanded too */
-               if (ring_buffer_expanded && type->use_max_tr)
-                       ring_buffer_resize(max_tr.buffer, trace_buf_size,
-                                               RING_BUFFER_ALL_CPUS);
+               if (type->use_max_tr) {
+                       /* If we expanded the buffers, make sure the max is expanded too */
+                       if (ring_buffer_expanded)
+                               ring_buffer_resize(max_tr.buffer, trace_buf_size,
+                                                  RING_BUFFER_ALL_CPUS);
+                       type->allocated_snapshot = true;
+               }
 
                /* the test is responsible for initializing and enabling */
                pr_info("Testing tracer %s: ", type->name);
@@ -881,10 +886,14 @@ int register_tracer(struct tracer *type)
                /* Only reset on passing, to avoid touching corrupted buffers */
                tracing_reset_online_cpus(tr);
 
-               /* Shrink the max buffer again */
-               if (ring_buffer_expanded && type->use_max_tr)
-                       ring_buffer_resize(max_tr.buffer, 1,
-                                               RING_BUFFER_ALL_CPUS);
+               if (type->use_max_tr) {
+                       type->allocated_snapshot = false;
+
+                       /* Shrink the max buffer again */
+                       if (ring_buffer_expanded)
+                               ring_buffer_resize(max_tr.buffer, 1,
+                                                  RING_BUFFER_ALL_CPUS);
+               }
 
                printk(KERN_CONT "PASSED\n");
        }
@@ -922,6 +931,9 @@ void tracing_reset(struct trace_array *tr, int cpu)
 {
        struct ring_buffer *buffer = tr->buffer;
 
+       if (!buffer)
+               return;
+
        ring_buffer_record_disable(buffer);
 
        /* Make sure all commits have finished */
@@ -936,6 +948,9 @@ void tracing_reset_online_cpus(struct trace_array *tr)
        struct ring_buffer *buffer = tr->buffer;
        int cpu;
 
+       if (!buffer)
+               return;
+
        ring_buffer_record_disable(buffer);
 
        /* Make sure all commits have finished */
@@ -1167,7 +1182,6 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
 
        entry->preempt_count            = pc & 0xff;
        entry->pid                      = (tsk) ? tsk->pid : 0;
-       entry->padding                  = 0;
        entry->flags =
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
                (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@ -1335,7 +1349,7 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer,
         */
        preempt_disable_notrace();
 
-       use_stack = ++__get_cpu_var(ftrace_stack_reserve);
+       use_stack = __this_cpu_inc_return(ftrace_stack_reserve);
        /*
         * We don't need any atomic variables, just a barrier.
         * If an interrupt comes in, we don't care, because it would
@@ -1389,7 +1403,7 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer,
  out:
        /* Again, don't let gcc optimize things here */
        barrier();
-       __get_cpu_var(ftrace_stack_reserve)--;
+       __this_cpu_dec(ftrace_stack_reserve);
        preempt_enable_notrace();
 
 }
@@ -1517,7 +1531,6 @@ static struct trace_buffer_struct *trace_percpu_nmi_buffer;
 static char *get_trace_buf(void)
 {
        struct trace_buffer_struct *percpu_buffer;
-       struct trace_buffer_struct *buffer;
 
        /*
         * If we have allocated per cpu buffers, then we do not
@@ -1535,9 +1548,7 @@ static char *get_trace_buf(void)
        if (!percpu_buffer)
                return NULL;
 
-       buffer = per_cpu_ptr(percpu_buffer, smp_processor_id());
-
-       return buffer->buffer;
+       return this_cpu_ptr(&percpu_buffer->buffer[0]);
 }
 
 static int alloc_percpu_trace_buffer(void)
@@ -1942,21 +1953,27 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
        struct trace_iterator *iter = m->private;
-       static struct tracer *old_tracer;
        int cpu_file = iter->cpu_file;
        void *p = NULL;
        loff_t l = 0;
        int cpu;
 
-       /* copy the tracer to avoid using a global lock all around */
+       /*
+        * copy the tracer to avoid using a global lock all around.
+        * iter->trace is a copy of current_trace, the pointer to the
+        * name may be used instead of a strcmp(), as iter->trace->name
+        * will point to the same string as current_trace->name.
+        */
        mutex_lock(&trace_types_lock);
-       if (unlikely(old_tracer != current_trace && current_trace)) {
-               old_tracer = current_trace;
+       if (unlikely(current_trace && iter->trace->name != current_trace->name))
                *iter->trace = *current_trace;
-       }
        mutex_unlock(&trace_types_lock);
 
-       atomic_inc(&trace_record_cmdline_disabled);
+       if (iter->snapshot && iter->trace->use_max_tr)
+               return ERR_PTR(-EBUSY);
+
+       if (!iter->snapshot)
+               atomic_inc(&trace_record_cmdline_disabled);
 
        if (*pos != iter->pos) {
                iter->ent = NULL;
@@ -1995,7 +2012,11 @@ static void s_stop(struct seq_file *m, void *p)
 {
        struct trace_iterator *iter = m->private;
 
-       atomic_dec(&trace_record_cmdline_disabled);
+       if (iter->snapshot && iter->trace->use_max_tr)
+               return;
+
+       if (!iter->snapshot)
+               atomic_dec(&trace_record_cmdline_disabled);
        trace_access_unlock(iter->cpu_file);
        trace_event_read_unlock();
 }
@@ -2080,8 +2101,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
        unsigned long total;
        const char *name = "preemption";
 
-       if (type)
-               name = type->name;
+       name = type->name;
 
        get_total_entries(tr, &total, &entries);
 
@@ -2430,7 +2450,7 @@ static const struct seq_operations tracer_seq_ops = {
 };
 
 static struct trace_iterator *
-__tracing_open(struct inode *inode, struct file *file)
+__tracing_open(struct inode *inode, struct file *file, bool snapshot)
 {
        long cpu_file = (long) inode->i_private;
        struct trace_iterator *iter;
@@ -2457,16 +2477,16 @@ __tracing_open(struct inode *inode, struct file *file)
        if (!iter->trace)
                goto fail;
 
-       if (current_trace)
-               *iter->trace = *current_trace;
+       *iter->trace = *current_trace;
 
        if (!zalloc_cpumask_var(&iter->started, GFP_KERNEL))
                goto fail;
 
-       if (current_trace && current_trace->print_max)
+       if (current_trace->print_max || snapshot)
                iter->tr = &max_tr;
        else
                iter->tr = &global_trace;
+       iter->snapshot = snapshot;
        iter->pos = -1;
        mutex_init(&iter->mutex);
        iter->cpu_file = cpu_file;
@@ -2483,8 +2503,9 @@ __tracing_open(struct inode *inode, struct file *file)
        if (trace_clocks[trace_clock_id].in_ns)
                iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
-       /* stop the trace while dumping */
-       tracing_stop();
+       /* stop the trace while dumping if we are not opening "snapshot" */
+       if (!iter->snapshot)
+               tracing_stop();
 
        if (iter->cpu_file == TRACE_PIPE_ALL_CPU) {
                for_each_tracing_cpu(cpu) {
@@ -2547,8 +2568,9 @@ static int tracing_release(struct inode *inode, struct file *file)
        if (iter->trace && iter->trace->close)
                iter->trace->close(iter);
 
-       /* reenable tracing if it was previously enabled */
-       tracing_start();
+       if (!iter->snapshot)
+               /* reenable tracing if it was previously enabled */
+               tracing_start();
        mutex_unlock(&trace_types_lock);
 
        mutex_destroy(&iter->mutex);
@@ -2576,7 +2598,7 @@ static int tracing_open(struct inode *inode, struct file *file)
        }
 
        if (file->f_mode & FMODE_READ) {
-               iter = __tracing_open(inode, file);
+               iter = __tracing_open(inode, file, false);
                if (IS_ERR(iter))
                        ret = PTR_ERR(iter);
                else if (trace_flags & TRACE_ITER_LATENCY_FMT)
@@ -2899,6 +2921,8 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
        if (copy_from_user(&buf, ubuf, cnt))
                return -EFAULT;
 
+       buf[cnt] = 0;
+
        trace_set_options(buf);
 
        *ppos += cnt;
@@ -3012,10 +3036,7 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf,
        int r;
 
        mutex_lock(&trace_types_lock);
-       if (current_trace)
-               r = sprintf(buf, "%s\n", current_trace->name);
-       else
-               r = sprintf(buf, "\n");
+       r = sprintf(buf, "%s\n", current_trace->name);
        mutex_unlock(&trace_types_lock);
 
        return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
@@ -3181,6 +3202,7 @@ static int tracing_set_tracer(const char *buf)
        static struct trace_option_dentry *topts;
        struct trace_array *tr = &global_trace;
        struct tracer *t;
+       bool had_max_tr;
        int ret = 0;
 
        mutex_lock(&trace_types_lock);
@@ -3205,9 +3227,21 @@ static int tracing_set_tracer(const char *buf)
                goto out;
 
        trace_branch_disable();
-       if (current_trace && current_trace->reset)
+       if (current_trace->reset)
                current_trace->reset(tr);
-       if (current_trace && current_trace->use_max_tr) {
+
+       had_max_tr = current_trace->allocated_snapshot;
+       current_trace = &nop_trace;
+
+       if (had_max_tr && !t->use_max_tr) {
+               /*
+                * We need to make sure that the update_max_tr sees that
+                * current_trace changed to nop_trace to keep it from
+                * swapping the buffers after we resize it.
+                * The update_max_tr is called from interrupts disabled
+                * so a synchronized_sched() is sufficient.
+                */
+               synchronize_sched();
                /*
                 * We don't free the ring buffer. instead, resize it because
                 * The max_tr ring buffer has some state (e.g. ring->clock) and
@@ -3215,18 +3249,19 @@ static int tracing_set_tracer(const char *buf)
                 */
                ring_buffer_resize(max_tr.buffer, 1, RING_BUFFER_ALL_CPUS);
                set_buffer_entries(&max_tr, 1);
+               tracing_reset_online_cpus(&max_tr);
+               current_trace->allocated_snapshot = false;
        }
        destroy_trace_option_files(topts);
 
-       current_trace = &nop_trace;
-
        topts = create_trace_option_files(t);
-       if (t->use_max_tr) {
+       if (t->use_max_tr && !had_max_tr) {
                /* we need to make per cpu buffer sizes equivalent */
                ret = resize_buffer_duplicate_size(&max_tr, &global_trace,
                                                   RING_BUFFER_ALL_CPUS);
                if (ret < 0)
                        goto out;
+               t->allocated_snapshot = true;
        }
 
        if (t->init) {
@@ -3334,8 +3369,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
                ret = -ENOMEM;
                goto fail;
        }
-       if (current_trace)
-               *iter->trace = *current_trace;
+       *iter->trace = *current_trace;
 
        if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) {
                ret = -ENOMEM;
@@ -3452,7 +3486,7 @@ static int tracing_wait_pipe(struct file *filp)
                        return -EINTR;
 
                /*
-                * We block until we read something and tracing is enabled.
+                * We block until we read something and tracing is disabled.
                 * We still block if tracing is disabled, but we have never
                 * read anything. This allows a user to cat this file, and
                 * then enable tracing. But after we have read something,
@@ -3460,7 +3494,7 @@ static int tracing_wait_pipe(struct file *filp)
                 *
                 * iter->pos will be 0 if we haven't read anything.
                 */
-               if (tracing_is_enabled() && iter->pos)
+               if (!tracing_is_enabled() && iter->pos)
                        break;
        }
 
@@ -3475,7 +3509,6 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
                  size_t cnt, loff_t *ppos)
 {
        struct trace_iterator *iter = filp->private_data;
-       static struct tracer *old_tracer;
        ssize_t sret;
 
        /* return any leftover data */
@@ -3487,10 +3520,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
 
        /* copy the tracer to avoid using a global lock all around */
        mutex_lock(&trace_types_lock);
-       if (unlikely(old_tracer != current_trace && current_trace)) {
-               old_tracer = current_trace;
+       if (unlikely(iter->trace->name != current_trace->name))
                *iter->trace = *current_trace;
-       }
        mutex_unlock(&trace_types_lock);
 
        /*
@@ -3646,7 +3677,6 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
                .ops            = &tracing_pipe_buf_ops,
                .spd_release    = tracing_spd_release_pipe,
        };
-       static struct tracer *old_tracer;
        ssize_t ret;
        size_t rem;
        unsigned int i;
@@ -3656,10 +3686,8 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
 
        /* copy the tracer to avoid using a global lock all around */
        mutex_lock(&trace_types_lock);
-       if (unlikely(old_tracer != current_trace && current_trace)) {
-               old_tracer = current_trace;
+       if (unlikely(iter->trace->name != current_trace->name))
                *iter->trace = *current_trace;
-       }
        mutex_unlock(&trace_types_lock);
 
        mutex_lock(&iter->mutex);
@@ -4035,8 +4063,7 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
         * Reset the buffer so that it doesn't have incomparable timestamps.
         */
        tracing_reset_online_cpus(&global_trace);
-       if (max_tr.buffer)
-               tracing_reset_online_cpus(&max_tr);
+       tracing_reset_online_cpus(&max_tr);
 
        mutex_unlock(&trace_types_lock);
 
@@ -4052,6 +4079,87 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
        return single_open(file, tracing_clock_show, NULL);
 }
 
+#ifdef CONFIG_TRACER_SNAPSHOT
+static int tracing_snapshot_open(struct inode *inode, struct file *file)
+{
+       struct trace_iterator *iter;
+       int ret = 0;
+
+       if (file->f_mode & FMODE_READ) {
+               iter = __tracing_open(inode, file, true);
+               if (IS_ERR(iter))
+                       ret = PTR_ERR(iter);
+       }
+       return ret;
+}
+
+static ssize_t
+tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
+                      loff_t *ppos)
+{
+       unsigned long val;
+       int ret;
+
+       ret = tracing_update_buffers();
+       if (ret < 0)
+               return ret;
+
+       ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&trace_types_lock);
+
+       if (current_trace->use_max_tr) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       switch (val) {
+       case 0:
+               if (current_trace->allocated_snapshot) {
+                       /* free spare buffer */
+                       ring_buffer_resize(max_tr.buffer, 1,
+                                          RING_BUFFER_ALL_CPUS);
+                       set_buffer_entries(&max_tr, 1);
+                       tracing_reset_online_cpus(&max_tr);
+                       current_trace->allocated_snapshot = false;
+               }
+               break;
+       case 1:
+               if (!current_trace->allocated_snapshot) {
+                       /* allocate spare buffer */
+                       ret = resize_buffer_duplicate_size(&max_tr,
+                                       &global_trace, RING_BUFFER_ALL_CPUS);
+                       if (ret < 0)
+                               break;
+                       current_trace->allocated_snapshot = true;
+               }
+
+               local_irq_disable();
+               /* Now, we're going to swap */
+               update_max_tr(&global_trace, current, smp_processor_id());
+               local_irq_enable();
+               break;
+       default:
+               if (current_trace->allocated_snapshot)
+                       tracing_reset_online_cpus(&max_tr);
+               else
+                       ret = -EINVAL;
+               break;
+       }
+
+       if (ret >= 0) {
+               *ppos += cnt;
+               ret = cnt;
+       }
+out:
+       mutex_unlock(&trace_types_lock);
+       return ret;
+}
+#endif /* CONFIG_TRACER_SNAPSHOT */
+
+
 static const struct file_operations tracing_max_lat_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_max_lat_read,
@@ -4108,6 +4216,16 @@ static const struct file_operations trace_clock_fops = {
        .write          = tracing_clock_write,
 };
 
+#ifdef CONFIG_TRACER_SNAPSHOT
+static const struct file_operations snapshot_fops = {
+       .open           = tracing_snapshot_open,
+       .read           = seq_read,
+       .write          = tracing_snapshot_write,
+       .llseek         = tracing_seek,
+       .release        = tracing_release,
+};
+#endif /* CONFIG_TRACER_SNAPSHOT */
+
 struct ftrace_buffer_info {
        struct trace_array      *tr;
        void                    *spare;
@@ -4412,6 +4530,9 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
        cnt = ring_buffer_dropped_events_cpu(tr->buffer, cpu);
        trace_seq_printf(s, "dropped events: %ld\n", cnt);
 
+       cnt = ring_buffer_read_events_cpu(tr->buffer, cpu);
+       trace_seq_printf(s, "read events: %ld\n", cnt);
+
        count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
 
        kfree(s);
@@ -4488,7 +4609,7 @@ struct dentry *tracing_init_dentry(void)
 
 static struct dentry *d_percpu;
 
-struct dentry *tracing_dentry_percpu(void)
+static struct dentry *tracing_dentry_percpu(void)
 {
        static int once;
        struct dentry *d_tracer;
@@ -4815,10 +4936,17 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
                return ret;
 
        if (buffer) {
-               if (val)
+               mutex_lock(&trace_types_lock);
+               if (val) {
                        ring_buffer_record_on(buffer);
-               else
+                       if (current_trace->start)
+                               current_trace->start(tr);
+               } else {
                        ring_buffer_record_off(buffer);
+                       if (current_trace->stop)
+                               current_trace->stop(tr);
+               }
+               mutex_unlock(&trace_types_lock);
        }
 
        (*ppos)++;
@@ -4897,6 +5025,11 @@ static __init int tracer_init_debugfs(void)
                        &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
 #endif
 
+#ifdef CONFIG_TRACER_SNAPSHOT
+       trace_create_file("snapshot", 0644, d_tracer,
+                         (void *) TRACE_PIPE_ALL_CPU, &snapshot_fops);
+#endif
+
        create_trace_options_dir();
 
        for_each_tracing_cpu(cpu)
@@ -5005,6 +5138,7 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
        if (disable_tracing)
                ftrace_kill();
 
+       /* Simulate the iterator */
        trace_init_global_iter(&iter);
 
        for_each_tracing_cpu(cpu) {
@@ -5016,10 +5150,6 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode)
        /* don't look at user memory in panic mode */
        trace_flags &= ~TRACE_ITER_SYM_USEROBJ;
 
-       /* Simulate the iterator */
-       iter.tr = &global_trace;
-       iter.trace = current_trace;
-
        switch (oops_dump_mode) {
        case DUMP_ALL:
                iter.cpu_file = TRACE_PIPE_ALL_CPU;
@@ -5164,7 +5294,7 @@ __init static int tracer_alloc_buffers(void)
        init_irq_work(&trace_work_wakeup, trace_wake_up);
 
        register_tracer(&nop_trace);
-       current_trace = &nop_trace;
+
        /* All seems OK, enable tracing */
        tracing_disabled = 0;
 
index c75d7988902caa5b7ce38d3cdad888d9ade9f105..57d7e5397d56da86f667e3139fb14703a99e8fcf 100644 (file)
@@ -287,20 +287,62 @@ struct tracer {
        struct tracer_flags     *flags;
        bool                    print_max;
        bool                    use_max_tr;
+       bool                    allocated_snapshot;
 };
 
 
 /* Only current can touch trace_recursion */
-#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
-#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
 
-/* Ring buffer has the 10 LSB bits to count */
-#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
-
-/* for function tracing recursion */
-#define TRACE_INTERNAL_BIT             (1<<11)
-#define TRACE_GLOBAL_BIT               (1<<12)
-#define TRACE_CONTROL_BIT              (1<<13)
+/*
+ * For function tracing recursion:
+ *  The order of these bits are important.
+ *
+ *  When function tracing occurs, the following steps are made:
+ *   If arch does not support a ftrace feature:
+ *    call internal function (uses INTERNAL bits) which calls...
+ *   If callback is registered to the "global" list, the list
+ *    function is called and recursion checks the GLOBAL bits.
+ *    then this function calls...
+ *   The function callback, which can use the FTRACE bits to
+ *    check for recursion.
+ *
+ * Now if the arch does not suppport a feature, and it calls
+ * the global list function which calls the ftrace callback
+ * all three of these steps will do a recursion protection.
+ * There's no reason to do one if the previous caller already
+ * did. The recursion that we are protecting against will
+ * go through the same steps again.
+ *
+ * To prevent the multiple recursion checks, if a recursion
+ * bit is set that is higher than the MAX bit of the current
+ * check, then we know that the check was made by the previous
+ * caller, and we can skip the current check.
+ */
+enum {
+       TRACE_BUFFER_BIT,
+       TRACE_BUFFER_NMI_BIT,
+       TRACE_BUFFER_IRQ_BIT,
+       TRACE_BUFFER_SIRQ_BIT,
+
+       /* Start of function recursion bits */
+       TRACE_FTRACE_BIT,
+       TRACE_FTRACE_NMI_BIT,
+       TRACE_FTRACE_IRQ_BIT,
+       TRACE_FTRACE_SIRQ_BIT,
+
+       /* GLOBAL_BITs must be greater than FTRACE_BITs */
+       TRACE_GLOBAL_BIT,
+       TRACE_GLOBAL_NMI_BIT,
+       TRACE_GLOBAL_IRQ_BIT,
+       TRACE_GLOBAL_SIRQ_BIT,
+
+       /* INTERNAL_BITs must be greater than GLOBAL_BITs */
+       TRACE_INTERNAL_BIT,
+       TRACE_INTERNAL_NMI_BIT,
+       TRACE_INTERNAL_IRQ_BIT,
+       TRACE_INTERNAL_SIRQ_BIT,
+
+       TRACE_CONTROL_BIT,
 
 /*
  * Abuse of the trace_recursion.
@@ -309,11 +351,77 @@ struct tracer {
  * was called in irq context but we have irq tracing off. Since this
  * can only be modified by current, we can reuse trace_recursion.
  */
-#define TRACE_IRQ_BIT                  (1<<13)
+       TRACE_IRQ_BIT,
+};
+
+#define trace_recursion_set(bit)       do { (current)->trace_recursion |= (1<<(bit)); } while (0)
+#define trace_recursion_clear(bit)     do { (current)->trace_recursion &= ~(1<<(bit)); } while (0)
+#define trace_recursion_test(bit)      ((current)->trace_recursion & (1<<(bit)))
+
+#define TRACE_CONTEXT_BITS     4
+
+#define TRACE_FTRACE_START     TRACE_FTRACE_BIT
+#define TRACE_FTRACE_MAX       ((1 << (TRACE_FTRACE_START + TRACE_CONTEXT_BITS)) - 1)
+
+#define TRACE_GLOBAL_START     TRACE_GLOBAL_BIT
+#define TRACE_GLOBAL_MAX       ((1 << (TRACE_GLOBAL_START + TRACE_CONTEXT_BITS)) - 1)
+
+#define TRACE_LIST_START       TRACE_INTERNAL_BIT
+#define TRACE_LIST_MAX         ((1 << (TRACE_LIST_START + TRACE_CONTEXT_BITS)) - 1)
+
+#define TRACE_CONTEXT_MASK     TRACE_LIST_MAX
+
+static __always_inline int trace_get_context_bit(void)
+{
+       int bit;
 
-#define trace_recursion_set(bit)       do { (current)->trace_recursion |= (bit); } while (0)
-#define trace_recursion_clear(bit)     do { (current)->trace_recursion &= ~(bit); } while (0)
-#define trace_recursion_test(bit)      ((current)->trace_recursion & (bit))
+       if (in_interrupt()) {
+               if (in_nmi())
+                       bit = 0;
+
+               else if (in_irq())
+                       bit = 1;
+               else
+                       bit = 2;
+       } else
+               bit = 3;
+
+       return bit;
+}
+
+static __always_inline int trace_test_and_set_recursion(int start, int max)
+{
+       unsigned int val = current->trace_recursion;
+       int bit;
+
+       /* A previous recursion check was made */
+       if ((val & TRACE_CONTEXT_MASK) > max)
+               return 0;
+
+       bit = trace_get_context_bit() + start;
+       if (unlikely(val & (1 << bit)))
+               return -1;
+
+       val |= 1 << bit;
+       current->trace_recursion = val;
+       barrier();
+
+       return bit;
+}
+
+static __always_inline void trace_clear_recursion(int bit)
+{
+       unsigned int val = current->trace_recursion;
+
+       if (!bit)
+               return;
+
+       bit = 1 << bit;
+       val &= ~bit;
+
+       barrier();
+       current->trace_recursion = val;
+}
 
 #define TRACE_PIPE_ALL_CPU     -1
 
index 394783531cbb76d9f7d9ab34ae0b6963d5d14dff..aa8f5f48dae610566f4b777119e1b3735b43170f 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/ktime.h>
 #include <linux/trace_clock.h>
 
-#include "trace.h"
-
 /*
  * trace_clock_local(): the simplest and least coherent tracing clock.
  *
@@ -44,6 +42,7 @@ u64 notrace trace_clock_local(void)
 
        return clock;
 }
+EXPORT_SYMBOL_GPL(trace_clock_local);
 
 /*
  * trace_clock(): 'between' trace clock. Not completely serialized,
@@ -86,7 +85,7 @@ u64 notrace trace_clock_global(void)
        local_irq_save(flags);
 
        this_cpu = raw_smp_processor_id();
-       now = cpu_clock(this_cpu);
+       now = sched_clock_cpu(this_cpu);
        /*
         * If in an NMI context then dont risk lockups and return the
         * cpu_clock() time:
index 880073d0b946fc58865b426511b038ca24271004..57e9b284250c4ea30d7ee11692066644099acc32 100644 (file)
@@ -116,7 +116,6 @@ static int trace_define_common_fields(void)
        __common_field(unsigned char, flags);
        __common_field(unsigned char, preempt_count);
        __common_field(int, pid);
-       __common_field(int, padding);
 
        return ret;
 }
index 8e3ad8082ab7074fde4ea9da403961afd2eadc45..60115252332668f2b39c4c868304b9187017b879 100644 (file)
@@ -47,34 +47,6 @@ static void function_trace_start(struct trace_array *tr)
        tracing_reset_online_cpus(tr);
 }
 
-static void
-function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,
-                                struct ftrace_ops *op, struct pt_regs *pt_regs)
-{
-       struct trace_array *tr = func_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
-       long disabled;
-       int cpu;
-       int pc;
-
-       if (unlikely(!ftrace_function_enabled))
-               return;
-
-       pc = preempt_count();
-       preempt_disable_notrace();
-       local_save_flags(flags);
-       cpu = raw_smp_processor_id();
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
-
-       if (likely(disabled == 1))
-               trace_function(tr, ip, parent_ip, flags, pc);
-
-       atomic_dec(&data->disabled);
-       preempt_enable_notrace();
-}
-
 /* Our option */
 enum {
        TRACE_FUNC_OPT_STACK    = 0x1,
@@ -85,34 +57,34 @@ static struct tracer_flags func_flags;
 static void
 function_trace_call(unsigned long ip, unsigned long parent_ip,
                    struct ftrace_ops *op, struct pt_regs *pt_regs)
-
 {
        struct trace_array *tr = func_trace;
        struct trace_array_cpu *data;
        unsigned long flags;
-       long disabled;
+       int bit;
        int cpu;
        int pc;
 
        if (unlikely(!ftrace_function_enabled))
                return;
 
-       /*
-        * Need to use raw, since this must be called before the
-        * recursive protection is performed.
-        */
-       local_irq_save(flags);
-       cpu = raw_smp_processor_id();
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
+       pc = preempt_count();
+       preempt_disable_notrace();
 
-       if (likely(disabled == 1)) {
-               pc = preempt_count();
+       bit = trace_test_and_set_recursion(TRACE_FTRACE_START, TRACE_FTRACE_MAX);
+       if (bit < 0)
+               goto out;
+
+       cpu = smp_processor_id();
+       data = tr->data[cpu];
+       if (!atomic_read(&data->disabled)) {
+               local_save_flags(flags);
                trace_function(tr, ip, parent_ip, flags, pc);
        }
+       trace_clear_recursion(bit);
 
-       atomic_dec(&data->disabled);
-       local_irq_restore(flags);
+ out:
+       preempt_enable_notrace();
 }
 
 static void
@@ -185,11 +157,6 @@ static void tracing_start_function_trace(void)
 {
        ftrace_function_enabled = 0;
 
-       if (trace_flags & TRACE_ITER_PREEMPTONLY)
-               trace_ops.func = function_trace_call_preempt_only;
-       else
-               trace_ops.func = function_trace_call;
-
        if (func_flags.val & TRACE_FUNC_OPT_STACK)
                register_ftrace_function(&trace_stack_ops);
        else
index 4edb4b74eb7e75ba171240882b20ee14fbb41099..39ada66389ccce96a92a17d5eba63bbb7fe37e63 100644 (file)
@@ -47,6 +47,8 @@ struct fgraph_data {
 #define TRACE_GRAPH_PRINT_ABS_TIME     0x20
 #define TRACE_GRAPH_PRINT_IRQS         0x40
 
+static unsigned int max_depth;
+
 static struct tracer_opt trace_opts[] = {
        /* Display overruns? (for self-debug purpose) */
        { TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
@@ -189,10 +191,16 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 
        ftrace_pop_return_trace(&trace, &ret, frame_pointer);
        trace.rettime = trace_clock_local();
-       ftrace_graph_return(&trace);
        barrier();
        current->curr_ret_stack--;
 
+       /*
+        * The trace should run after decrementing the ret counter
+        * in case an interrupt were to come in. We don't want to
+        * lose the interrupt if max_depth is set.
+        */
+       ftrace_graph_return(&trace);
+
        if (unlikely(!ret)) {
                ftrace_graph_stop();
                WARN_ON(1);
@@ -250,8 +258,9 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
                return 0;
 
        /* trace it when it is-nested-in or is a function enabled. */
-       if (!(trace->depth || ftrace_graph_addr(trace->func)) ||
-             ftrace_graph_ignore_irqs())
+       if ((!(trace->depth || ftrace_graph_addr(trace->func)) ||
+            ftrace_graph_ignore_irqs()) ||
+           (max_depth && trace->depth >= max_depth))
                return 0;
 
        local_irq_save(flags);
@@ -1457,6 +1466,59 @@ static struct tracer graph_trace __read_mostly = {
 #endif
 };
 
+
+static ssize_t
+graph_depth_write(struct file *filp, const char __user *ubuf, size_t cnt,
+                 loff_t *ppos)
+{
+       unsigned long val;
+       int ret;
+
+       ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+       if (ret)
+               return ret;
+
+       max_depth = val;
+
+       *ppos += cnt;
+
+       return cnt;
+}
+
+static ssize_t
+graph_depth_read(struct file *filp, char __user *ubuf, size_t cnt,
+                loff_t *ppos)
+{
+       char buf[15]; /* More than enough to hold UINT_MAX + "\n"*/
+       int n;
+
+       n = sprintf(buf, "%d\n", max_depth);
+
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
+}
+
+static const struct file_operations graph_depth_fops = {
+       .open           = tracing_open_generic,
+       .write          = graph_depth_write,
+       .read           = graph_depth_read,
+       .llseek         = generic_file_llseek,
+};
+
+static __init int init_graph_debugfs(void)
+{
+       struct dentry *d_tracer;
+
+       d_tracer = tracing_init_dentry();
+       if (!d_tracer)
+               return 0;
+
+       trace_create_file("max_graph_depth", 0644, d_tracer,
+                         NULL, &graph_depth_fops);
+
+       return 0;
+}
+fs_initcall(init_graph_debugfs);
+
 static __init int init_graph_trace(void)
 {
        max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1);
index 933708677814573c5c133b96574a919e842963ec..5c7e09d10d74d54638a0d845ca0d5c5f1a328f12 100644 (file)
@@ -66,7 +66,6 @@
 #define TP_FLAG_TRACE          1
 #define TP_FLAG_PROFILE                2
 #define TP_FLAG_REGISTERED     4
-#define TP_FLAG_UPROBE         8
 
 
 /* data_rloc: data relative location, compatible with u32 */
index 9fe45fcefca084b804b37d8a4f782fdafa87f1bb..75aa97fbe1a11120d93ed241e00ddbac5a51a55d 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
+#include <linux/sched/rt.h>
 #include <trace/events/sched.h>
-
 #include "trace.h"
 
 static struct trace_array      *wakeup_trace;
index 47623169a815def678e012083aa70a21fd7c8ec9..51c819c12c2916c8e93226c79d3fc464dc190ec3 100644 (file)
@@ -415,7 +415,8 @@ static void trace_selftest_test_recursion_func(unsigned long ip,
         * The ftrace infrastructure should provide the recursion
         * protection. If not, this will crash the kernel!
         */
-       trace_selftest_recursion_cnt++;
+       if (trace_selftest_recursion_cnt++ > 10)
+               return;
        DYN_FTRACE_TEST_NAME();
 }
 
@@ -452,7 +453,6 @@ trace_selftest_function_recursion(void)
        char *func_name;
        int len;
        int ret;
-       int cnt;
 
        /* The previous test PASSED */
        pr_cont("PASSED\n");
@@ -510,19 +510,10 @@ trace_selftest_function_recursion(void)
 
        unregister_ftrace_function(&test_recsafe_probe);
 
-       /*
-        * If arch supports all ftrace features, and no other task
-        * was on the list, we should be fine.
-        */
-       if (!ftrace_nr_registered_ops() && !FTRACE_FORCE_LIST_FUNC)
-               cnt = 2; /* Should have recursed */
-       else
-               cnt = 1;
-
        ret = -1;
-       if (trace_selftest_recursion_cnt != cnt) {
-               pr_cont("*callback not called expected %d times (%d)* ",
-                       cnt, trace_selftest_recursion_cnt);
+       if (trace_selftest_recursion_cnt != 2) {
+               pr_cont("*callback not called expected 2 times (%d)* ",
+                       trace_selftest_recursion_cnt);
                goto out;
        }
 
@@ -568,7 +559,7 @@ trace_selftest_function_regs(void)
        int ret;
        int supported = 0;
 
-#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
        supported = 1;
 #endif
 
index 7609dd6714c2acc1a8862a47fbb014ef4f50e1c2..5329e13e74a13816969771b421852916f8bc3a50 100644 (file)
@@ -77,7 +77,7 @@ static struct syscall_metadata *syscall_nr_to_meta(int nr)
        return syscalls_metadata[nr];
 }
 
-enum print_line_t
+static enum print_line_t
 print_syscall_enter(struct trace_iterator *iter, int flags,
                    struct trace_event *event)
 {
@@ -130,7 +130,7 @@ end:
        return TRACE_TYPE_HANDLED;
 }
 
-enum print_line_t
+static enum print_line_t
 print_syscall_exit(struct trace_iterator *iter, int flags,
                   struct trace_event *event)
 {
@@ -270,7 +270,7 @@ static int syscall_exit_define_fields(struct ftrace_event_call *call)
        return ret;
 }
 
-void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
+static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
 {
        struct syscall_trace_enter *entry;
        struct syscall_metadata *sys_data;
@@ -305,7 +305,7 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
                trace_current_buffer_unlock_commit(buffer, event, 0, 0);
 }
 
-void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
+static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
 {
        struct syscall_trace_exit *entry;
        struct syscall_metadata *sys_data;
@@ -337,7 +337,7 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
                trace_current_buffer_unlock_commit(buffer, event, 0, 0);
 }
 
-int reg_event_syscall_enter(struct ftrace_event_call *call)
+static int reg_event_syscall_enter(struct ftrace_event_call *call)
 {
        int ret = 0;
        int num;
@@ -356,7 +356,7 @@ int reg_event_syscall_enter(struct ftrace_event_call *call)
        return ret;
 }
 
-void unreg_event_syscall_enter(struct ftrace_event_call *call)
+static void unreg_event_syscall_enter(struct ftrace_event_call *call)
 {
        int num;
 
@@ -371,7 +371,7 @@ void unreg_event_syscall_enter(struct ftrace_event_call *call)
        mutex_unlock(&syscall_trace_lock);
 }
 
-int reg_event_syscall_exit(struct ftrace_event_call *call)
+static int reg_event_syscall_exit(struct ftrace_event_call *call)
 {
        int ret = 0;
        int num;
@@ -390,7 +390,7 @@ int reg_event_syscall_exit(struct ftrace_event_call *call)
        return ret;
 }
 
-void unreg_event_syscall_exit(struct ftrace_event_call *call)
+static void unreg_event_syscall_exit(struct ftrace_event_call *call)
 {
        int num;
 
@@ -459,7 +459,7 @@ unsigned long __init __weak arch_syscall_addr(int nr)
        return (unsigned long)sys_call_table[nr];
 }
 
-int __init init_ftrace_syscalls(void)
+static int __init init_ftrace_syscalls(void)
 {
        struct syscall_metadata *meta;
        unsigned long addr;
index c86e6d4f67fbfac4a81c6c58d7194afa7603f7e5..8dad2a92dee9c9fff297d62edfe72147a1b371e4 100644 (file)
 
 #define UPROBE_EVENT_SYSTEM    "uprobes"
 
+struct trace_uprobe_filter {
+       rwlock_t                rwlock;
+       int                     nr_systemwide;
+       struct list_head        perf_events;
+};
+
 /*
  * uprobe event core functions
  */
-struct trace_uprobe;
-struct uprobe_trace_consumer {
-       struct uprobe_consumer          cons;
-       struct trace_uprobe             *tu;
-};
-
 struct trace_uprobe {
        struct list_head                list;
        struct ftrace_event_class       class;
        struct ftrace_event_call        call;
-       struct uprobe_trace_consumer    *consumer;
+       struct trace_uprobe_filter      filter;
+       struct uprobe_consumer          consumer;
        struct inode                    *inode;
        char                            *filename;
        unsigned long                   offset;
@@ -64,6 +65,18 @@ static LIST_HEAD(uprobe_list);
 
 static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
 
+static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter)
+{
+       rwlock_init(&filter->rwlock);
+       filter->nr_systemwide = 0;
+       INIT_LIST_HEAD(&filter->perf_events);
+}
+
+static inline bool uprobe_filter_is_empty(struct trace_uprobe_filter *filter)
+{
+       return !filter->nr_systemwide && list_empty(&filter->perf_events);
+}
+
 /*
  * Allocate new trace_uprobe and initialize it (including uprobes).
  */
@@ -92,6 +105,8 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs)
                goto error;
 
        INIT_LIST_HEAD(&tu->list);
+       tu->consumer.handler = uprobe_dispatcher;
+       init_trace_uprobe_filter(&tu->filter);
        return tu;
 
 error:
@@ -253,12 +268,18 @@ static int create_trace_uprobe(int argc, char **argv)
        if (ret)
                goto fail_address_parse;
 
+       inode = igrab(path.dentry->d_inode);
+       path_put(&path);
+
+       if (!inode || !S_ISREG(inode->i_mode)) {
+               ret = -EINVAL;
+               goto fail_address_parse;
+       }
+
        ret = kstrtoul(arg, 0, &offset);
        if (ret)
                goto fail_address_parse;
 
-       inode = igrab(path.dentry->d_inode);
-
        argc -= 2;
        argv += 2;
 
@@ -356,7 +377,7 @@ fail_address_parse:
        if (inode)
                iput(inode);
 
-       pr_info("Failed to parse address.\n");
+       pr_info("Failed to parse address or file.\n");
 
        return ret;
 }
@@ -465,7 +486,7 @@ static const struct file_operations uprobe_profile_ops = {
 };
 
 /* uprobe handler */
-static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
+static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
 {
        struct uprobe_trace_entry_head *entry;
        struct ring_buffer_event *event;
@@ -475,8 +496,6 @@ static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
        unsigned long irq_flags;
        struct ftrace_event_call *call = &tu->call;
 
-       tu->nhit++;
-
        local_save_flags(irq_flags);
        pc = preempt_count();
 
@@ -485,16 +504,18 @@ static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
        event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
                                                  size, irq_flags, pc);
        if (!event)
-               return;
+               return 0;
 
        entry = ring_buffer_event_data(event);
-       entry->ip = uprobe_get_swbp_addr(task_pt_regs(current));
+       entry->ip = instruction_pointer(task_pt_regs(current));
        data = (u8 *)&entry[1];
        for (i = 0; i < tu->nr_args; i++)
                call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset);
 
        if (!filter_current_check_discard(buffer, call, entry, event))
                trace_buffer_unlock_commit(buffer, event, irq_flags, pc);
+
+       return 0;
 }
 
 /* Event entry printers */
@@ -533,42 +554,43 @@ partial:
        return TRACE_TYPE_PARTIAL_LINE;
 }
 
-static int probe_event_enable(struct trace_uprobe *tu, int flag)
+static inline bool is_trace_uprobe_enabled(struct trace_uprobe *tu)
 {
-       struct uprobe_trace_consumer *utc;
-       int ret = 0;
+       return tu->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE);
+}
 
-       if (!tu->inode || tu->consumer)
-               return -EINTR;
+typedef bool (*filter_func_t)(struct uprobe_consumer *self,
+                               enum uprobe_filter_ctx ctx,
+                               struct mm_struct *mm);
 
-       utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
-       if (!utc)
+static int
+probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter)
+{
+       int ret = 0;
+
+       if (is_trace_uprobe_enabled(tu))
                return -EINTR;
 
-       utc->cons.handler = uprobe_dispatcher;
-       utc->cons.filter = NULL;
-       ret = uprobe_register(tu->inode, tu->offset, &utc->cons);
-       if (ret) {
-               kfree(utc);
-               return ret;
-       }
+       WARN_ON(!uprobe_filter_is_empty(&tu->filter));
 
        tu->flags |= flag;
-       utc->tu = tu;
-       tu->consumer = utc;
+       tu->consumer.filter = filter;
+       ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
+       if (ret)
+               tu->flags &= ~flag;
 
-       return 0;
+       return ret;
 }
 
 static void probe_event_disable(struct trace_uprobe *tu, int flag)
 {
-       if (!tu->inode || !tu->consumer)
+       if (!is_trace_uprobe_enabled(tu))
                return;
 
-       uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons);
+       WARN_ON(!uprobe_filter_is_empty(&tu->filter));
+
+       uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
        tu->flags &= ~flag;
-       kfree(tu->consumer);
-       tu->consumer = NULL;
 }
 
 static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
@@ -642,8 +664,96 @@ static int set_print_fmt(struct trace_uprobe *tu)
 }
 
 #ifdef CONFIG_PERF_EVENTS
+static bool
+__uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
+{
+       struct perf_event *event;
+
+       if (filter->nr_systemwide)
+               return true;
+
+       list_for_each_entry(event, &filter->perf_events, hw.tp_list) {
+               if (event->hw.tp_target->mm == mm)
+                       return true;
+       }
+
+       return false;
+}
+
+static inline bool
+uprobe_filter_event(struct trace_uprobe *tu, struct perf_event *event)
+{
+       return __uprobe_perf_filter(&tu->filter, event->hw.tp_target->mm);
+}
+
+static int uprobe_perf_open(struct trace_uprobe *tu, struct perf_event *event)
+{
+       bool done;
+
+       write_lock(&tu->filter.rwlock);
+       if (event->hw.tp_target) {
+               /*
+                * event->parent != NULL means copy_process(), we can avoid
+                * uprobe_apply(). current->mm must be probed and we can rely
+                * on dup_mmap() which preserves the already installed bp's.
+                *
+                * attr.enable_on_exec means that exec/mmap will install the
+                * breakpoints we need.
+                */
+               done = tu->filter.nr_systemwide ||
+                       event->parent || event->attr.enable_on_exec ||
+                       uprobe_filter_event(tu, event);
+               list_add(&event->hw.tp_list, &tu->filter.perf_events);
+       } else {
+               done = tu->filter.nr_systemwide;
+               tu->filter.nr_systemwide++;
+       }
+       write_unlock(&tu->filter.rwlock);
+
+       if (!done)
+               uprobe_apply(tu->inode, tu->offset, &tu->consumer, true);
+
+       return 0;
+}
+
+static int uprobe_perf_close(struct trace_uprobe *tu, struct perf_event *event)
+{
+       bool done;
+
+       write_lock(&tu->filter.rwlock);
+       if (event->hw.tp_target) {
+               list_del(&event->hw.tp_list);
+               done = tu->filter.nr_systemwide ||
+                       (event->hw.tp_target->flags & PF_EXITING) ||
+                       uprobe_filter_event(tu, event);
+       } else {
+               tu->filter.nr_systemwide--;
+               done = tu->filter.nr_systemwide;
+       }
+       write_unlock(&tu->filter.rwlock);
+
+       if (!done)
+               uprobe_apply(tu->inode, tu->offset, &tu->consumer, false);
+
+       return 0;
+}
+
+static bool uprobe_perf_filter(struct uprobe_consumer *uc,
+                               enum uprobe_filter_ctx ctx, struct mm_struct *mm)
+{
+       struct trace_uprobe *tu;
+       int ret;
+
+       tu = container_of(uc, struct trace_uprobe, consumer);
+       read_lock(&tu->filter.rwlock);
+       ret = __uprobe_perf_filter(&tu->filter, mm);
+       read_unlock(&tu->filter.rwlock);
+
+       return ret;
+}
+
 /* uprobe profile handler */
-static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
+static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
 {
        struct ftrace_event_call *call = &tu->call;
        struct uprobe_trace_entry_head *entry;
@@ -652,11 +762,14 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
        int size, __size, i;
        int rctx;
 
+       if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
+               return UPROBE_HANDLER_REMOVE;
+
        __size = sizeof(*entry) + tu->size;
        size = ALIGN(__size + sizeof(u32), sizeof(u64));
        size -= sizeof(u32);
        if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
-               return;
+               return 0;
 
        preempt_disable();
 
@@ -664,7 +777,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
        if (!entry)
                goto out;
 
-       entry->ip = uprobe_get_swbp_addr(task_pt_regs(current));
+       entry->ip = instruction_pointer(task_pt_regs(current));
        data = (u8 *)&entry[1];
        for (i = 0; i < tu->nr_args; i++)
                call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset);
@@ -674,6 +787,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
 
  out:
        preempt_enable();
+       return 0;
 }
 #endif /* CONFIG_PERF_EVENTS */
 
@@ -684,7 +798,7 @@ int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type,
 
        switch (type) {
        case TRACE_REG_REGISTER:
-               return probe_event_enable(tu, TP_FLAG_TRACE);
+               return probe_event_enable(tu, TP_FLAG_TRACE, NULL);
 
        case TRACE_REG_UNREGISTER:
                probe_event_disable(tu, TP_FLAG_TRACE);
@@ -692,11 +806,18 @@ int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type,
 
 #ifdef CONFIG_PERF_EVENTS
        case TRACE_REG_PERF_REGISTER:
-               return probe_event_enable(tu, TP_FLAG_PROFILE);
+               return probe_event_enable(tu, TP_FLAG_PROFILE, uprobe_perf_filter);
 
        case TRACE_REG_PERF_UNREGISTER:
                probe_event_disable(tu, TP_FLAG_PROFILE);
                return 0;
+
+       case TRACE_REG_PERF_OPEN:
+               return uprobe_perf_open(tu, data);
+
+       case TRACE_REG_PERF_CLOSE:
+               return uprobe_perf_close(tu, data);
+
 #endif
        default:
                return 0;
@@ -706,22 +827,20 @@ int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type,
 
 static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
 {
-       struct uprobe_trace_consumer *utc;
        struct trace_uprobe *tu;
+       int ret = 0;
 
-       utc = container_of(con, struct uprobe_trace_consumer, cons);
-       tu = utc->tu;
-       if (!tu || tu->consumer != utc)
-               return 0;
+       tu = container_of(con, struct trace_uprobe, consumer);
+       tu->nhit++;
 
        if (tu->flags & TP_FLAG_TRACE)
-               uprobe_trace_func(tu, regs);
+               ret |= uprobe_trace_func(tu, regs);
 
 #ifdef CONFIG_PERF_EVENTS
        if (tu->flags & TP_FLAG_PROFILE)
-               uprobe_perf_func(tu, regs);
+               ret |= uprobe_perf_func(tu, regs);
 #endif
-       return 0;
+       return ret;
 }
 
 static struct trace_event_functions uprobe_funcs = {
index 625df0b44690a67a1ca6d5f6e7f264fc1ac28fb5..a1dd9a1b1327e9121265cb681b4b483a375b163a 100644 (file)
@@ -32,6 +32,7 @@ void bacct_add_tsk(struct user_namespace *user_ns,
 {
        const struct cred *tcred;
        struct timespec uptime, ts;
+       cputime_t utime, stime, utimescaled, stimescaled;
        u64 ac_etime;
 
        BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN);
@@ -65,10 +66,15 @@ void bacct_add_tsk(struct user_namespace *user_ns,
        stats->ac_ppid   = pid_alive(tsk) ?
                task_tgid_nr_ns(rcu_dereference(tsk->real_parent), pid_ns) : 0;
        rcu_read_unlock();
-       stats->ac_utime = cputime_to_usecs(tsk->utime);
-       stats->ac_stime = cputime_to_usecs(tsk->stime);
-       stats->ac_utimescaled = cputime_to_usecs(tsk->utimescaled);
-       stats->ac_stimescaled = cputime_to_usecs(tsk->stimescaled);
+
+       task_cputime(tsk, &utime, &stime);
+       stats->ac_utime = cputime_to_usecs(utime);
+       stats->ac_stime = cputime_to_usecs(stime);
+
+       task_cputime_scaled(tsk, &utimescaled, &stimescaled);
+       stats->ac_utimescaled = cputime_to_usecs(utimescaled);
+       stats->ac_stimescaled = cputime_to_usecs(stimescaled);
+
        stats->ac_minflt = tsk->min_flt;
        stats->ac_majflt = tsk->maj_flt;
 
@@ -115,11 +121,8 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 #undef KB
 #undef MB
 
-/**
- * acct_update_integrals - update mm integral fields in task_struct
- * @tsk: task_struct for accounting
- */
-void acct_update_integrals(struct task_struct *tsk)
+static void __acct_update_integrals(struct task_struct *tsk,
+                                   cputime_t utime, cputime_t stime)
 {
        if (likely(tsk->mm)) {
                cputime_t time, dtime;
@@ -128,7 +131,7 @@ void acct_update_integrals(struct task_struct *tsk)
                u64 delta;
 
                local_irq_save(flags);
-               time = tsk->stime + tsk->utime;
+               time = stime + utime;
                dtime = time - tsk->acct_timexpd;
                jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
                delta = value.tv_sec;
@@ -144,6 +147,27 @@ void acct_update_integrals(struct task_struct *tsk)
        }
 }
 
+/**
+ * acct_update_integrals - update mm integral fields in task_struct
+ * @tsk: task_struct for accounting
+ */
+void acct_update_integrals(struct task_struct *tsk)
+{
+       cputime_t utime, stime;
+
+       task_cputime(tsk, &utime, &stime);
+       __acct_update_integrals(tsk, utime, stime);
+}
+
+/**
+ * acct_account_cputime - update mm integral after cputime update
+ * @tsk: task_struct for accounting
+ */
+void acct_account_cputime(struct task_struct *tsk)
+{
+       __acct_update_integrals(tsk, tsk->utime, tsk->stime);
+}
+
 /**
  * acct_clear_integrals - clear the mm integral fields in task_struct
  * @tsk: task_struct whose accounting fields are cleared
index 75a2ab3d0b0208dfa51e40339ffd00206622732e..27689422aa9284274f3514286dfafc6da04b2880 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/sysctl.h>
 #include <linux/smpboot.h>
+#include <linux/sched/rt.h>
 
 #include <asm/irq_regs.h>
 #include <linux/kvm_para.h>
index 3a353091a90390f6b95b632408797d14908d57f3..a1714c897e3f185778ece70c9797063968dd4d4f 100644 (file)
@@ -134,7 +134,7 @@ config DEBUG_SECTION_MISMATCH
          any use of code/data previously in these sections would
          most likely result in an oops.
          In the code, functions and variables are annotated with
-         __init, __devinit, etc. (see the full list in include/linux/init.h),
+         __init, __cpuinit, etc. (see the full list in include/linux/init.h),
          which results in the code/data being placed in specific sections.
          The section mismatch analysis is always performed after a full
          kernel build, and enabling this option causes the following
@@ -605,61 +605,6 @@ config PROVE_LOCKING
 
         For more details, see Documentation/lockdep-design.txt.
 
-config PROVE_RCU
-       bool "RCU debugging: prove RCU correctness"
-       depends on PROVE_LOCKING
-       default n
-       help
-        This feature enables lockdep extensions that check for correct
-        use of RCU APIs.  This is currently under development.  Say Y
-        if you want to debug RCU usage or help work on the PROVE_RCU
-        feature.
-
-        Say N if you are unsure.
-
-config PROVE_RCU_REPEATEDLY
-       bool "RCU debugging: don't disable PROVE_RCU on first splat"
-       depends on PROVE_RCU
-       default n
-       help
-        By itself, PROVE_RCU will disable checking upon issuing the
-        first warning (or "splat").  This feature prevents such
-        disabling, allowing multiple RCU-lockdep warnings to be printed
-        on a single reboot.
-
-        Say Y to allow multiple RCU-lockdep warnings per boot.
-
-        Say N if you are unsure.
-
-config PROVE_RCU_DELAY
-       bool "RCU debugging: preemptible RCU race provocation"
-       depends on DEBUG_KERNEL && PREEMPT_RCU
-       default n
-       help
-        There is a class of races that involve an unlikely preemption
-        of __rcu_read_unlock() just after ->rcu_read_lock_nesting has
-        been set to INT_MIN.  This feature inserts a delay at that
-        point to increase the probability of these races.
-
-        Say Y to increase probability of preemption of __rcu_read_unlock().
-
-        Say N if you are unsure.
-
-config SPARSE_RCU_POINTER
-       bool "RCU debugging: sparse-based checks for pointer usage"
-       default n
-       help
-        This feature enables the __rcu sparse annotation for
-        RCU-protected pointers.  This annotation will cause sparse
-        to flag any non-RCU used of annotated pointers.  This can be
-        helpful when debugging RCU usage.  Please note that this feature
-        is not intended to enforce code cleanliness; it is instead merely
-        a debugging aid.
-
-        Say Y to make sparse flag questionable use of RCU-protected pointers
-
-        Say N if you are unsure.
-
 config LOCKDEP
        bool
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@ -937,6 +882,63 @@ config BOOT_PRINTK_DELAY
          BOOT_PRINTK_DELAY also may cause LOCKUP_DETECTOR to detect
          what it believes to be lockup conditions.
 
+menu "RCU Debugging"
+
+config PROVE_RCU
+       bool "RCU debugging: prove RCU correctness"
+       depends on PROVE_LOCKING
+       default n
+       help
+        This feature enables lockdep extensions that check for correct
+        use of RCU APIs.  This is currently under development.  Say Y
+        if you want to debug RCU usage or help work on the PROVE_RCU
+        feature.
+
+        Say N if you are unsure.
+
+config PROVE_RCU_REPEATEDLY
+       bool "RCU debugging: don't disable PROVE_RCU on first splat"
+       depends on PROVE_RCU
+       default n
+       help
+        By itself, PROVE_RCU will disable checking upon issuing the
+        first warning (or "splat").  This feature prevents such
+        disabling, allowing multiple RCU-lockdep warnings to be printed
+        on a single reboot.
+
+        Say Y to allow multiple RCU-lockdep warnings per boot.
+
+        Say N if you are unsure.
+
+config PROVE_RCU_DELAY
+       bool "RCU debugging: preemptible RCU race provocation"
+       depends on DEBUG_KERNEL && PREEMPT_RCU
+       default n
+       help
+        There is a class of races that involve an unlikely preemption
+        of __rcu_read_unlock() just after ->rcu_read_lock_nesting has
+        been set to INT_MIN.  This feature inserts a delay at that
+        point to increase the probability of these races.
+
+        Say Y to increase probability of preemption of __rcu_read_unlock().
+
+        Say N if you are unsure.
+
+config SPARSE_RCU_POINTER
+       bool "RCU debugging: sparse-based checks for pointer usage"
+       default n
+       help
+        This feature enables the __rcu sparse annotation for
+        RCU-protected pointers.  This annotation will cause sparse
+        to flag any non-RCU used of annotated pointers.  This can be
+        helpful when debugging RCU usage.  Please note that this feature
+        is not intended to enforce code cleanliness; it is instead merely
+        a debugging aid.
+
+        Say Y to make sparse flag questionable use of RCU-protected pointers
+
+        Say N if you are unsure.
+
 config RCU_TORTURE_TEST
        tristate "torture tests for RCU"
        depends on DEBUG_KERNEL
@@ -970,7 +972,7 @@ config RCU_TORTURE_TEST_RUNNABLE
 
 config RCU_CPU_STALL_TIMEOUT
        int "RCU CPU stall timeout in seconds"
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on RCU_STALL_COMMON
        range 3 300
        default 21
        help
@@ -1008,6 +1010,7 @@ config RCU_CPU_STALL_INFO
 config RCU_TRACE
        bool "Enable tracing for RCU"
        depends on DEBUG_KERNEL
+       select TRACE_CLOCK
        help
          This option provides tracing in RCU which presents stats
          in debugfs for debugging RCU implementation.
@@ -1015,6 +1018,8 @@ config RCU_TRACE
          Say Y here if you want to enable RCU tracing
          Say N if you are unsure.
 
+endmenu # "RCU Debugging"
+
 config KPROBES_SANITY_TEST
        bool "Kprobes sanity tests"
        depends on DEBUG_KERNEL
index 978537809d84c4c18c469e1a38005872cdf165f1..08a4f068e61e7689f4246ec77683d71b18f72a76 100644 (file)
 static union {
        raw_spinlock_t lock;
        char pad[L1_CACHE_BYTES];
-} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp;
+} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp = {
+       [0 ... (NR_LOCKS - 1)] = {
+               .lock =  __RAW_SPIN_LOCK_UNLOCKED(atomic64_lock.lock),
+       },
+};
 
 static inline raw_spinlock_t *lock_addr(const atomic64_t *v)
 {
@@ -173,14 +177,3 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u)
        return ret;
 }
 EXPORT_SYMBOL(atomic64_add_unless);
-
-static int init_atomic64_lock(void)
-{
-       int i;
-
-       for (i = 0; i < NR_LOCKS; ++i)
-               raw_spin_lock_init(&atomic64_lock[i].lock);
-       return 0;
-}
-
-pure_initcall(init_atomic64_lock);
index a28c1415357cac9d30fc09195652fbfd099bc421..d0cdf14c651ae629cba6731debb3b6a5edee39bf 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -55,6 +55,7 @@ static inline unsigned long bug_addr(const struct bug_entry *bug)
 }
 
 #ifdef CONFIG_MODULES
+/* Updates are protected by module mutex */
 static LIST_HEAD(module_bug_list);
 
 static const struct bug_entry *module_find_bug(unsigned long bugaddr)
index 145dec5267c91a6989402acc51ec50895e488988..5fbed5caba6e833222a62952cb4ba6e3430c053e 100644 (file)
@@ -45,6 +45,7 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags)
        if (!rmap)
                return NULL;
 
+       kref_init(&rmap->refcount);
        rmap->obj = (void **)((char *)rmap + obj_offset);
 
        /* Initially assign CPUs to objects on a rota, since we have
@@ -63,6 +64,35 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags)
 }
 EXPORT_SYMBOL(alloc_cpu_rmap);
 
+/**
+ * cpu_rmap_release - internal reclaiming helper called from kref_put
+ * @ref: kref to struct cpu_rmap
+ */
+static void cpu_rmap_release(struct kref *ref)
+{
+       struct cpu_rmap *rmap = container_of(ref, struct cpu_rmap, refcount);
+       kfree(rmap);
+}
+
+/**
+ * cpu_rmap_get - internal helper to get new ref on a cpu_rmap
+ * @rmap: reverse-map allocated with alloc_cpu_rmap()
+ */
+static inline void cpu_rmap_get(struct cpu_rmap *rmap)
+{
+       kref_get(&rmap->refcount);
+}
+
+/**
+ * cpu_rmap_put - release ref on a cpu_rmap
+ * @rmap: reverse-map allocated with alloc_cpu_rmap()
+ */
+int cpu_rmap_put(struct cpu_rmap *rmap)
+{
+       return kref_put(&rmap->refcount, cpu_rmap_release);
+}
+EXPORT_SYMBOL(cpu_rmap_put);
+
 /* Reevaluate nearest object for given CPU, comparing with the given
  * neighbours at the given distance.
  */
@@ -197,8 +227,7 @@ struct irq_glue {
  * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs
  * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL
  *
- * Must be called in process context, before freeing the IRQs, and
- * without holding any locks required by global workqueue items.
+ * Must be called in process context, before freeing the IRQs.
  */
 void free_irq_cpu_rmap(struct cpu_rmap *rmap)
 {
@@ -212,12 +241,18 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap)
                glue = rmap->obj[index];
                irq_set_affinity_notifier(glue->notify.irq, NULL);
        }
-       irq_run_affinity_notifiers();
 
-       kfree(rmap);
+       cpu_rmap_put(rmap);
 }
 EXPORT_SYMBOL(free_irq_cpu_rmap);
 
+/**
+ * irq_cpu_rmap_notify - callback for IRQ subsystem when IRQ affinity updated
+ * @notify: struct irq_affinity_notify passed by irq/manage.c
+ * @mask: cpu mask for new SMP affinity
+ *
+ * This is executed in workqueue context.
+ */
 static void
 irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask)
 {
@@ -230,10 +265,16 @@ irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask)
                pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc);
 }
 
+/**
+ * irq_cpu_rmap_release - reclaiming callback for IRQ subsystem
+ * @ref: kref to struct irq_affinity_notify passed by irq/manage.c
+ */
 static void irq_cpu_rmap_release(struct kref *ref)
 {
        struct irq_glue *glue =
                container_of(ref, struct irq_glue, notify.kref);
+
+       cpu_rmap_put(glue->rmap);
        kfree(glue);
 }
 
@@ -258,10 +299,13 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
        glue->notify.notify = irq_cpu_rmap_notify;
        glue->notify.release = irq_cpu_rmap_release;
        glue->rmap = rmap;
+       cpu_rmap_get(rmap);
        glue->index = cpu_rmap_add(rmap, glue);
        rc = irq_set_affinity_notifier(irq, &glue->notify);
-       if (rc)
+       if (rc) {
+               cpu_rmap_put(glue->rmap);
                kfree(glue);
+       }
        return rc;
 }
 EXPORT_SYMBOL(irq_cpu_rmap_add);
index 8c0e62975c88d49a09c9c29ab9e7a2b1334a6587..dc2be7ed1765b0dc3675c97b2cf862dc969dcd90 100644 (file)
@@ -162,6 +162,8 @@ static int digsig_verify_rsa(struct key *key,
        memset(out1, 0, head);
        memcpy(out1 + head, p, l);
 
+       kfree(p);
+
        err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
        if (err)
                goto err;
index 4f56a11d67fa9da105b34337280277d6fe437b2e..c0e31fe2fabf5b99c160fb01daf618cb7c0488b3 100644 (file)
@@ -194,8 +194,12 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
        }
 }
 
-__always_inline void
-__rb_erase_color(struct rb_node *parent, struct rb_root *root,
+/*
+ * Inline version for rb_erase() use - we want to be able to inline
+ * and eliminate the dummy_rotate callback there
+ */
+static __always_inline void
+____rb_erase_color(struct rb_node *parent, struct rb_root *root,
        void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
 {
        struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
@@ -355,6 +359,13 @@ __rb_erase_color(struct rb_node *parent, struct rb_root *root,
                }
        }
 }
+
+/* Non-inline version for rb_erase_augmented() use */
+void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
+       void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+       ____rb_erase_color(parent, root, augment_rotate);
+}
 EXPORT_SYMBOL(__rb_erase_color);
 
 /*
@@ -380,7 +391,10 @@ EXPORT_SYMBOL(rb_insert_color);
 
 void rb_erase(struct rb_node *node, struct rb_root *root)
 {
-       rb_erase_augmented(node, root, &dummy_callbacks);
+       struct rb_node *rebalance;
+       rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
+       if (rebalance)
+               ____rb_erase_color(rebalance, root, dummy_rotate);
 }
 EXPORT_SYMBOL(rb_erase);
 
index 1324cd74faec45dc2b0ba4f0b3fb0659640e9f25..b93376c39b61308fe2ef7de2466e83306c865cf9 100644 (file)
@@ -185,10 +185,23 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 
        while (start < end) {
                unsigned long *map, idx, vec;
+               unsigned shift;
 
                map = bdata->node_bootmem_map;
                idx = start - bdata->node_min_pfn;
+               shift = idx & (BITS_PER_LONG - 1);
+               /*
+                * vec holds at most BITS_PER_LONG map bits,
+                * bit 0 corresponds to start.
+                */
                vec = ~map[idx / BITS_PER_LONG];
+
+               if (shift) {
+                       vec >>= shift;
+                       if (end - start >= BITS_PER_LONG)
+                               vec |= ~map[idx / BITS_PER_LONG + 1] <<
+                                       (BITS_PER_LONG - shift);
+               }
                /*
                 * If we have a properly aligned and fully unreserved
                 * BITS_PER_LONG block of pages in front of us, free
@@ -201,19 +214,18 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                        count += BITS_PER_LONG;
                        start += BITS_PER_LONG;
                } else {
-                       unsigned long off = 0;
+                       unsigned long cur = start;
 
-                       vec >>= start & (BITS_PER_LONG - 1);
-                       while (vec) {
+                       start = ALIGN(start + 1, BITS_PER_LONG);
+                       while (vec && cur != start) {
                                if (vec & 1) {
-                                       page = pfn_to_page(start + off);
+                                       page = pfn_to_page(cur);
                                        __free_pages_bootmem(page, 0);
                                        count++;
                                }
                                vec >>= 1;
-                               off++;
+                               ++cur;
                        }
-                       start = ALIGN(start + 1, BITS_PER_LONG);
                }
        }
 
index 5ad7f4f4d6f7bb6c1f3710f68022fdc3148ade5f..c62bd063d766c7333ca0370444636a52ddc70802 100644 (file)
 #include <linux/balloon_compaction.h>
 #include "internal.h"
 
+#ifdef CONFIG_COMPACTION
+static inline void count_compact_event(enum vm_event_item item)
+{
+       count_vm_event(item);
+}
+
+static inline void count_compact_events(enum vm_event_item item, long delta)
+{
+       count_vm_events(item, delta);
+}
+#else
+#define count_compact_event(item) do { } while (0)
+#define count_compact_events(item, delta) do { } while (0)
+#endif
+
 #if defined CONFIG_COMPACTION || defined CONFIG_CMA
 
 #define CREATE_TRACE_POINTS
@@ -303,10 +318,9 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
        if (blockpfn == end_pfn)
                update_pageblock_skip(cc, valid_page, total_isolated, false);
 
-       count_vm_events(COMPACTFREE_SCANNED, nr_scanned);
+       count_compact_events(COMPACTFREE_SCANNED, nr_scanned);
        if (total_isolated)
-               count_vm_events(COMPACTISOLATED, total_isolated);
-
+               count_compact_events(COMPACTISOLATED, total_isolated);
        return total_isolated;
 }
 
@@ -613,9 +627,9 @@ next_pageblock:
 
        trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
 
-       count_vm_events(COMPACTMIGRATE_SCANNED, nr_scanned);
+       count_compact_events(COMPACTMIGRATE_SCANNED, nr_scanned);
        if (nr_isolated)
-               count_vm_events(COMPACTISOLATED, nr_isolated);
+               count_compact_events(COMPACTISOLATED, nr_isolated);
 
        return low_pfn;
 }
@@ -802,6 +816,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
 static int compact_finished(struct zone *zone,
                            struct compact_control *cc)
 {
+       unsigned int order;
        unsigned long watermark;
 
        if (fatal_signal_pending(current))
@@ -836,22 +851,16 @@ static int compact_finished(struct zone *zone,
                return COMPACT_CONTINUE;
 
        /* Direct compactor: Is a suitable page free? */
-       if (cc->page) {
-               /* Was a suitable page captured? */
-               if (*cc->page)
+       for (order = cc->order; order < MAX_ORDER; order++) {
+               struct free_area *area = &zone->free_area[order];
+
+               /* Job done if page is free of the right migratetype */
+               if (!list_empty(&area->free_list[cc->migratetype]))
+                       return COMPACT_PARTIAL;
+
+               /* Job done if allocation would set block type */
+               if (cc->order >= pageblock_order && area->nr_free)
                        return COMPACT_PARTIAL;
-       } else {
-               unsigned int order;
-               for (order = cc->order; order < MAX_ORDER; order++) {
-                       struct free_area *area = &zone->free_area[cc->order];
-                       /* Job done if page is free of the right migratetype */
-                       if (!list_empty(&area->free_list[cc->migratetype]))
-                               return COMPACT_PARTIAL;
-
-                       /* Job done if allocation would set block type */
-                       if (cc->order >= pageblock_order && area->nr_free)
-                               return COMPACT_PARTIAL;
-               }
        }
 
        return COMPACT_CONTINUE;
@@ -907,60 +916,6 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        return COMPACT_CONTINUE;
 }
 
-static void compact_capture_page(struct compact_control *cc)
-{
-       unsigned long flags;
-       int mtype, mtype_low, mtype_high;
-
-       if (!cc->page || *cc->page)
-               return;
-
-       /*
-        * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
-        * regardless of the migratetype of the freelist is is captured from.
-        * This is fine because the order for a high-order MIGRATE_MOVABLE
-        * allocation is typically at least a pageblock size and overall
-        * fragmentation is not impaired. Other allocation types must
-        * capture pages from their own migratelist because otherwise they
-        * could pollute other pageblocks like MIGRATE_MOVABLE with
-        * difficult to move pages and making fragmentation worse overall.
-        */
-       if (cc->migratetype == MIGRATE_MOVABLE) {
-               mtype_low = 0;
-               mtype_high = MIGRATE_PCPTYPES;
-       } else {
-               mtype_low = cc->migratetype;
-               mtype_high = cc->migratetype + 1;
-       }
-
-       /* Speculatively examine the free lists without zone lock */
-       for (mtype = mtype_low; mtype < mtype_high; mtype++) {
-               int order;
-               for (order = cc->order; order < MAX_ORDER; order++) {
-                       struct page *page;
-                       struct free_area *area;
-                       area = &(cc->zone->free_area[order]);
-                       if (list_empty(&area->free_list[mtype]))
-                               continue;
-
-                       /* Take the lock and attempt capture of the page */
-                       if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
-                               return;
-                       if (!list_empty(&area->free_list[mtype])) {
-                               page = list_entry(area->free_list[mtype].next,
-                                                       struct page, lru);
-                               if (capture_free_page(page, cc->order, mtype)) {
-                                       spin_unlock_irqrestore(&cc->zone->lock,
-                                                                       flags);
-                                       *cc->page = page;
-                                       return;
-                               }
-                       }
-                       spin_unlock_irqrestore(&cc->zone->lock, flags);
-               }
-       }
-}
-
 static int compact_zone(struct zone *zone, struct compact_control *cc)
 {
        int ret;
@@ -1040,9 +995,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                                goto out;
                        }
                }
-
-               /* Capture a page now if it is a suitable size */
-               compact_capture_page(cc);
        }
 
 out:
@@ -1055,8 +1007,7 @@ out:
 
 static unsigned long compact_zone_order(struct zone *zone,
                                 int order, gfp_t gfp_mask,
-                                bool sync, bool *contended,
-                                struct page **page)
+                                bool sync, bool *contended)
 {
        unsigned long ret;
        struct compact_control cc = {
@@ -1066,7 +1017,6 @@ static unsigned long compact_zone_order(struct zone *zone,
                .migratetype = allocflags_to_migratetype(gfp_mask),
                .zone = zone,
                .sync = sync,
-               .page = page,
        };
        INIT_LIST_HEAD(&cc.freepages);
        INIT_LIST_HEAD(&cc.migratepages);
@@ -1096,7 +1046,7 @@ int sysctl_extfrag_threshold = 500;
  */
 unsigned long try_to_compact_pages(struct zonelist *zonelist,
                        int order, gfp_t gfp_mask, nodemask_t *nodemask,
-                       bool sync, bool *contended, struct page **page)
+                       bool sync, bool *contended)
 {
        enum zone_type high_zoneidx = gfp_zone(gfp_mask);
        int may_enter_fs = gfp_mask & __GFP_FS;
@@ -1110,7 +1060,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
        if (!order || !may_enter_fs || !may_perform_io)
                return rc;
 
-       count_vm_event(COMPACTSTALL);
+       count_compact_event(COMPACTSTALL);
 
 #ifdef CONFIG_CMA
        if (allocflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE)
@@ -1122,7 +1072,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
                int status;
 
                status = compact_zone_order(zone, order, gfp_mask, sync,
-                                               contended, page);
+                                               contended);
                rc = max(status, rc);
 
                /* If a normal allocation would succeed, stop compacting */
@@ -1178,7 +1128,6 @@ int compact_pgdat(pg_data_t *pgdat, int order)
        struct compact_control cc = {
                .order = order,
                .sync = false,
-               .page = NULL,
        };
 
        return __compact_pgdat(pgdat, &cc);
@@ -1189,14 +1138,13 @@ static int compact_node(int nid)
        struct compact_control cc = {
                .order = -1,
                .sync = true,
-               .page = NULL,
        };
 
        return __compact_pgdat(NODE_DATA(nid), &cc);
 }
 
 /* Compact all nodes in the system */
-static int compact_nodes(void)
+static void compact_nodes(void)
 {
        int nid;
 
@@ -1205,8 +1153,6 @@ static int compact_nodes(void)
 
        for_each_online_node(nid)
                compact_node(nid);
-
-       return COMPACT_COMPLETE;
 }
 
 /* The written value is actually unused, all memory is compacted */
@@ -1217,7 +1163,7 @@ int sysctl_compaction_handler(struct ctl_table *table, int write,
                        void __user *buffer, size_t *length, loff_t *ppos)
 {
        if (write)
-               return compact_nodes();
+               compact_nodes();
 
        return 0;
 }
index 32754eece63e517a9cf124b3f24f619c83045f84..b5783d81eda90fc9a808478ac6dcea4f74b4424e 100644 (file)
@@ -574,19 +574,19 @@ static int __init hugepage_init_sysfs(struct kobject **hugepage_kobj)
 
        *hugepage_kobj = kobject_create_and_add("transparent_hugepage", mm_kobj);
        if (unlikely(!*hugepage_kobj)) {
-               printk(KERN_ERR "hugepage: failed kobject create\n");
+               printk(KERN_ERR "hugepage: failed to create transparent hugepage kobject\n");
                return -ENOMEM;
        }
 
        err = sysfs_create_group(*hugepage_kobj, &hugepage_attr_group);
        if (err) {
-               printk(KERN_ERR "hugepage: failed register hugeage group\n");
+               printk(KERN_ERR "hugepage: failed to register transparent hugepage group\n");
                goto delete_obj;
        }
 
        err = sysfs_create_group(*hugepage_kobj, &khugepaged_attr_group);
        if (err) {
-               printk(KERN_ERR "hugepage: failed register hugeage group\n");
+               printk(KERN_ERR "hugepage: failed to register transparent hugepage group\n");
                goto remove_hp_group;
        }
 
@@ -1257,6 +1257,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if (flags & FOLL_WRITE && !pmd_write(*pmd))
                goto out;
 
+       /* Avoid dumping huge zero page */
+       if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
+               return ERR_PTR(-EFAULT);
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
@@ -1819,9 +1823,19 @@ int split_huge_page(struct page *page)
 
        BUG_ON(is_huge_zero_pfn(page_to_pfn(page)));
        BUG_ON(!PageAnon(page));
-       anon_vma = page_lock_anon_vma_read(page);
+
+       /*
+        * The caller does not necessarily hold an mmap_sem that would prevent
+        * the anon_vma disappearing so we first we take a reference to it
+        * and then lock the anon_vma for write. This is similar to
+        * page_lock_anon_vma_read except the write lock is taken to serialise
+        * against parallel split or collapse operations.
+        */
+       anon_vma = page_get_anon_vma(page);
        if (!anon_vma)
                goto out;
+       anon_vma_lock_write(anon_vma);
+
        ret = 0;
        if (!PageCompound(page))
                goto out_unlock;
@@ -1832,7 +1846,8 @@ int split_huge_page(struct page *page)
 
        BUG_ON(PageCompound(page));
 out_unlock:
-       page_unlock_anon_vma_read(anon_vma);
+       anon_vma_unlock(anon_vma);
+       put_anon_vma(anon_vma);
 out:
        return ret;
 }
index 4f3ea0b1e57ce33bbf71bd1d3f41e04e11ae05dc..546db81820e45e8279f5a6425794da2980031dc8 100644 (file)
@@ -3033,6 +3033,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                if (!huge_pte_none(huge_ptep_get(ptep))) {
                        pte = huge_ptep_get_and_clear(mm, address, ptep);
                        pte = pte_mkhuge(pte_modify(pte, newprot));
+                       pte = arch_make_huge_pte(pte, vma, NULL, 0);
                        set_huge_pte_at(mm, address, ptep, pte);
                        pages++;
                }
index d597f94cc2059ade4d9fd808457d240538faac55..9ba21100ebf3b01bb0f2296baaf55ec41e303450 100644 (file)
@@ -135,7 +135,6 @@ struct compact_control {
        int migratetype;                /* MOVABLE, RECLAIMABLE etc */
        struct zone *zone;
        bool contended;                 /* True if a lock was contended */
-       struct page **page;             /* Page captured of requested size */
 };
 
 unsigned long
index 625905523c2a1592f539c46f6721723d62376648..88adc8afb6103d6c1ba2eb7e20c1ed226cf2b1d3 100644 (file)
@@ -314,7 +314,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
                }
 
                this->size += next->size;
-               memmove(next, next + 1, (type->cnt - (i + 1)) * sizeof(*next));
+               /* move forward from next + 1, index of which is i + 2 */
+               memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));
                type->cnt--;
        }
 }
index f3009b4bae510bdf5eced41a429aa1476519df2f..fbb60b103e64b11021475a749b86da6f7eb7137e 100644 (file)
@@ -3030,7 +3030,9 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
        if (memcg) {
                s->memcg_params->memcg = memcg;
                s->memcg_params->root_cache = root_cache;
-       }
+       } else
+               s->memcg_params->is_root_cache = true;
+
        return 0;
 }
 
@@ -6090,7 +6092,6 @@ mem_cgroup_css_alloc(struct cgroup *cont)
                                                &per_cpu(memcg_stock, cpu);
                        INIT_WORK(&stock->work, drain_local_stock);
                }
-               hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
        } else {
                parent = mem_cgroup_from_cont(cont->parent);
                memcg->use_hierarchy = parent->use_hierarchy;
@@ -6756,6 +6757,19 @@ struct cgroup_subsys mem_cgroup_subsys = {
        .use_id = 1,
 };
 
+/*
+ * The rest of init is performed during ->css_alloc() for root css which
+ * happens before initcalls.  hotcpu_notifier() can't be done together as
+ * it would introduce circular locking by adding cgroup_lock -> cpu hotplug
+ * dependency.  Do it from a subsys_initcall().
+ */
+static int __init mem_cgroup_init(void)
+{
+       hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
+       return 0;
+}
+subsys_initcall(mem_cgroup_init);
+
 #ifdef CONFIG_MEMCG_SWAP
 static int __init enable_swap_account(char *s)
 {
index e0a9b0ce4f102f8cfef2d6d7c6581d71f7595ff4..bb1369f7b9b4ba8af51d90a40de8f522aa2470dc 100644 (file)
@@ -184,10 +184,14 @@ static int tlb_next_batch(struct mmu_gather *tlb)
                return 1;
        }
 
+       if (tlb->batch_count == MAX_GATHER_BATCH_COUNT)
+               return 0;
+
        batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
        if (!batch)
                return 0;
 
+       tlb->batch_count++;
        batch->next = NULL;
        batch->nr   = 0;
        batch->max  = MAX_GATHER_BATCH;
@@ -216,6 +220,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
        tlb->local.nr   = 0;
        tlb->local.max  = ARRAY_SIZE(tlb->__pages);
        tlb->active     = &tlb->local;
+       tlb->batch_count = 0;
 
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb->batch = NULL;
@@ -3706,6 +3711,14 @@ retry:
                if (pmd_trans_huge(orig_pmd)) {
                        unsigned int dirty = flags & FAULT_FLAG_WRITE;
 
+                       /*
+                        * If the pmd is splitting, return and retry the
+                        * the fault.  Alternative: wait until the split
+                        * is done, and goto retry.
+                        */
+                       if (pmd_trans_splitting(orig_pmd))
+                               return 0;
+
                        if (pmd_numa(orig_pmd))
                                return do_huge_pmd_numa_page(mm, vma, address,
                                                             orig_pmd, pmd);
index d1b315e9862726a7f9511615279942f144261f4d..e2df1c1fb41f7a94e4ac2db1248cfb8165e5a17a 100644 (file)
@@ -2132,7 +2132,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
  */
 
 /* lookup first element intersecting start-end */
-/* Caller holds sp->mutex */
+/* Caller holds sp->lock */
 static struct sp_node *
 sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end)
 {
@@ -2196,13 +2196,13 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx)
 
        if (!sp->root.rb_node)
                return NULL;
-       mutex_lock(&sp->mutex);
+       spin_lock(&sp->lock);
        sn = sp_lookup(sp, idx, idx+1);
        if (sn) {
                mpol_get(sn->policy);
                pol = sn->policy;
        }
-       mutex_unlock(&sp->mutex);
+       spin_unlock(&sp->lock);
        return pol;
 }
 
@@ -2328,6 +2328,14 @@ static void sp_delete(struct shared_policy *sp, struct sp_node *n)
        sp_free(n);
 }
 
+static void sp_node_init(struct sp_node *node, unsigned long start,
+                       unsigned long end, struct mempolicy *pol)
+{
+       node->start = start;
+       node->end = end;
+       node->policy = pol;
+}
+
 static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
                                struct mempolicy *pol)
 {
@@ -2344,10 +2352,7 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
                return NULL;
        }
        newpol->flags |= MPOL_F_SHARED;
-
-       n->start = start;
-       n->end = end;
-       n->policy = newpol;
+       sp_node_init(n, start, end, newpol);
 
        return n;
 }
@@ -2357,9 +2362,12 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
                                 unsigned long end, struct sp_node *new)
 {
        struct sp_node *n;
+       struct sp_node *n_new = NULL;
+       struct mempolicy *mpol_new = NULL;
        int ret = 0;
 
-       mutex_lock(&sp->mutex);
+restart:
+       spin_lock(&sp->lock);
        n = sp_lookup(sp, start, end);
        /* Take care of old policies in the same range. */
        while (n && n->start < end) {
@@ -2372,14 +2380,16 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
                } else {
                        /* Old policy spanning whole new range. */
                        if (n->end > end) {
-                               struct sp_node *new2;
-                               new2 = sp_alloc(end, n->end, n->policy);
-                               if (!new2) {
-                                       ret = -ENOMEM;
-                                       goto out;
-                               }
+                               if (!n_new)
+                                       goto alloc_new;
+
+                               *mpol_new = *n->policy;
+                               atomic_set(&mpol_new->refcnt, 1);
+                               sp_node_init(n_new, n->end, end, mpol_new);
+                               sp_insert(sp, n_new);
                                n->end = start;
-                               sp_insert(sp, new2);
+                               n_new = NULL;
+                               mpol_new = NULL;
                                break;
                        } else
                                n->end = start;
@@ -2390,9 +2400,27 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
        }
        if (new)
                sp_insert(sp, new);
-out:
-       mutex_unlock(&sp->mutex);
+       spin_unlock(&sp->lock);
+       ret = 0;
+
+err_out:
+       if (mpol_new)
+               mpol_put(mpol_new);
+       if (n_new)
+               kmem_cache_free(sn_cache, n_new);
+
        return ret;
+
+alloc_new:
+       spin_unlock(&sp->lock);
+       ret = -ENOMEM;
+       n_new = kmem_cache_alloc(sn_cache, GFP_KERNEL);
+       if (!n_new)
+               goto err_out;
+       mpol_new = kmem_cache_alloc(policy_cache, GFP_KERNEL);
+       if (!mpol_new)
+               goto err_out;
+       goto restart;
 }
 
 /**
@@ -2410,7 +2438,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
        int ret;
 
        sp->root = RB_ROOT;             /* empty tree == default mempolicy */
-       mutex_init(&sp->mutex);
+       spin_lock_init(&sp->lock);
 
        if (mpol) {
                struct vm_area_struct pvma;
@@ -2476,14 +2504,14 @@ void mpol_free_shared_policy(struct shared_policy *p)
 
        if (!p->root.rb_node)
                return;
-       mutex_lock(&p->mutex);
+       spin_lock(&p->lock);
        next = rb_first(&p->root);
        while (next) {
                n = rb_entry(next, struct sp_node, nd);
                next = rb_next(&n->nd);
                sp_delete(p, n);
        }
-       mutex_unlock(&p->mutex);
+       spin_unlock(&p->lock);
 }
 
 #ifdef CONFIG_NUMA_BALANCING
@@ -2595,8 +2623,7 @@ void numa_default_policy(void)
  */
 
 /*
- * "local" is pseudo-policy:  MPOL_PREFERRED with MPOL_F_LOCAL flag
- * Used only for mpol_parse_str() and mpol_to_str()
+ * "local" is implemented internally by MPOL_PREFERRED with MPOL_F_LOCAL flag.
  */
 static const char * const policy_modes[] =
 {
@@ -2610,28 +2637,20 @@ static const char * const policy_modes[] =
 
 #ifdef CONFIG_TMPFS
 /**
- * mpol_parse_str - parse string to mempolicy
+ * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.
  * @str:  string containing mempolicy to parse
  * @mpol:  pointer to struct mempolicy pointer, returned on success.
- * @no_context:  flag whether to "contextualize" the mempolicy
  *
  * Format of input:
  *     <mode>[=<flags>][:<nodelist>]
  *
- * if @no_context is true, save the input nodemask in w.user_nodemask in
- * the returned mempolicy.  This will be used to "clone" the mempolicy in
- * a specific context [cpuset] at a later time.  Used to parse tmpfs mpol
- * mount option.  Note that if 'static' or 'relative' mode flags were
- * specified, the input nodemask will already have been saved.  Saving
- * it again is redundant, but safe.
- *
  * On success, returns 0, else 1
  */
-int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
+int mpol_parse_str(char *str, struct mempolicy **mpol)
 {
        struct mempolicy *new = NULL;
        unsigned short mode;
-       unsigned short uninitialized_var(mode_flags);
+       unsigned short mode_flags;
        nodemask_t nodes;
        char *nodelist = strchr(str, ':');
        char *flags = strchr(str, '=');
@@ -2719,24 +2738,23 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
        if (IS_ERR(new))
                goto out;
 
-       if (no_context) {
-               /* save for contextualization */
-               new->w.user_nodemask = nodes;
-       } else {
-               int ret;
-               NODEMASK_SCRATCH(scratch);
-               if (scratch) {
-                       task_lock(current);
-                       ret = mpol_set_nodemask(new, &nodes, scratch);
-                       task_unlock(current);
-               } else
-                       ret = -ENOMEM;
-               NODEMASK_SCRATCH_FREE(scratch);
-               if (ret) {
-                       mpol_put(new);
-                       goto out;
-               }
-       }
+       /*
+        * Save nodes for mpol_to_str() to show the tmpfs mount options
+        * for /proc/mounts, /proc/pid/mounts and /proc/pid/mountinfo.
+        */
+       if (mode != MPOL_PREFERRED)
+               new->v.nodes = nodes;
+       else if (nodelist)
+               new->v.preferred_node = first_node(nodes);
+       else
+               new->flags |= MPOL_F_LOCAL;
+
+       /*
+        * Save nodes for contextualization: this will be used to "clone"
+        * the mempolicy in a specific context [cpuset] at a later time.
+        */
+       new->w.user_nodemask = nodes;
+
        err = 0;
 
 out:
@@ -2756,13 +2774,12 @@ out:
  * @buffer:  to contain formatted mempolicy string
  * @maxlen:  length of @buffer
  * @pol:  pointer to mempolicy to be formatted
- * @no_context:  "context free" mempolicy - use nodemask in w.user_nodemask
  *
  * Convert a mempolicy into a string.
  * Returns the number of characters in buffer (if positive)
  * or an error (negative)
  */
-int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
+int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
 {
        char *p = buffer;
        int l;
@@ -2788,7 +2805,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
        case MPOL_PREFERRED:
                nodes_clear(nodes);
                if (flags & MPOL_F_LOCAL)
-                       mode = MPOL_LOCAL;      /* pseudo-policy */
+                       mode = MPOL_LOCAL;
                else
                        node_set(pol->v.preferred_node, nodes);
                break;
@@ -2796,10 +2813,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
        case MPOL_BIND:
                /* Fall through */
        case MPOL_INTERLEAVE:
-               if (no_context)
-                       nodes = pol->w.user_nodemask;
-               else
-                       nodes = pol->v.nodes;
+               nodes = pol->v.nodes;
                break;
 
        default:
index 3b676b0c5c3ecca91d5e91d8ef2adc2982353f57..2fd8b4af47440a39a31d48a1096e24b571028455 100644 (file)
@@ -160,8 +160,10 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
        if (is_write_migration_entry(entry))
                pte = pte_mkwrite(pte);
 #ifdef CONFIG_HUGETLB_PAGE
-       if (PageHuge(new))
+       if (PageHuge(new)) {
                pte = pte_mkhuge(pte);
+               pte = arch_make_huge_pte(pte, vma, new, 0);
+       }
 #endif
        flush_cache_page(vma, addr, pte_pfn(pte));
        set_pte_at(mm, addr, ptep, pte);
@@ -1679,9 +1681,21 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
        page_xchg_last_nid(new_page, page_last_nid(page));
 
        isolated = numamigrate_isolate_page(pgdat, page);
-       if (!isolated) {
+
+       /*
+        * Failing to isolate or a GUP pin prevents migration. The expected
+        * page count is 2. 1 for anonymous pages without a mapping and 1
+        * for the callers pin. If the page was isolated, the page will
+        * need to be put back on the LRU.
+        */
+       if (!isolated || page_count(page) != 2) {
                count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
                put_page(new_page);
+               if (isolated) {
+                       putback_lru_page(page);
+                       isolated = 0;
+                       goto out;
+               }
                goto out_keep_locked;
        }
 
index f0b9ce572fc78ddbd0118db8aaa60d9b56086bf9..c9bd528b01d2361aa6e37f9791a831c3b2a443e7 100644 (file)
@@ -517,11 +517,11 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
 static int do_mlockall(int flags)
 {
        struct vm_area_struct * vma, * prev = NULL;
-       unsigned int def_flags = 0;
 
        if (flags & MCL_FUTURE)
-               def_flags = VM_LOCKED;
-       current->mm->def_flags = def_flags;
+               current->mm->def_flags |= VM_LOCKED;
+       else
+               current->mm->def_flags &= ~VM_LOCKED;
        if (flags == MCL_FUTURE)
                goto out;
 
index f54b235f29a98c3b3a91c2c1e6b4b50ef5e8f287..09da0b2649822beae4ee559c265d087e4b93db15 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -32,6 +32,7 @@
 #include <linux/khugepaged.h>
 #include <linux/uprobes.h>
 #include <linux/rbtree_augmented.h>
+#include <linux/sched/sysctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -2886,7 +2887,7 @@ static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma)
                 * The LSB of head.next can't change from under us
                 * because we hold the mm_all_locks_mutex.
                 */
-               down_write(&anon_vma->root->rwsem);
+               down_write_nest_lock(&anon_vma->root->rwsem, &mm->mmap_sem);
                /*
                 * We can safely modify head.next after taking the
                 * anon_vma->root->rwsem. If some other vma in this mm shares
@@ -2943,7 +2944,7 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping)
  * vma in this mm is backed by the same anon_vma or address_space.
  *
  * We can take all the locks in random order because the VM code
- * taking i_mmap_mutex or anon_vma->mutex outside the mmap_sem never
+ * taking i_mmap_mutex or anon_vma->rwsem outside the mmap_sem never
  * takes more than one of them in a row. Secondly we're protected
  * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex.
  *
index e1031e1f6a61b68ba5055a162ea0d9161b510ba2..f9766f4602999f0fd6928a4c4b93f69ba0748b6a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/mmu_notifier.h>
+#include <linux/sched/sysctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
index 79c3cac87afa1d1f96fc9397f50bb370980e0a84..b20db4e222630cebde1ca16879d817977e881618 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
+#include <linux/sched/sysctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
index 6f4271224493a01699f7ffdc29afa54b7ffd94ac..66a0024becd9f6c87f5e437c92ce6852657638a9 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/buffer_head.h> /* __set_page_dirty_buffers */
 #include <linux/pagevec.h>
 #include <linux/timer.h>
+#include <linux/sched/rt.h>
 #include <trace/events/writeback.h>
 
 /*
@@ -200,6 +201,18 @@ static unsigned long highmem_dirtyable_memory(unsigned long total)
                x += zone_page_state(z, NR_FREE_PAGES) +
                     zone_reclaimable_pages(z) - z->dirty_balance_reserve;
        }
+       /*
+        * Unreclaimable memory (kernel memory or anonymous memory
+        * without swap) can bring down the dirtyable pages below
+        * the zone's dirty balance reserve and the above calculation
+        * will underflow.  However we still want to add in nodes
+        * which are below threshold (negative values) to get a more
+        * accurate calculation but make sure that the total never
+        * underflows.
+        */
+       if ((long)x < 0)
+               x = 0;
+
        /*
         * Make sure that the number of highmem pages is never larger
         * than the number of the total dirtyable memory. This can only
@@ -222,8 +235,8 @@ static unsigned long global_dirtyable_memory(void)
 {
        unsigned long x;
 
-       x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages() -
-           dirty_balance_reserve;
+       x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages();
+       x -= min(x, dirty_balance_reserve);
 
        if (!vm_highmem_is_dirtyable)
                x -= highmem_dirtyable_memory(x);
@@ -290,9 +303,12 @@ static unsigned long zone_dirtyable_memory(struct zone *zone)
         * highmem zone can hold its share of dirty pages, so we don't
         * care about vm_highmem_is_dirtyable here.
         */
-       return zone_page_state(zone, NR_FREE_PAGES) +
-              zone_reclaimable_pages(zone) -
-              zone->dirty_balance_reserve;
+       unsigned long nr_pages = zone_page_state(zone, NR_FREE_PAGES) +
+               zone_reclaimable_pages(zone);
+
+       /* don't allow this to underflow */
+       nr_pages -= min(nr_pages, zone->dirty_balance_reserve);
+       return nr_pages;
 }
 
 /**
index 2ad2ad168efe930bb75391848e71f4ac8c61099b..d1107adf174a5390c597414ea335494e857f1af2 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/prefetch.h>
 #include <linux/migrate.h>
 #include <linux/page-debug-flags.h>
+#include <linux/sched/rt.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -221,11 +222,6 @@ EXPORT_SYMBOL(nr_online_nodes);
 
 int page_group_by_mobility_disabled __read_mostly;
 
-/*
- * NOTE:
- * Don't use set_pageblock_migratetype(page, MIGRATE_ISOLATE) directly.
- * Instead, use {un}set_pageblock_isolate.
- */
 void set_pageblock_migratetype(struct page *page, int migratetype)
 {
 
@@ -778,6 +774,10 @@ void __init init_cma_reserved_pageblock(struct page *page)
        set_pageblock_migratetype(page, MIGRATE_CMA);
        __free_pages(page, pageblock_order);
        totalram_pages += pageblock_nr_pages;
+#ifdef CONFIG_HIGHMEM
+       if (PageHighMem(page))
+               totalhigh_pages += pageblock_nr_pages;
+#endif
 }
 #endif
 
@@ -1389,14 +1389,8 @@ void split_page(struct page *page, unsigned int order)
                set_page_refcounted(page + i);
 }
 
-/*
- * Similar to the split_page family of functions except that the page
- * required at the given order and being isolated now to prevent races
- * with parallel allocators
- */
-int capture_free_page(struct page *page, int alloc_order, int migratetype)
+static int __isolate_free_page(struct page *page, unsigned int order)
 {
-       unsigned int order;
        unsigned long watermark;
        struct zone *zone;
        int mt;
@@ -1404,7 +1398,6 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
        BUG_ON(!PageBuddy(page));
 
        zone = page_zone(page);
-       order = page_order(page);
        mt = get_pageblock_migratetype(page);
 
        if (mt != MIGRATE_ISOLATE) {
@@ -1413,7 +1406,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
                if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
                        return 0;
 
-               __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
+               __mod_zone_freepage_state(zone, -(1UL << order), mt);
        }
 
        /* Remove page from free list */
@@ -1421,11 +1414,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
        zone->free_area[order].nr_free--;
        rmv_page_order(page);
 
-       if (alloc_order != order)
-               expand(zone, page, alloc_order, order,
-                       &zone->free_area[order], migratetype);
-
-       /* Set the pageblock if the captured page is at least a pageblock */
+       /* Set the pageblock if the isolated page is at least a pageblock */
        if (order >= pageblock_order - 1) {
                struct page *endpage = page + (1 << order) - 1;
                for (; page < endpage; page += pageblock_nr_pages) {
@@ -1436,7 +1425,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
                }
        }
 
-       return 1UL << alloc_order;
+       return 1UL << order;
 }
 
 /*
@@ -1454,10 +1443,9 @@ int split_free_page(struct page *page)
        unsigned int order;
        int nr_pages;
 
-       BUG_ON(!PageBuddy(page));
        order = page_order(page);
 
-       nr_pages = capture_free_page(page, order, 0);
+       nr_pages = __isolate_free_page(page, order);
        if (!nr_pages)
                return 0;
 
@@ -1655,20 +1643,6 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
        return true;
 }
 
-#ifdef CONFIG_MEMORY_ISOLATION
-static inline unsigned long nr_zone_isolate_freepages(struct zone *zone)
-{
-       if (unlikely(zone->nr_pageblock_isolate))
-               return zone->nr_pageblock_isolate * pageblock_nr_pages;
-       return 0;
-}
-#else
-static inline unsigned long nr_zone_isolate_freepages(struct zone *zone)
-{
-       return 0;
-}
-#endif
-
 bool zone_watermark_ok(struct zone *z, int order, unsigned long mark,
                      int classzone_idx, int alloc_flags)
 {
@@ -1684,14 +1658,6 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
        if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark)
                free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES);
 
-       /*
-        * If the zone has MIGRATE_ISOLATE type free pages, we should consider
-        * it.  nr_zone_isolate_freepages is never accurate so kswapd might not
-        * sleep although it could do so.  But this is more desirable for memory
-        * hotplug than sleeping which can cause a livelock in the direct
-        * reclaim path.
-        */
-       free_pages -= nr_zone_isolate_freepages(z);
        return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
                                                                free_pages);
 }
@@ -2163,8 +2129,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
        bool *contended_compaction, bool *deferred_compaction,
        unsigned long *did_some_progress)
 {
-       struct page *page = NULL;
-
        if (!order)
                return NULL;
 
@@ -2176,16 +2140,12 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
        current->flags |= PF_MEMALLOC;
        *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask,
                                                nodemask, sync_migration,
-                                               contended_compaction, &page);
+                                               contended_compaction);
        current->flags &= ~PF_MEMALLOC;
 
-       /* If compaction captured a page, prep and use it */
-       if (page) {
-               prep_new_page(page, order, gfp_mask);
-               goto got_page;
-       }
-
        if (*did_some_progress != COMPACT_SKIPPED) {
+               struct page *page;
+
                /* Page migration frees to the PCP lists but we want merging */
                drain_pages(get_cpu());
                put_cpu();
@@ -2195,7 +2155,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
                                alloc_flags & ~ALLOC_NO_WATERMARKS,
                                preferred_zone, migratetype);
                if (page) {
-got_page:
                        preferred_zone->compact_blockskip_flush = false;
                        preferred_zone->compact_considered = 0;
                        preferred_zone->compact_defer_shift = 0;
@@ -4462,10 +4421,11 @@ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
  * round what is now in bits to nearest long in bits, then return it in
  * bytes.
  */
-static unsigned long __init usemap_size(unsigned long zonesize)
+static unsigned long __init usemap_size(unsigned long zone_start_pfn, unsigned long zonesize)
 {
        unsigned long usemapsize;
 
+       zonesize += zone_start_pfn & (pageblock_nr_pages-1);
        usemapsize = roundup(zonesize, pageblock_nr_pages);
        usemapsize = usemapsize >> pageblock_order;
        usemapsize *= NR_PAGEBLOCK_BITS;
@@ -4475,17 +4435,19 @@ static unsigned long __init usemap_size(unsigned long zonesize)
 }
 
 static void __init setup_usemap(struct pglist_data *pgdat,
-                               struct zone *zone, unsigned long zonesize)
+                               struct zone *zone,
+                               unsigned long zone_start_pfn,
+                               unsigned long zonesize)
 {
-       unsigned long usemapsize = usemap_size(zonesize);
+       unsigned long usemapsize = usemap_size(zone_start_pfn, zonesize);
        zone->pageblock_flags = NULL;
        if (usemapsize)
                zone->pageblock_flags = alloc_bootmem_node_nopanic(pgdat,
                                                                   usemapsize);
 }
 #else
-static inline void setup_usemap(struct pglist_data *pgdat,
-                               struct zone *zone, unsigned long zonesize) {}
+static inline void setup_usemap(struct pglist_data *pgdat, struct zone *zone,
+                               unsigned long zone_start_pfn, unsigned long zonesize) {}
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
@@ -4636,7 +4598,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                        continue;
 
                set_pageblock_order();
-               setup_usemap(pgdat, zone, size);
+               setup_usemap(pgdat, zone, zone_start_pfn, size);
                ret = init_currently_empty_zone(zone, zone_start_pfn,
                                                size, MEMMAP_EARLY);
                BUG_ON(ret);
@@ -5631,7 +5593,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
        pfn &= (PAGES_PER_SECTION-1);
        return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
 #else
-       pfn = pfn - zone->zone_start_pfn;
+       pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages);
        return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
 #endif /* CONFIG_SPARSEMEM */
 }
@@ -5978,8 +5940,15 @@ done:
 
 void free_contig_range(unsigned long pfn, unsigned nr_pages)
 {
-       for (; nr_pages--; ++pfn)
-               __free_page(pfn_to_page(pfn));
+       unsigned int count = 0;
+
+       for (; nr_pages--; pfn++) {
+               struct page *page = pfn_to_page(pfn);
+
+               count += page_count(page) != 1;
+               __free_page(page);
+       }
+       WARN(count != 0, "%d pages are still in use!\n", count);
 }
 #endif
 
index 9d2264ea460617b6aef2b59271e61933c15fbffd..383bdbb98b04ca22726fe3d243db2ce789642975 100644 (file)
@@ -8,28 +8,6 @@
 #include <linux/memory.h>
 #include "internal.h"
 
-/* called while holding zone->lock */
-static void set_pageblock_isolate(struct page *page)
-{
-       if (get_pageblock_migratetype(page) == MIGRATE_ISOLATE)
-               return;
-
-       set_pageblock_migratetype(page, MIGRATE_ISOLATE);
-       page_zone(page)->nr_pageblock_isolate++;
-}
-
-/* called while holding zone->lock */
-static void restore_pageblock_isolate(struct page *page, int migratetype)
-{
-       struct zone *zone = page_zone(page);
-       if (WARN_ON(get_pageblock_migratetype(page) != MIGRATE_ISOLATE))
-               return;
-
-       BUG_ON(zone->nr_pageblock_isolate <= 0);
-       set_pageblock_migratetype(page, migratetype);
-       zone->nr_pageblock_isolate--;
-}
-
 int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages)
 {
        struct zone *zone;
@@ -80,7 +58,7 @@ out:
                unsigned long nr_pages;
                int migratetype = get_pageblock_migratetype(page);
 
-               set_pageblock_isolate(page);
+               set_pageblock_migratetype(page, MIGRATE_ISOLATE);
                nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE);
 
                __mod_zone_freepage_state(zone, -nr_pages, migratetype);
@@ -103,7 +81,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
                goto out;
        nr_pages = move_freepages_block(zone, page, migratetype);
        __mod_zone_freepage_state(zone, nr_pages, migratetype);
-       restore_pageblock_isolate(page, migratetype);
+       set_pageblock_migratetype(page, migratetype);
 out:
        spin_unlock_irqrestore(&zone->lock, flags);
 }
index 5c90d84c2b028ae6478b78cacdf52494bab2c233..5dd56f6efdbd593733b793df2731f243dbaf031c 100644 (file)
@@ -889,7 +889,7 @@ static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
        if (!mpol || mpol->mode == MPOL_DEFAULT)
                return;         /* show nothing */
 
-       mpol_to_str(buffer, sizeof(buffer), mpol, 1);
+       mpol_to_str(buffer, sizeof(buffer), mpol);
 
        seq_printf(seq, ",mpol=%s", buffer);
 }
@@ -2463,7 +2463,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
                        if (!gid_valid(sbinfo->gid))
                                goto bad_val;
                } else if (!strcmp(this_char,"mpol")) {
-                       if (mpol_parse_str(value, &sbinfo->mpol, 1))
+                       if (mpol_parse_str(value, &sbinfo->mpol))
                                goto bad_val;
                } else {
                        printk(KERN_ERR "tmpfs: Bad mount option %s\n",
index d51ce92d6e83fefd08c2594d3ef8d25b1575f577..c75b736e54b793f338fce25f35afa60eb0faf5ef 100644 (file)
@@ -576,29 +576,6 @@ void truncate_setsize(struct inode *inode, loff_t newsize)
 }
 EXPORT_SYMBOL(truncate_setsize);
 
-/**
- * vmtruncate - unmap mappings "freed" by truncate() syscall
- * @inode: inode of the file used
- * @newsize: file offset to start truncating
- *
- * This function is deprecated and truncate_setsize or truncate_pagecache
- * should be used instead, together with filesystem specific block truncation.
- */
-int vmtruncate(struct inode *inode, loff_t newsize)
-{
-       int error;
-
-       error = inode_newsize_ok(inode, newsize);
-       if (error)
-               return error;
-
-       truncate_setsize(inode, newsize);
-       if (inode->i_op->truncate)
-               inode->i_op->truncate(inode);
-       return 0;
-}
-EXPORT_SYMBOL(vmtruncate);
-
 /**
  * truncate_pagecache_range - unmap and remove pagecache that is hole-punched
  * @inode: inode
index adc7e9058181eb4d38c2f22d77bd1e413d3457e7..196709f5ee5862753f5f3731bdeab58c2c45c323 100644 (file)
@@ -2452,12 +2452,16 @@ static bool zone_balanced(struct zone *zone, int order,
 }
 
 /*
- * 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
- * by the callers classzone_idx are added to balanced_pages. The total of
- * balanced pages must be at least 25% of the zones allowed by classzone_idx
- * for the node to be considered balanced. Forcing all zones to be balanced
- * for high orders can cause excessive reclaim when there are imbalanced zones.
+ * pgdat_balanced() is used when checking if a node is balanced.
+ *
+ * For order-0, all zones must be balanced!
+ *
+ * For high-order allocations only zones that meet watermarks and are in a
+ * zone allowed by the callers classzone_idx are added to balanced_pages. The
+ * total of balanced pages must be at least 25% of the zones allowed by
+ * classzone_idx for the node to be considered balanced. Forcing all zones to
+ * be balanced for high orders can cause excessive reclaim when there are
+ * imbalanced zones.
  * The choice of 25% is due to
  *   o a 16M DMA zone that is balanced will not balance a zone on any
  *     reasonable sized machine
@@ -2467,17 +2471,43 @@ static bool zone_balanced(struct zone *zone, int order,
  *     Similarly, on x86-64 the Normal zone would need to be at least 1G
  *     to balance a node on its own. These seemed like reasonable ratios.
  */
-static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages,
-                                               int classzone_idx)
+static bool pgdat_balanced(pg_data_t *pgdat, int order, int classzone_idx)
 {
        unsigned long present_pages = 0;
+       unsigned long balanced_pages = 0;
        int i;
 
-       for (i = 0; i <= classzone_idx; i++)
-               present_pages += pgdat->node_zones[i].present_pages;
+       /* Check the watermark levels */
+       for (i = 0; i <= classzone_idx; i++) {
+               struct zone *zone = pgdat->node_zones + i;
 
-       /* A special case here: if zone has no page, we think it's balanced */
-       return balanced_pages >= (present_pages >> 2);
+               if (!populated_zone(zone))
+                       continue;
+
+               present_pages += zone->present_pages;
+
+               /*
+                * A special case here:
+                *
+                * balance_pgdat() skips over all_unreclaimable after
+                * DEF_PRIORITY. Effectively, it considers them balanced so
+                * they must be considered balanced here as well!
+                */
+               if (zone->all_unreclaimable) {
+                       balanced_pages += zone->present_pages;
+                       continue;
+               }
+
+               if (zone_balanced(zone, order, 0, i))
+                       balanced_pages += zone->present_pages;
+               else if (!order)
+                       return false;
+       }
+
+       if (order)
+               return balanced_pages >= (present_pages >> 2);
+       else
+               return true;
 }
 
 /*
@@ -2489,10 +2519,6 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages,
 static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
                                        int classzone_idx)
 {
-       int i;
-       unsigned long balanced = 0;
-       bool all_zones_ok = true;
-
        /* If a direct reclaimer woke kswapd within HZ/10, it's premature */
        if (remaining)
                return false;
@@ -2511,39 +2537,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
                return false;
        }
 
-       /* Check the watermark levels */
-       for (i = 0; i <= classzone_idx; i++) {
-               struct zone *zone = pgdat->node_zones + i;
-
-               if (!populated_zone(zone))
-                       continue;
-
-               /*
-                * balance_pgdat() skips over all_unreclaimable after
-                * DEF_PRIORITY. Effectively, it considers them balanced so
-                * they must be considered balanced here as well if kswapd
-                * is to sleep
-                */
-               if (zone->all_unreclaimable) {
-                       balanced += zone->present_pages;
-                       continue;
-               }
-
-               if (!zone_balanced(zone, order, 0, i))
-                       all_zones_ok = false;
-               else
-                       balanced += zone->present_pages;
-       }
-
-       /*
-        * For high-order requests, the balanced zones must contain at least
-        * 25% of the nodes pages for kswapd to sleep. For order-0, all zones
-        * must be balanced
-        */
-       if (order)
-               return pgdat_balanced(pgdat, balanced, classzone_idx);
-       else
-               return all_zones_ok;
+       return pgdat_balanced(pgdat, order, classzone_idx);
 }
 
 /*
@@ -2571,7 +2565,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
                                                        int *classzone_idx)
 {
        struct zone *unbalanced_zone;
-       unsigned long balanced;
        int i;
        int end_zone = 0;       /* Inclusive.  0 = ZONE_DMA */
        unsigned long total_scanned;
@@ -2605,7 +2598,6 @@ loop_again:
                int has_under_min_watermark_zone = 0;
 
                unbalanced_zone = NULL;
-               balanced = 0;
 
                /*
                 * Scan in the highmem->dma direction for the highest
@@ -2761,8 +2753,6 @@ loop_again:
                                 * speculatively avoid congestion waits
                                 */
                                zone_clear_flag(zone, ZONE_CONGESTED);
-                               if (i <= *classzone_idx)
-                                       balanced += zone->present_pages;
                        }
 
                }
@@ -2776,7 +2766,7 @@ loop_again:
                                pfmemalloc_watermark_ok(pgdat))
                        wake_up(&pgdat->pfmemalloc_wait);
 
-               if (!unbalanced_zone || (order && pgdat_balanced(pgdat, balanced, *classzone_idx)))
+               if (pgdat_balanced(pgdat, order, *classzone_idx))
                        break;          /* kswapd: all done */
                /*
                 * OK, kswapd is getting into trouble.  Take a nap, then take
@@ -2785,7 +2775,7 @@ loop_again:
                if (total_scanned && (sc.priority < DEF_PRIORITY - 2)) {
                        if (has_under_min_watermark_zone)
                                count_vm_event(KSWAPD_SKIP_CONGESTION_WAIT);
-                       else
+                       else if (unbalanced_zone)
                                wait_iff_congested(unbalanced_zone, BLK_RW_ASYNC, HZ/10);
                }
 
@@ -2800,12 +2790,7 @@ loop_again:
        } while (--sc.priority >= 0);
 out:
 
-       /*
-        * order-0: All zones must meet high watermark for a balanced node
-        * high-order: Balanced zones must make up at least 25% of the node
-        *             for the node to be balanced
-        */
-       if (unbalanced_zone && (!order || !pgdat_balanced(pgdat, balanced, *classzone_idx))) {
+       if (!pgdat_balanced(pgdat, order, *classzone_idx)) {
                cond_resched();
 
                try_to_freeze();
@@ -3137,8 +3122,8 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
    not required for correctness.  So if the last cpu in a node goes
    away, we get changed to run anywhere: as the first one comes back,
    restore their cpu bindings. */
-static int __devinit cpu_callback(struct notifier_block *nfb,
-                                 unsigned long action, void *hcpu)
+static int cpu_callback(struct notifier_block *nfb, unsigned long action,
+                       void *hcpu)
 {
        int nid;
 
index 9f3925a85aab07e8eae11a1ac7b40e85f64fc480..7d02ebd11a7f1bd13b173cbe1eb0f54e623e0345 100644 (file)
@@ -123,7 +123,7 @@ batadv_iv_ogm_emit_send_time(const struct batadv_priv *bat_priv)
        unsigned int msecs;
 
        msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
-       msecs += (random32() % 2 * BATADV_JITTER);
+       msecs += random32() % (2 * BATADV_JITTER);
 
        return jiffies + msecs_to_jiffies(msecs);
 }
index 8e1d89d2b1c1cada56f190bcca967525a2b7a2e7..553921511e4ee585cc9dd9e5bb52be59ef83298b 100644 (file)
@@ -440,7 +440,7 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
        /* this is an hash collision with the temporary selected node. Choose
         * the one with the lowest address
         */
-       if ((tmp_max == max) &&
+       if ((tmp_max == max) && max_orig_node &&
            (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0))
                goto out;
 
@@ -738,6 +738,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
        struct arphdr *arphdr;
        struct ethhdr *ethhdr;
        __be32 ip_src, ip_dst;
+       uint8_t *hw_src, *hw_dst;
        uint16_t type = 0;
 
        /* pull the ethernet header */
@@ -777,9 +778,23 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
        ip_src = batadv_arp_ip_src(skb, hdr_size);
        ip_dst = batadv_arp_ip_dst(skb, hdr_size);
        if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
-           ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
+           ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst) ||
+           ipv4_is_zeronet(ip_src) || ipv4_is_lbcast(ip_src) ||
+           ipv4_is_zeronet(ip_dst) || ipv4_is_lbcast(ip_dst))
                goto out;
 
+       hw_src = batadv_arp_hw_src(skb, hdr_size);
+       if (is_zero_ether_addr(hw_src) || is_multicast_ether_addr(hw_src))
+               goto out;
+
+       /* we don't care about the destination MAC address in ARP requests */
+       if (arphdr->ar_op != htons(ARPOP_REQUEST)) {
+               hw_dst = batadv_arp_hw_dst(skb, hdr_size);
+               if (is_zero_ether_addr(hw_dst) ||
+                   is_multicast_ether_addr(hw_dst))
+                       goto out;
+       }
+
        type = ntohs(arphdr->ar_op);
 out:
        return type;
@@ -1012,6 +1027,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
         */
        ret = !batadv_is_my_client(bat_priv, hw_dst);
 out:
+       if (ret)
+               kfree_skb(skb);
        /* if ret == false -> packet has to be delivered to the interface */
        return ret;
 }
index 25bfce0666ebff70258019ddb1bba9b6f1eca967..4925a02ae7e4db7df4d4cdfc972e68375743861c 100644 (file)
@@ -249,12 +249,12 @@ static void hci_conn_disconnect(struct hci_conn *conn)
        __u8 reason = hci_proto_disconn_ind(conn);
 
        switch (conn->type) {
-       case ACL_LINK:
-               hci_acl_disconn(conn, reason);
-               break;
        case AMP_LINK:
                hci_amp_disconn(conn, reason);
                break;
+       default:
+               hci_acl_disconn(conn, reason);
+               break;
        }
 }
 
index 596660d37c5e56d6a0178b16b288a2d3c868f965..0f78e34220c9025aae08f3b38b49924b6c397ff6 100644 (file)
@@ -2810,14 +2810,6 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        if (conn) {
                hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
 
-               hci_dev_lock(hdev);
-               if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
-                   !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-                       mgmt_device_connected(hdev, &conn->dst, conn->type,
-                                             conn->dst_type, 0, NULL, 0,
-                                             conn->dev_class);
-               hci_dev_unlock(hdev);
-
                /* Send to upper protocol */
                l2cap_recv_acldata(conn, skb, flags);
                return;
index 705078a0cc393c023054ad1d55aea1a548e3da1d..81b44481d0d93a8dd8513dd15f97f9a21b8a32d6 100644 (file)
@@ -2688,7 +2688,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (ev->opcode != HCI_OP_NOP)
                del_timer(&hdev->cmd_timer);
 
-       if (ev->ncmd) {
+       if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
                        queue_work(hdev->workqueue, &hdev->cmd_work);
index b2bcbe2dc328ba8473227035c39a7ff467ee5659..a7352ff3fd1e7884c2fc43142fba9bc0033063b8 100644 (file)
@@ -931,7 +931,7 @@ static int hidp_setup_hid(struct hidp_session *session,
        hid->version = req->version;
        hid->country = req->country;
 
-       strncpy(hid->name, req->name, 128);
+       strncpy(hid->name, req->name, sizeof(req->name) - 1);
 
        snprintf(hid->phys, sizeof(hid->phys), "%pMR",
                 &bt_sk(session->ctrl_sock->sk)->src);
index 2c78208d793eb8db838cf85a480e029a4dc3567b..22e658322845b9f16bcf8de52c1ba7c401bfef87 100644 (file)
@@ -3727,6 +3727,17 @@ sendresp:
 static int l2cap_connect_req(struct l2cap_conn *conn,
                             struct l2cap_cmd_hdr *cmd, u8 *data)
 {
+       struct hci_dev *hdev = conn->hcon->hdev;
+       struct hci_conn *hcon = conn->hcon;
+
+       hci_dev_lock(hdev);
+       if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+           !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
+               mgmt_device_connected(hdev, &hcon->dst, hcon->type,
+                                     hcon->dst_type, 0, NULL, 0,
+                                     hcon->dev_class);
+       hci_dev_unlock(hdev);
+
        l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
        return 0;
 }
index 531a93d613d4f3f86eff5174cdbb1236b75cfb53..57f250c20e399851ca6998d9813dc60e3ffa3455 100644 (file)
@@ -352,7 +352,7 @@ static void __sco_sock_close(struct sock *sk)
 
        case BT_CONNECTED:
        case BT_CONFIG:
-               if (sco_pi(sk)->conn) {
+               if (sco_pi(sk)->conn->hcon) {
                        sk->sk_state = BT_DISCONN;
                        sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
                        hci_conn_put(sco_pi(sk)->conn->hcon);
index 68a9587c96945cdd3264cc310b68b7be95cfd953..5abefb12891d5144f97d1feacb0803937b0c9765 100644 (file)
@@ -859,6 +859,19 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
        skb_pull(skb, sizeof(code));
 
+       /*
+        * The SMP context must be initialized for all other PDUs except
+        * pairing and security requests. If we get any other PDU when
+        * not initialized simply disconnect (done if this function
+        * returns an error).
+        */
+       if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
+           !conn->smp_chan) {
+               BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
+               kfree_skb(skb);
+               return -ENOTSUPP;
+       }
+
        switch (code) {
        case SMP_CMD_PAIRING_REQ:
                reason = smp_cmd_pairing_req(conn, skb);
index 1c8fdc3558cd48e9ad5d7be9c3981ebf80878364..37fe693471a84d6815b31a5efcadfd836c0be254 100644 (file)
@@ -366,11 +366,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        err = netdev_set_master(dev, br->dev);
        if (err)
-               goto err3;
+               goto err4;
 
        err = netdev_rx_handler_register(dev, br_handle_frame, p);
        if (err)
-               goto err4;
+               goto err5;
 
        dev->priv_flags |= IFF_BRIDGE_PORT;
 
@@ -402,8 +402,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        return 0;
 
-err4:
+err5:
        netdev_set_master(dev, NULL);
+err4:
+       br_netpoll_disable(p);
 err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
index 5391ca43336a7d518c1640f855ecc7b739ce7226..6d6f26531de227004450456065fc51a8ee0c7c73 100644 (file)
@@ -1608,7 +1608,6 @@ void br_multicast_init(struct net_bridge *br)
                    br_multicast_querier_expired, (unsigned long)br);
        setup_timer(&br->multicast_query_timer, br_multicast_query_expired,
                    (unsigned long)br);
-       br_mdb_init();
 }
 
 void br_multicast_open(struct net_bridge *br)
@@ -1633,7 +1632,6 @@ void br_multicast_stop(struct net_bridge *br)
        del_timer_sync(&br->multicast_querier_timer);
        del_timer_sync(&br->multicast_query_timer);
 
-       br_mdb_uninit();
        spin_lock_bh(&br->multicast_lock);
        mdb = mlock_dereference(br->mdb, br);
        if (!mdb)
index 97ba0189c6f7c0cdba7c83491db620e2b409ae77..5dc66abcc9e22c93bb4f70f5a219f730bab63275 100644 (file)
@@ -299,10 +299,21 @@ struct rtnl_link_ops br_link_ops __read_mostly = {
 
 int __init br_netlink_init(void)
 {
-       return rtnl_link_register(&br_link_ops);
+       int err;
+
+       br_mdb_init();
+       err = rtnl_link_register(&br_link_ops);
+       if (err)
+               goto out;
+
+       return 0;
+out:
+       br_mdb_uninit();
+       return err;
 }
 
 void __exit br_netlink_fini(void)
 {
+       br_mdb_uninit();
        rtnl_link_unregister(&br_link_ops);
 }
index 8d83be5ffedcd8d04fdff6edf715947f56a1fbcc..711094aed41a29f967cf925c1863f569dff023d0 100644 (file)
@@ -526,6 +526,12 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
 {
        return 0;
 }
+static inline void br_mdb_init(void)
+{
+}
+static inline void br_mdb_uninit(void)
+{
+}
 #endif
 
 /* br_netfilter.c */
index 7f884e3fb9554328b1e39650d5708a21b9f92a57..8660ea3be7054571defa59bcfbfc0cd0dd7ab99e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/etherdevice.h>
 #include <linux/llc.h>
 #include <linux/slab.h>
+#include <linux/pkt_sched.h>
 #include <net/net_namespace.h>
 #include <net/llc.h>
 #include <net/llc_pdu.h>
@@ -40,6 +41,7 @@ static void br_send_bpdu(struct net_bridge_port *p,
 
        skb->dev = p->dev;
        skb->protocol = htons(ETH_P_802_2);
+       skb->priority = TC_PRIO_CONTROL;
 
        skb_reserve(skb, LLC_RESERVE);
        memcpy(__skb_put(skb, length), data, length);
index a8020293f34210620eff72f6193ee35e064f5d69..ee71ea26777ae892fafd13a8338b3f556d9f427b 100644 (file)
@@ -305,7 +305,6 @@ ceph_parse_options(char *options, const char *dev_name,
 
        /* start with defaults */
        opt->flags = CEPH_OPT_DEFAULT;
-       opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
        opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
        opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
@@ -391,7 +390,7 @@ ceph_parse_options(char *options, const char *dev_name,
 
                        /* misc */
                case Opt_osdtimeout:
-                       opt->osd_timeout = intval;
+                       pr_warning("ignoring deprecated osdtimeout option\n");
                        break;
                case Opt_osdkeepalivetimeout:
                        opt->osd_keepalive_timeout = intval;
index 3ef1759403b411fe53595e2ddf1eb6314a4f9ef8..5ccf87ed8d688820a23ba1267439abe149398ec2 100644 (file)
@@ -506,6 +506,7 @@ static void reset_connection(struct ceph_connection *con)
 {
        /* reset connection, out_queue, msg_ and connect_seq */
        /* discard existing out_queue and msg_seq */
+       dout("reset_connection %p\n", con);
        ceph_msg_remove_list(&con->out_queue);
        ceph_msg_remove_list(&con->out_sent);
 
@@ -561,7 +562,7 @@ void ceph_con_open(struct ceph_connection *con,
        mutex_lock(&con->mutex);
        dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
 
-       BUG_ON(con->state != CON_STATE_CLOSED);
+       WARN_ON(con->state != CON_STATE_CLOSED);
        con->state = CON_STATE_PREOPEN;
 
        con->peer_name.type = (__u8) entity_type;
@@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_connection *con)
        return 0;
 }
 
-static void fail_protocol(struct ceph_connection *con)
-{
-       reset_connection(con);
-       BUG_ON(con->state != CON_STATE_NEGOTIATING);
-       con->state = CON_STATE_CLOSED;
-}
-
 static int process_connect(struct ceph_connection *con)
 {
        u64 sup_feat = con->msgr->supported_features;
@@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_connection *con)
                       ceph_pr_addr(&con->peer_addr.in_addr),
                       sup_feat, server_feat, server_feat & ~sup_feat);
                con->error_msg = "missing required protocol features";
-               fail_protocol(con);
+               reset_connection(con);
                return -1;
 
        case CEPH_MSGR_TAG_BADPROTOVER:
@@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_connection *con)
                       le32_to_cpu(con->out_connect.protocol_version),
                       le32_to_cpu(con->in_reply.protocol_version));
                con->error_msg = "protocol version mismatch";
-               fail_protocol(con);
+               reset_connection(con);
                return -1;
 
        case CEPH_MSGR_TAG_BADAUTHORIZER:
@@ -1631,11 +1625,11 @@ static int process_connect(struct ceph_connection *con)
                               ceph_pr_addr(&con->peer_addr.in_addr),
                               req_feat, server_feat, req_feat & ~server_feat);
                        con->error_msg = "missing required protocol features";
-                       fail_protocol(con);
+                       reset_connection(con);
                        return -1;
                }
 
-               BUG_ON(con->state != CON_STATE_NEGOTIATING);
+               WARN_ON(con->state != CON_STATE_NEGOTIATING);
                con->state = CON_STATE_OPEN;
 
                con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
@@ -2132,7 +2126,6 @@ more:
                if (ret < 0)
                        goto out;
 
-               BUG_ON(con->state != CON_STATE_CONNECTING);
                con->state = CON_STATE_NEGOTIATING;
 
                /*
@@ -2160,7 +2153,7 @@ more:
                goto more;
        }
 
-       BUG_ON(con->state != CON_STATE_OPEN);
+       WARN_ON(con->state != CON_STATE_OPEN);
 
        if (con->in_base_pos < 0) {
                /*
@@ -2244,22 +2237,62 @@ bad_tag:
 
 
 /*
- * Atomically queue work on a connection.  Bump @con reference to
- * avoid races with connection teardown.
+ * Atomically queue work on a connection after the specified delay.
+ * Bump @con reference to avoid races with connection teardown.
+ * Returns 0 if work was queued, or an error code otherwise.
  */
-static void queue_con(struct ceph_connection *con)
+static int queue_con_delay(struct ceph_connection *con, unsigned long delay)
 {
        if (!con->ops->get(con)) {
-               dout("queue_con %p ref count 0\n", con);
-               return;
+               dout("%s %p ref count 0\n", __func__, con);
+
+               return -ENOENT;
        }
 
-       if (!queue_delayed_work(ceph_msgr_wq, &con->work, 0)) {
-               dout("queue_con %p - already queued\n", con);
+       if (!queue_delayed_work(ceph_msgr_wq, &con->work, delay)) {
+               dout("%s %p - already queued\n", __func__, con);
                con->ops->put(con);
-       } else {
-               dout("queue_con %p\n", con);
+
+               return -EBUSY;
+       }
+
+       dout("%s %p %lu\n", __func__, con, delay);
+
+       return 0;
+}
+
+static void queue_con(struct ceph_connection *con)
+{
+       (void) queue_con_delay(con, 0);
+}
+
+static bool con_sock_closed(struct ceph_connection *con)
+{
+       if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags))
+               return false;
+
+#define CASE(x)                                                                \
+       case CON_STATE_ ## x:                                           \
+               con->error_msg = "socket closed (con state " #x ")";    \
+               break;
+
+       switch (con->state) {
+       CASE(CLOSED);
+       CASE(PREOPEN);
+       CASE(CONNECTING);
+       CASE(NEGOTIATING);
+       CASE(OPEN);
+       CASE(STANDBY);
+       default:
+               pr_warning("%s con %p unrecognized state %lu\n",
+                       __func__, con, con->state);
+               con->error_msg = "unrecognized con state";
+               BUG();
+               break;
        }
+#undef CASE
+
+       return true;
 }
 
 /*
@@ -2273,35 +2306,16 @@ static void con_work(struct work_struct *work)
 
        mutex_lock(&con->mutex);
 restart:
-       if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) {
-               switch (con->state) {
-               case CON_STATE_CONNECTING:
-                       con->error_msg = "connection failed";
-                       break;
-               case CON_STATE_NEGOTIATING:
-                       con->error_msg = "negotiation failed";
-                       break;
-               case CON_STATE_OPEN:
-                       con->error_msg = "socket closed";
-                       break;
-               default:
-                       dout("unrecognized con state %d\n", (int)con->state);
-                       con->error_msg = "unrecognized con state";
-                       BUG();
-               }
+       if (con_sock_closed(con))
                goto fault;
-       }
 
        if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) {
                dout("con_work %p backing off\n", con);
-               if (queue_delayed_work(ceph_msgr_wq, &con->work,
-                                      round_jiffies_relative(con->delay))) {
-                       dout("con_work %p backoff %lu\n", con, con->delay);
-                       mutex_unlock(&con->mutex);
-                       return;
-               } else {
+               ret = queue_con_delay(con, round_jiffies_relative(con->delay));
+               if (ret) {
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       BUG_ON(ret == -ENOENT);
                        set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
                goto done;
@@ -2356,12 +2370,12 @@ fault:
 static void ceph_fault(struct ceph_connection *con)
        __releases(con->mutex)
 {
-       pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
+       pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
               ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
        dout("fault %p state %lu to peer %s\n",
             con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
 
-       BUG_ON(con->state != CON_STATE_CONNECTING &&
+       WARN_ON(con->state != CON_STATE_CONNECTING &&
               con->state != CON_STATE_NEGOTIATING &&
               con->state != CON_STATE_OPEN);
 
@@ -2398,24 +2412,8 @@ static void ceph_fault(struct ceph_connection *con)
                        con->delay = BASE_DELAY_INTERVAL;
                else if (con->delay < MAX_DELAY_INTERVAL)
                        con->delay *= 2;
-               con->ops->get(con);
-               if (queue_delayed_work(ceph_msgr_wq, &con->work,
-                                      round_jiffies_relative(con->delay))) {
-                       dout("fault queued %p delay %lu\n", con, con->delay);
-               } else {
-                       con->ops->put(con);
-                       dout("fault failed to queue %p delay %lu, backoff\n",
-                            con, con->delay);
-                       /*
-                        * In many cases we see a socket state change
-                        * while con_work is running and end up
-                        * queuing (non-delayed) work, such that we
-                        * can't backoff with a delay.  Set a flag so
-                        * that when con_work restarts we schedule the
-                        * delay then.
-                        */
-                       set_bit(CON_FLAG_BACKOFF, &con->flags);
-               }
+               set_bit(CON_FLAG_BACKOFF, &con->flags);
+               queue_con(con);
        }
 
 out_unlock:
index c1d756cc74486178ed8d1f662d14172e3e59bb1c..eb9a4447876481e9a4110a1e68ea351ce3ec86d9 100644 (file)
@@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
        kref_init(&req->r_kref);
        init_completion(&req->r_completion);
        init_completion(&req->r_safe_completion);
+       RB_CLEAR_NODE(&req->r_node);
        INIT_LIST_HEAD(&req->r_unsafe_item);
        INIT_LIST_HEAD(&req->r_linger_item);
        INIT_LIST_HEAD(&req->r_linger_osd);
@@ -580,7 +581,7 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc,
 
        dout("__kick_osd_requests osd%d\n", osd->o_osd);
        err = __reset_osd(osdc, osd);
-       if (err == -EAGAIN)
+       if (err)
                return;
 
        list_for_each_entry(req, &osd->o_requests, r_osd_item) {
@@ -607,14 +608,6 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc,
        }
 }
 
-static void kick_osd_requests(struct ceph_osd_client *osdc,
-                             struct ceph_osd *kickosd)
-{
-       mutex_lock(&osdc->request_mutex);
-       __kick_osd_requests(osdc, kickosd);
-       mutex_unlock(&osdc->request_mutex);
-}
-
 /*
  * If the osd connection drops, we need to resubmit all requests.
  */
@@ -628,7 +621,9 @@ static void osd_reset(struct ceph_connection *con)
        dout("osd_reset osd%d\n", osd->o_osd);
        osdc = osd->o_osdc;
        down_read(&osdc->map_sem);
-       kick_osd_requests(osdc, osd);
+       mutex_lock(&osdc->request_mutex);
+       __kick_osd_requests(osdc, osd);
+       mutex_unlock(&osdc->request_mutex);
        send_queued(osdc);
        up_read(&osdc->map_sem);
 }
@@ -647,6 +642,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
        atomic_set(&osd->o_ref, 1);
        osd->o_osdc = osdc;
        osd->o_osd = onum;
+       RB_CLEAR_NODE(&osd->o_node);
        INIT_LIST_HEAD(&osd->o_requests);
        INIT_LIST_HEAD(&osd->o_linger_requests);
        INIT_LIST_HEAD(&osd->o_osd_lru);
@@ -750,6 +746,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
        if (list_empty(&osd->o_requests) &&
            list_empty(&osd->o_linger_requests)) {
                __remove_osd(osdc, osd);
+               ret = -ENODEV;
        } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
                          &osd->o_con.peer_addr,
                          sizeof(osd->o_con.peer_addr)) == 0 &&
@@ -876,9 +873,9 @@ static void __unregister_request(struct ceph_osd_client *osdc,
                        req->r_osd = NULL;
        }
 
+       list_del_init(&req->r_req_lru_item);
        ceph_osdc_put_request(req);
 
-       list_del_init(&req->r_req_lru_item);
        if (osdc->num_requests == 0) {
                dout(" no requests, canceling timeout\n");
                __cancel_osd_timeout(osdc);
@@ -910,8 +907,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc,
                                        struct ceph_osd_request *req)
 {
        dout("__unregister_linger_request %p\n", req);
+       list_del_init(&req->r_linger_item);
        if (req->r_osd) {
-               list_del_init(&req->r_linger_item);
                list_del_init(&req->r_linger_osd);
 
                if (list_empty(&req->r_osd->o_requests) &&
@@ -1090,12 +1087,10 @@ static void handle_timeout(struct work_struct *work)
 {
        struct ceph_osd_client *osdc =
                container_of(work, struct ceph_osd_client, timeout_work.work);
-       struct ceph_osd_request *req, *last_req = NULL;
+       struct ceph_osd_request *req;
        struct ceph_osd *osd;
-       unsigned long timeout = osdc->client->options->osd_timeout * HZ;
        unsigned long keepalive =
                osdc->client->options->osd_keepalive_timeout * HZ;
-       unsigned long last_stamp = 0;
        struct list_head slow_osds;
        dout("timeout\n");
        down_read(&osdc->map_sem);
@@ -1104,37 +1099,6 @@ static void handle_timeout(struct work_struct *work)
 
        mutex_lock(&osdc->request_mutex);
 
-       /*
-        * reset osds that appear to be _really_ unresponsive.  this
-        * is a failsafe measure.. we really shouldn't be getting to
-        * this point if the system is working properly.  the monitors
-        * should mark the osd as failed and we should find out about
-        * it from an updated osd map.
-        */
-       while (timeout && !list_empty(&osdc->req_lru)) {
-               req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
-                                r_req_lru_item);
-
-               /* hasn't been long enough since we sent it? */
-               if (time_before(jiffies, req->r_stamp + timeout))
-                       break;
-
-               /* hasn't been long enough since it was acked? */
-               if (req->r_request->ack_stamp == 0 ||
-                   time_before(jiffies, req->r_request->ack_stamp + timeout))
-                       break;
-
-               BUG_ON(req == last_req && req->r_stamp == last_stamp);
-               last_req = req;
-               last_stamp = req->r_stamp;
-
-               osd = req->r_osd;
-               BUG_ON(!osd);
-               pr_warning(" tid %llu timed out on osd%d, will reset osd\n",
-                          req->r_tid, osd->o_osd);
-               __kick_osd_requests(osdc, osd);
-       }
-
        /*
         * ping osds that are a bit slow.  this ensures that if there
         * is a break in the TCP connection we will notice, and reopen
@@ -1306,7 +1270,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc)
  * Requeue requests whose mapping to an OSD has changed.  If requests map to
  * no osd, request a new map.
  *
- * Caller should hold map_sem for read and request_mutex.
+ * Caller should hold map_sem for read.
  */
 static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
 {
@@ -1320,6 +1284,24 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
        for (p = rb_first(&osdc->requests); p; ) {
                req = rb_entry(p, struct ceph_osd_request, r_node);
                p = rb_next(p);
+
+               /*
+                * For linger requests that have not yet been
+                * registered, move them to the linger list; they'll
+                * be sent to the osd in the loop below.  Unregister
+                * the request before re-registering it as a linger
+                * request to ensure the __map_request() below
+                * will decide it needs to be sent.
+                */
+               if (req->r_linger && list_empty(&req->r_linger_item)) {
+                       dout("%p tid %llu restart on osd%d\n",
+                            req, req->r_tid,
+                            req->r_osd ? req->r_osd->o_osd : -1);
+                       __unregister_request(osdc, req);
+                       __register_linger_request(osdc, req);
+                       continue;
+               }
+
                err = __map_request(osdc, req, force_resend);
                if (err < 0)
                        continue;  /* error */
@@ -1334,17 +1316,6 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                                req->r_flags |= CEPH_OSD_FLAG_RETRY;
                        }
                }
-               if (req->r_linger && list_empty(&req->r_linger_item)) {
-                       /*
-                        * register as a linger so that we will
-                        * re-submit below and get a new tid
-                        */
-                       dout("%p tid %llu restart on osd%d\n",
-                            req, req->r_tid,
-                            req->r_osd ? req->r_osd->o_osd : -1);
-                       __register_linger_request(osdc, req);
-                       __unregister_request(osdc, req);
-               }
        }
 
        list_for_each_entry_safe(req, nreq, &osdc->req_linger,
@@ -1352,6 +1323,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                dout("linger req=%p req->r_osd=%p\n", req, req->r_osd);
 
                err = __map_request(osdc, req, force_resend);
+               dout("__map_request returned %d\n", err);
                if (err == 0)
                        continue;  /* no change and no osd was specified */
                if (err < 0)
@@ -1364,8 +1336,8 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
 
                dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid,
                     req->r_osd ? req->r_osd->o_osd : -1);
-               __unregister_linger_request(osdc, req);
                __register_request(osdc, req);
+               __unregister_linger_request(osdc, req);
        }
        mutex_unlock(&osdc->request_mutex);
 
@@ -1373,6 +1345,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                dout("%d requests for down osds, need new map\n", needmap);
                ceph_monc_request_next_osdmap(&osdc->client->monc);
        }
+       reset_changed_osds(osdc);
 }
 
 
@@ -1429,7 +1402,6 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
                                osdc->osdmap = newmap;
                        }
                        kick_requests(osdc, 0);
-                       reset_changed_osds(osdc);
                } else {
                        dout("ignoring incremental map %u len %d\n",
                             epoch, maplen);
@@ -1599,6 +1571,7 @@ int ceph_osdc_create_event(struct ceph_osd_client *osdc,
        event->data = data;
        event->osdc = osdc;
        INIT_LIST_HEAD(&event->osd_node);
+       RB_CLEAR_NODE(&event->node);
        kref_init(&event->kref);   /* one ref for us */
        kref_get(&event->kref);    /* one ref for the caller */
        init_completion(&event->completion);
index 5433fb0eb3c68596b375388b3df74a03c6e8441c..de73214b5d26c04989905bafc62bd9c056f2131c 100644 (file)
@@ -469,6 +469,22 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id)
        return NULL;
 }
 
+const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id)
+{
+       struct ceph_pg_pool_info *pi;
+
+       if (id == CEPH_NOPOOL)
+               return NULL;
+
+       if (WARN_ON_ONCE(id > (u64) INT_MAX))
+               return NULL;
+
+       pi = __lookup_pg_pool(&map->pg_pools, (int) id);
+
+       return pi ? pi->name : NULL;
+}
+EXPORT_SYMBOL(ceph_pg_pool_name_by_id);
+
 int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name)
 {
        struct rb_node *rbp;
@@ -645,10 +661,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
        ceph_decode_32_safe(p, end, max, bad);
        while (max--) {
                ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad);
+               err = -ENOMEM;
                pi = kzalloc(sizeof(*pi), GFP_NOFS);
                if (!pi)
                        goto bad;
                pi->id = ceph_decode_32(p);
+               err = -EINVAL;
                ev = ceph_decode_8(p); /* encoding version */
                if (ev > CEPH_PG_POOL_VERSION) {
                        pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
@@ -664,8 +682,13 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
                __insert_pg_pool(&map->pg_pools, pi);
        }
 
-       if (version >= 5 && __decode_pool_names(p, end, map) < 0)
-               goto bad;
+       if (version >= 5) {
+               err = __decode_pool_names(p, end, map);
+               if (err < 0) {
+                       dout("fail to decode pool names");
+                       goto bad;
+               }
+       }
 
        ceph_decode_32_safe(p, end, map->pool_max, bad);
 
@@ -745,7 +768,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
        return map;
 
 bad:
-       dout("osdmap_decode fail\n");
+       dout("osdmap_decode fail err %d\n", err);
        ceph_osdmap_destroy(map);
        return ERR_PTR(err);
 }
@@ -839,6 +862,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
                if (ev > CEPH_PG_POOL_VERSION) {
                        pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
                                   ev, CEPH_PG_POOL_VERSION);
+                       err = -EINVAL;
                        goto bad;
                }
                pi = __lookup_pg_pool(&map->pg_pools, pool);
@@ -855,8 +879,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
                if (err < 0)
                        goto bad;
        }
-       if (version >= 5 && __decode_pool_names(p, end, map) < 0)
-               goto bad;
+       if (version >= 5) {
+               err = __decode_pool_names(p, end, map);
+               if (err < 0)
+                       goto bad;
+       }
 
        /* old_pool */
        ceph_decode_32_safe(p, end, len, bad);
@@ -932,15 +959,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
                        (void) __remove_pg_mapping(&map->pg_temp, pgid);
 
                        /* insert */
-                       if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) {
-                               err = -EINVAL;
+                       err = -EINVAL;
+                       if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
                                goto bad;
-                       }
+                       err = -ENOMEM;
                        pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
-                       if (!pg) {
-                               err = -ENOMEM;
+                       if (!pg)
                                goto bad;
-                       }
                        pg->pgid = pgid;
                        pg->len = pglen;
                        for (j = 0; j < pglen; j++)
index 0337e2b768628d353936dc09ba4fe483b2c5b638..368f9c3f9dc6505e693f56066da6dcb19ec2ebd6 100644 (file)
@@ -187,7 +187,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
                skb_queue_walk(queue, skb) {
                        *peeked = skb->peeked;
                        if (flags & MSG_PEEK) {
-                               if (*off >= skb->len) {
+                               if (*off >= skb->len && skb->len) {
                                        *off -= skb->len;
                                        continue;
                                }
index d0cbc93fcf32d94db2b909274dd60a9fe88cc80e..f64e439b4a00fe206fb634745a470475eb31cbb9 100644 (file)
@@ -203,7 +203,7 @@ static struct list_head offload_base __read_mostly;
 DEFINE_RWLOCK(dev_base_lock);
 EXPORT_SYMBOL(dev_base_lock);
 
-DEFINE_SEQLOCK(devnet_rename_seq);
+seqcount_t devnet_rename_seq;
 
 static inline void dev_base_seq_inc(struct net *net)
 {
@@ -1093,10 +1093,10 @@ int dev_change_name(struct net_device *dev, const char *newname)
        if (dev->flags & IFF_UP)
                return -EBUSY;
 
-       write_seqlock(&devnet_rename_seq);
+       write_seqcount_begin(&devnet_rename_seq);
 
        if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
-               write_sequnlock(&devnet_rename_seq);
+               write_seqcount_end(&devnet_rename_seq);
                return 0;
        }
 
@@ -1104,7 +1104,7 @@ int dev_change_name(struct net_device *dev, const char *newname)
 
        err = dev_get_valid_name(net, dev, newname);
        if (err < 0) {
-               write_sequnlock(&devnet_rename_seq);
+               write_seqcount_end(&devnet_rename_seq);
                return err;
        }
 
@@ -1112,11 +1112,11 @@ rollback:
        ret = device_rename(&dev->dev, dev->name);
        if (ret) {
                memcpy(dev->name, oldname, IFNAMSIZ);
-               write_sequnlock(&devnet_rename_seq);
+               write_seqcount_end(&devnet_rename_seq);
                return ret;
        }
 
-       write_sequnlock(&devnet_rename_seq);
+       write_seqcount_end(&devnet_rename_seq);
 
        write_lock_bh(&dev_base_lock);
        hlist_del_rcu(&dev->name_hlist);
@@ -1135,7 +1135,7 @@ rollback:
                /* err >= 0 after dev_alloc_name() or stores the first errno */
                if (err >= 0) {
                        err = ret;
-                       write_seqlock(&devnet_rename_seq);
+                       write_seqcount_begin(&devnet_rename_seq);
                        memcpy(dev->name, oldname, IFNAMSIZ);
                        goto rollback;
                } else {
@@ -4180,7 +4180,7 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
                return -EFAULT;
 
 retry:
-       seq = read_seqbegin(&devnet_rename_seq);
+       seq = read_seqcount_begin(&devnet_rename_seq);
        rcu_read_lock();
        dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex);
        if (!dev) {
@@ -4190,7 +4190,7 @@ retry:
 
        strcpy(ifr.ifr_name, dev->name);
        rcu_read_unlock();
-       if (read_seqretry(&devnet_rename_seq, seq))
+       if (read_seqcount_retry(&devnet_rename_seq, seq))
                goto retry;
 
        if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
@@ -6121,6 +6121,14 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev)
 
 static const struct ethtool_ops default_ethtool_ops;
 
+void netdev_set_default_ethtool_ops(struct net_device *dev,
+                                   const struct ethtool_ops *ops)
+{
+       if (dev->ethtool_ops == &default_ethtool_ops)
+               dev->ethtool_ops = ops;
+}
+EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops);
+
 /**
  *     alloc_netdev_mqs - allocate network device
  *     @sizeof_priv:   size of private data to allocate space for
index 334efd5d67a9efe9706fcd0feca4f0afc3621f2e..28c5f5aa7ca7e019b93e07f4d58a6758a7f5a78b 100644 (file)
@@ -1334,7 +1334,6 @@ struct kobj_ns_type_operations net_ns_type_operations = {
 };
 EXPORT_SYMBOL_GPL(net_ns_type_operations);
 
-#ifdef CONFIG_HOTPLUG
 static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
 {
        struct net_device *dev = to_net_dev(d);
@@ -1353,7 +1352,6 @@ static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
 exit:
        return retval;
 }
-#endif
 
 /*
  *     netdev_release -- destroy and free a dead device.
@@ -1382,9 +1380,7 @@ static struct class net_class = {
 #ifdef CONFIG_SYSFS
        .dev_attrs = net_class_attributes,
 #endif /* CONFIG_SYSFS */
-#ifdef CONFIG_HOTPLUG
        .dev_uevent = netdev_uevent,
-#endif
        .ns_type = &net_ns_type_operations,
        .namespace = net_namespace,
 };
index b29dacf900f9496a42a565a3b2c48ad9cf502c74..e6e1cbe863f57cc18dfc3e25ed2eeffca45e618b 100644 (file)
@@ -1781,10 +1781,13 @@ static ssize_t pktgen_thread_write(struct file *file,
                        return -EFAULT;
                i += len;
                mutex_lock(&pktgen_thread_lock);
-               pktgen_add_device(t, f);
+               ret = pktgen_add_device(t, f);
                mutex_unlock(&pktgen_thread_lock);
-               ret = count;
-               sprintf(pg_result, "OK: add_device=%s", f);
+               if (!ret) {
+                       ret = count;
+                       sprintf(pg_result, "OK: add_device=%s", f);
+               } else
+                       sprintf(pg_result, "ERROR: can not add device %s", f);
                goto out;
        }
 
index c31d9e8668c30346894adbf3be55eed4beeb1258..4425148d2b51592626b92a1451d9bc1208213fb8 100644 (file)
@@ -186,8 +186,6 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
        struct fastopen_queue *fastopenq =
            inet_csk(lsk)->icsk_accept_queue.fastopenq;
 
-       BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk));
-
        tcp_sk(sk)->fastopen_rsk = NULL;
        spin_lock_bh(&fastopenq->lock);
        fastopenq->qlen--;
index 57fb1ee6649f65a0994d86c6f8763fe6e14ba081..905dcc6ad1e3b480c01f87df5157f4e37de112a1 100644 (file)
@@ -35,6 +35,7 @@
 #include <net/sock.h>
 #include <net/compat.h>
 #include <net/scm.h>
+#include <net/cls_cgroup.h>
 
 
 /*
@@ -302,8 +303,10 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
                }
                /* Bump the usage count and install the file. */
                sock = sock_from_file(fp[i], &err);
-               if (sock)
+               if (sock) {
                        sock_update_netprioidx(sock->sk, current);
+                       sock_update_classid(sock->sk, current);
+               }
                fd_install(new_fd, get_file(fp[i]));
        }
 
index 3ab989b0de42a0bfe7905ee99d98901ee9e9a075..32443ebc3e890532810b94c6196b182ccdf558d4 100644 (file)
@@ -683,7 +683,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->network_header     = old->network_header;
        new->mac_header         = old->mac_header;
        new->inner_transport_header = old->inner_transport_header;
-       new->inner_network_header = old->inner_transport_header;
+       new->inner_network_header = old->inner_network_header;
        skb_dst_copy(new, old);
        new->rxhash             = old->rxhash;
        new->ooo_okay           = old->ooo_okay;
@@ -1649,7 +1649,7 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
 
 static struct page *linear_to_page(struct page *page, unsigned int *len,
                                   unsigned int *offset,
-                                  struct sk_buff *skb, struct sock *sk)
+                                  struct sock *sk)
 {
        struct page_frag *pfrag = sk_page_frag(sk);
 
@@ -1682,14 +1682,14 @@ static bool spd_can_coalesce(const struct splice_pipe_desc *spd,
 static bool spd_fill_page(struct splice_pipe_desc *spd,
                          struct pipe_inode_info *pipe, struct page *page,
                          unsigned int *len, unsigned int offset,
-                         struct sk_buff *skb, bool linear,
+                         bool linear,
                          struct sock *sk)
 {
        if (unlikely(spd->nr_pages == MAX_SKB_FRAGS))
                return true;
 
        if (linear) {
-               page = linear_to_page(page, len, &offset, skb, sk);
+               page = linear_to_page(page, len, &offset, sk);
                if (!page)
                        return true;
        }
@@ -1706,23 +1706,9 @@ static bool spd_fill_page(struct splice_pipe_desc *spd,
        return false;
 }
 
-static inline void __segment_seek(struct page **page, unsigned int *poff,
-                                 unsigned int *plen, unsigned int off)
-{
-       unsigned long n;
-
-       *poff += off;
-       n = *poff / PAGE_SIZE;
-       if (n)
-               *page = nth_page(*page, n);
-
-       *poff = *poff % PAGE_SIZE;
-       *plen -= off;
-}
-
 static bool __splice_segment(struct page *page, unsigned int poff,
                             unsigned int plen, unsigned int *off,
-                            unsigned int *len, struct sk_buff *skb,
+                            unsigned int *len,
                             struct splice_pipe_desc *spd, bool linear,
                             struct sock *sk,
                             struct pipe_inode_info *pipe)
@@ -1737,23 +1723,19 @@ static bool __splice_segment(struct page *page, unsigned int poff,
        }
 
        /* ignore any bits we already processed */
-       if (*off) {
-               __segment_seek(&page, &poff, &plen, *off);
-               *off = 0;
-       }
+       poff += *off;
+       plen -= *off;
+       *off = 0;
 
        do {
                unsigned int flen = min(*len, plen);
 
-               /* the linear region may spread across several pages  */
-               flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
-
-               if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk))
+               if (spd_fill_page(spd, pipe, page, &flen, poff,
+                                 linear, sk))
                        return true;
-
-               __segment_seek(&page, &poff, &plen, flen);
+               poff += flen;
+               plen -= flen;
                *len -= flen;
-
        } while (*len && plen);
 
        return false;
@@ -1777,7 +1759,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
        if (__splice_segment(virt_to_page(skb->data),
                             (unsigned long) skb->data & (PAGE_SIZE - 1),
                             skb_headlen(skb),
-                            offset, len, skb, spd,
+                            offset, len, spd,
                             skb_head_is_locked(skb),
                             sk, pipe))
                return true;
@@ -1790,7 +1772,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
 
                if (__splice_segment(skb_frag_page(f),
                                     f->page_offset, skb_frag_size(f),
-                                    offset, len, skb, spd, false, sk, pipe))
+                                    offset, len, spd, false, sk, pipe))
                        return true;
        }
 
index a692ef49c9bb9b2d996f0538049a135a93c26812..bc131d419683c11bd6f098c930e7d4f3cd9fb697 100644 (file)
@@ -583,7 +583,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
                goto out;
 
 retry:
-       seq = read_seqbegin(&devnet_rename_seq);
+       seq = read_seqcount_begin(&devnet_rename_seq);
        rcu_read_lock();
        dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
        ret = -ENODEV;
@@ -594,7 +594,7 @@ retry:
 
        strcpy(devname, dev->name);
        rcu_read_unlock();
-       if (read_seqretry(&devnet_rename_seq, seq))
+       if (read_seqcount_retry(&devnet_rename_seq, seq))
                goto retry;
 
        len = strlen(devname) + 1;
index a0d8392491c3c3e947876c943457227e4ed4ad92..a69b4e4a02b5099043d98e5278355274e18ea72b 100644 (file)
@@ -269,7 +269,11 @@ static void ah_input_done(struct crypto_async_request *base, int err)
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, ihl);
        __skb_pull(skb, ah_hlen + ihl);
-       skb_set_transport_header(skb, -ihl);
+
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -ihl);
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -381,7 +385,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, ihl);
        __skb_pull(skb, ah_hlen + ihl);
-       skb_set_transport_header(skb, -ihl);
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -ihl);
 
        err = nexthdr;
 
@@ -413,9 +420,12 @@ static void ah4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+               atomic_inc(&flow_cache_genid);
+               rt_genid_bump(net);
+
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
        xfrm_state_put(x);
 }
index ce6fbdfd40b893edc29aa090052663024039eadc..ded146b217f10dbd511da977fe1e146f848c8272 100644 (file)
@@ -321,7 +321,7 @@ static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
        __be32 saddr = 0;
-       u8  *dst_ha = NULL;
+       u8 dst_ha[MAX_ADDR_LEN], *dst_hw = NULL;
        struct net_device *dev = neigh->dev;
        __be32 target = *(__be32 *)neigh->primary_key;
        int probes = atomic_read(&neigh->probes);
@@ -363,8 +363,8 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        if (probes < 0) {
                if (!(neigh->nud_state & NUD_VALID))
                        pr_debug("trying to ucast probe in NUD_INVALID\n");
-               dst_ha = neigh->ha;
-               read_lock_bh(&neigh->lock);
+               neigh_ha_snapshot(dst_ha, neigh, dev);
+               dst_hw = dst_ha;
        } else {
                probes -= neigh->parms->app_probes;
                if (probes < 0) {
@@ -376,9 +376,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        }
 
        arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
-                dst_ha, dev->dev_addr, NULL);
-       if (dst_ha)
-               read_unlock_bh(&neigh->lock);
+                dst_hw, dev->dev_addr, NULL);
 }
 
 static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
@@ -930,24 +928,25 @@ static void parp_redo(struct sk_buff *skb)
 static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
                   struct packet_type *pt, struct net_device *orig_dev)
 {
-       struct arphdr *arp;
+       const struct arphdr *arp;
+
+       if (dev->flags & IFF_NOARP ||
+           skb->pkt_type == PACKET_OTHERHOST ||
+           skb->pkt_type == PACKET_LOOPBACK)
+               goto freeskb;
+
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               goto out_of_mem;
 
        /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
        if (!pskb_may_pull(skb, arp_hdr_len(dev)))
                goto freeskb;
 
        arp = arp_hdr(skb);
-       if (arp->ar_hln != dev->addr_len ||
-           dev->flags & IFF_NOARP ||
-           skb->pkt_type == PACKET_OTHERHOST ||
-           skb->pkt_type == PACKET_LOOPBACK ||
-           arp->ar_pln != 4)
+       if (arp->ar_hln != dev->addr_len || arp->ar_pln != 4)
                goto freeskb;
 
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (skb == NULL)
-               goto out_of_mem;
-
        memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
 
        return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
index 424fafbc8cb02c49fb2dd3551f3583290f2fc330..b28e863fe0a7143b199bee51cfdf242c125f31cf 100644 (file)
@@ -85,3 +85,28 @@ out:
        return err;
 }
 EXPORT_SYMBOL(ip4_datagram_connect);
+
+void ip4_datagram_release_cb(struct sock *sk)
+{
+       const struct inet_sock *inet = inet_sk(sk);
+       const struct ip_options_rcu *inet_opt;
+       __be32 daddr = inet->inet_daddr;
+       struct flowi4 fl4;
+       struct rtable *rt;
+
+       if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0))
+               return;
+
+       rcu_read_lock();
+       inet_opt = rcu_dereference(inet->inet_opt);
+       if (inet_opt && inet_opt->opt.srr)
+               daddr = inet_opt->opt.faddr;
+       rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr,
+                                  inet->inet_saddr, inet->inet_dport,
+                                  inet->inet_sport, sk->sk_protocol,
+                                  RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
+       if (!IS_ERR(rt))
+               __sk_dst_set(sk, &rt->dst);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);
index cc06a47f12163ad8b93cae060a8c211bb13fcc73..a8e4f2665d5e6687c28438de69586673be9b3484 100644 (file)
@@ -823,9 +823,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                if (!ifa) {
                        ret = -ENOBUFS;
                        ifa = inet_alloc_ifa();
-                       INIT_HLIST_NODE(&ifa->hash);
                        if (!ifa)
                                break;
+                       INIT_HLIST_NODE(&ifa->hash);
                        if (colon)
                                memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
                        else
index b61e9deb7c7ecc9cae92ab0365b871a773627cc4..3b4f0cd2e63edbd136683577873b288712a4b92a 100644 (file)
@@ -346,7 +346,10 @@ static int esp_input_done2(struct sk_buff *skb, int err)
 
        pskb_trim(skb, skb->len - alen - padlen - 2);
        __skb_pull(skb, hlen);
-       skb_set_transport_header(skb, -ihl);
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -ihl);
 
        err = nexthdr[1];
 
@@ -499,9 +502,12 @@ static void esp4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+               atomic_inc(&flow_cache_genid);
+               rt_genid_bump(net);
+
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
        xfrm_state_put(x);
 }
index a85ae2f7a21cb15502bd69e9c63a1ec29020fa40..e81b1caf2ea2a0ceaa20ef8e1847ebd4f71cd98e 100644 (file)
@@ -750,6 +750,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        int    gre_hlen;
        __be32 dst;
        int    mtu;
+       u8     ttl;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
            skb_checksum_help(skb))
@@ -760,7 +761,10 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 
        if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
                gre_hlen = 0;
-               tiph = (const struct iphdr *)skb->data;
+               if (skb->protocol == htons(ETH_P_IP))
+                       tiph = (const struct iphdr *)skb->data;
+               else
+                       tiph = &tunnel->parms.iph;
        } else {
                gre_hlen = tunnel->hlen;
                tiph = &tunnel->parms.iph;
@@ -812,6 +816,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        goto tx_error;
        }
 
+       ttl = tiph->ttl;
        tos = tiph->tos;
        if (tos == 1) {
                tos = 0;
@@ -904,11 +909,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                dev_kfree_skb(skb);
                skb = new_skb;
                old_iph = ip_hdr(skb);
+               /* Warning : tiph value might point to freed memory */
        }
 
-       skb_reset_transport_header(skb);
        skb_push(skb, gre_hlen);
        skb_reset_network_header(skb);
+       skb_set_transport_header(skb, sizeof(*iph));
        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
        IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
                              IPSKB_REROUTED);
@@ -927,8 +933,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        iph->tos                =       ipgre_ecn_encapsulate(tos, old_iph, skb);
        iph->daddr              =       fl4.daddr;
        iph->saddr              =       fl4.saddr;
+       iph->ttl                =       ttl;
 
-       if ((iph->ttl = tiph->ttl) == 0) {
+       if (ttl == 0) {
                if (skb->protocol == htons(ETH_P_IP))
                        iph->ttl = old_iph->ttl;
 #if IS_ENABLED(CONFIG_IPV6)
@@ -956,8 +963,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        ptr--;
                }
                if (tunnel->parms.o_flags&GRE_CSUM) {
+                       int offset = skb_transport_offset(skb);
+
                        *ptr = 0;
-                       *(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr));
+                       *(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset,
+                                                                skb->len - offset,
+                                                                0));
                }
        }
 
index 3c9d20880283de0f9b5244eae8184e76d9a20dcd..d9c4f113d7093bba7eba2beefc31cd0af4b9bb95 100644 (file)
@@ -590,7 +590,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
        case IP_TTL:
                if (optlen < 1)
                        goto e_inval;
-               if (val != -1 && (val < 0 || val > 255))
+               if (val != -1 && (val < 1 || val > 255))
                        goto e_inval;
                inet->uc_ttl = val;
                break;
index d3ab47e19a896277161c2bf1b87706c20ebd73be..9a46daed2f3c05be9ed82138edac731fcc571145 100644 (file)
@@ -47,9 +47,12 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
        if (!x)
                return;
 
-       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+       if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+               atomic_inc(&flow_cache_genid);
+               rt_genid_bump(net);
+
                ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
-       else
+       else
                ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
        xfrm_state_put(x);
 }
index d763701cff1b4aca032e60f335a4208e054a4e06..a2e50ae80b53361ca30c718dce7e85b5e4e7c66c 100644 (file)
@@ -136,6 +136,8 @@ __be32 ic_myaddr = NONE;            /* My IP address */
 static __be32 ic_netmask = NONE;       /* Netmask for local subnet */
 __be32 ic_gateway = NONE;      /* Gateway IP address */
 
+__be32 ic_addrservaddr = NONE; /* IP Address of the IP addresses'server */
+
 __be32 ic_servaddr = NONE;     /* Boot server IP address */
 
 __be32 root_server_addr = NONE;        /* Address of NFS server */
@@ -558,6 +560,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        if (ic_myaddr == NONE)
                ic_myaddr = tip;
        ic_servaddr = sip;
+       ic_addrservaddr = sip;
        ic_got_reply = IC_RARP;
 
 drop_unlock:
@@ -1068,7 +1071,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
                                ic_servaddr = server_id;
 #ifdef IPCONFIG_DEBUG
                                printk("DHCP: Offered address %pI4 by server %pI4\n",
-                                      &ic_myaddr, &ic_servaddr);
+                                      &ic_myaddr, &b->iph.saddr);
 #endif
                                /* The DHCP indicated server address takes
                                 * precedence over the bootp header one if
@@ -1113,6 +1116,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
        ic_dev = dev;
        ic_myaddr = b->your_ip;
        ic_servaddr = b->server_ip;
+       ic_addrservaddr = b->iph.saddr;
        if (ic_gateway == NONE && b->relay_ip)
                ic_gateway = b->relay_ip;
        if (ic_nameservers[0] == NONE)
@@ -1268,7 +1272,7 @@ static int __init ic_dynamic(void)
        printk("IP-Config: Got %s answer from %pI4, ",
                ((ic_got_reply & IC_RARP) ? "RARP"
                 : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
-              &ic_servaddr);
+              &ic_addrservaddr);
        pr_cont("my address is %pI4\n", &ic_myaddr);
 
        return 0;
index 51f13f8ec724f8c5dad543073e8a0d82639b555a..04b18c1ac3458503a2b5d79bd7fd1547c13e76d7 100644 (file)
@@ -81,6 +81,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        niph->saddr     = oiph->daddr;
        niph->daddr     = oiph->saddr;
 
+       skb_reset_transport_header(nskb);
        tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
        memset(tcph, 0, sizeof(*tcph));
        tcph->source    = oth->dest;
index da2c8a368f68d9c6b72c605593aa5b83e0622344..eeaff7e4acb5c8da1c042769ac4c805579260bef 100644 (file)
@@ -124,23 +124,28 @@ nf_nat_ipv4_fn(unsigned int hooknum,
                        ret = nf_nat_rule_find(skb, hooknum, in, out, ct);
                        if (ret != NF_ACCEPT)
                                return ret;
-               } else
+               } else {
                        pr_debug("Already setup manip %s for ct %p\n",
                                 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
                                 ct);
+                       if (nf_nat_oif_changed(hooknum, ctinfo, nat, out))
+                               goto oif_changed;
+               }
                break;
 
        default:
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == IP_CT_ESTABLISHED_REPLY);
-               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
-                       nf_ct_kill_acct(ct, ctinfo, skb);
-                       return NF_DROP;
-               }
+               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out))
+                       goto oif_changed;
        }
 
        return nf_nat_packet(ct, ctinfo, hooknum, skb);
+
+oif_changed:
+       nf_ct_kill_acct(ct, ctinfo, skb);
+       return NF_DROP;
 }
 
 static unsigned int
index 8f3d05424a3e8f2f318c36bf007fd17724533997..6f9c07268cf6d433379898421e978d74fa49952f 100644 (file)
@@ -738,6 +738,7 @@ struct proto ping_prot = {
        .recvmsg =      ping_recvmsg,
        .bind =         ping_bind,
        .backlog_rcv =  ping_queue_rcv_skb,
+       .release_cb =   ip4_datagram_release_cb,
        .hash =         ping_v4_hash,
        .unhash =       ping_v4_unhash,
        .get_port =     ping_v4_get_port,
index 73d1e4df4bf630f176f385b96639b4e803469458..6f08991409c3ad9d3620357d04d1f59005f7e2fa 100644 (file)
@@ -894,6 +894,7 @@ struct proto raw_prot = {
        .recvmsg           = raw_recvmsg,
        .bind              = raw_bind,
        .backlog_rcv       = raw_rcv_skb,
+       .release_cb        = ip4_datagram_release_cb,
        .hash              = raw_hash_sk,
        .unhash            = raw_unhash_sk,
        .obj_size          = sizeof(struct raw_sock),
index 844a9ef60dbd89f459515101ebb0db6e7cfaa8a3..a0fcc47fee732744baf42bf1e61772faad87982d 100644 (file)
@@ -912,6 +912,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
        struct dst_entry *dst = &rt->dst;
        struct fib_result res;
 
+       if (dst_metric_locked(dst, RTAX_MTU))
+               return;
+
        if (dst->dev->mtu < mtu)
                return;
 
@@ -962,7 +965,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
 }
 EXPORT_SYMBOL_GPL(ipv4_update_pmtu);
 
-void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
+static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
 {
        const struct iphdr *iph = (const struct iphdr *) skb->data;
        struct flowi4 fl4;
@@ -975,6 +978,53 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
                ip_rt_put(rt);
        }
 }
+
+void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
+{
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       struct flowi4 fl4;
+       struct rtable *rt;
+       struct dst_entry *dst;
+       bool new = false;
+
+       bh_lock_sock(sk);
+       rt = (struct rtable *) __sk_dst_get(sk);
+
+       if (sock_owned_by_user(sk) || !rt) {
+               __ipv4_sk_update_pmtu(skb, sk, mtu);
+               goto out;
+       }
+
+       __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+
+       if (!__sk_dst_check(sk, 0)) {
+               rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
+               if (IS_ERR(rt))
+                       goto out;
+
+               new = true;
+       }
+
+       __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu);
+
+       dst = dst_check(&rt->dst, 0);
+       if (!dst) {
+               if (new)
+                       dst_release(&rt->dst);
+
+               rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
+               if (IS_ERR(rt))
+                       goto out;
+
+               new = true;
+       }
+
+       if (new)
+               __sk_dst_set(sk, &rt->dst);
+
+out:
+       bh_unlock_sock(sk);
+}
 EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu);
 
 void ipv4_redirect(struct sk_buff *skb, struct net *net,
@@ -1120,7 +1170,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
        if (!mtu || time_after_eq(jiffies, rt->dst.expires))
                mtu = dst_metric_raw(dst, RTAX_MTU);
 
-       if (mtu && rt_is_output_route(rt))
+       if (mtu)
                return mtu;
 
        mtu = dst->dev->mtu;
index 1ca253635f7acdda23624c28ae1ead4645bd0dd5..2aa69c8ae60c1990c76e69fe5aef46b990b6da6e 100644 (file)
@@ -1428,12 +1428,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait)
 }
 #endif
 
-static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
+static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
 {
        struct sk_buff *skb;
        u32 offset;
 
-       skb_queue_walk(&sk->sk_receive_queue, skb) {
+       while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
                offset = seq - TCP_SKB_CB(skb)->seq;
                if (tcp_hdr(skb)->syn)
                        offset--;
@@ -1441,6 +1441,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
                        *off = offset;
                        return skb;
                }
+               /* This looks weird, but this can happen if TCP collapsing
+                * splitted a fat GRO packet, while we released socket lock
+                * in skb_splice_bits()
+                */
+               sk_eat_skb(sk, skb, false);
        }
        return NULL;
 }
@@ -1482,7 +1487,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
                                        break;
                        }
                        used = recv_actor(desc, skb, offset, len);
-                       if (used < 0) {
+                       if (used <= 0) {
                                if (!copied)
                                        copied = used;
                                break;
@@ -1520,8 +1525,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
        tcp_rcv_space_adjust(sk);
 
        /* Clean up data we have read: This will do ACK frames. */
-       if (copied > 0)
+       if (copied > 0) {
+               tcp_recv_skb(sk, seq, &offset);
                tcp_cleanup_rbuf(sk, copied);
+       }
        return copied;
 }
 EXPORT_SYMBOL(tcp_read_sock);
index 291f2ed7cc311649a72700d65098b6d70ba338b5..cdf2e707bb100500511d6b2d46ece69e19163cfa 100644 (file)
@@ -310,6 +310,12 @@ void tcp_slow_start(struct tcp_sock *tp)
 {
        int cnt; /* increase in packets */
        unsigned int delta = 0;
+       u32 snd_cwnd = tp->snd_cwnd;
+
+       if (unlikely(!snd_cwnd)) {
+               pr_err_once("snd_cwnd is nul, please report this bug.\n");
+               snd_cwnd = 1U;
+       }
 
        /* RFC3465: ABC Slow start
         * Increase only after a full MSS of bytes is acked
@@ -324,7 +330,7 @@ void tcp_slow_start(struct tcp_sock *tp)
        if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)
                cnt = sysctl_tcp_max_ssthresh >> 1;     /* limited slow start */
        else
-               cnt = tp->snd_cwnd;                     /* exponential increase */
+               cnt = snd_cwnd;                         /* exponential increase */
 
        /* RFC3465: ABC
         * We MAY increase by 2 if discovered delayed ack
@@ -334,11 +340,11 @@ void tcp_slow_start(struct tcp_sock *tp)
        tp->bytes_acked = 0;
 
        tp->snd_cwnd_cnt += cnt;
-       while (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
-               tp->snd_cwnd_cnt -= tp->snd_cwnd;
+       while (tp->snd_cwnd_cnt >= snd_cwnd) {
+               tp->snd_cwnd_cnt -= snd_cwnd;
                delta++;
        }
-       tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp);
+       tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp);
 }
 EXPORT_SYMBOL_GPL(tcp_slow_start);
 
index a13692560e637b215f56c906e3302e5a19a0bc44..ad70a962c20e1daa7637a190d1c81208d6656263 100644 (file)
@@ -3504,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag)
                }
        } else {
                if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) {
+                       if (!tcp_packets_in_flight(tp)) {
+                               tcp_enter_frto_loss(sk, 2, flag);
+                               return true;
+                       }
+
                        /* Prevent sending of new data. */
                        tp->snd_cwnd = min(tp->snd_cwnd,
                                           tcp_packets_in_flight(tp));
@@ -5543,6 +5548,9 @@ slow_path:
        if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
                goto csum_error;
 
+       if (!th->ack && !th->rst)
+               goto discard;
+
        /*
         *      Standard slow path.
         */
@@ -5551,7 +5559,7 @@ slow_path:
                return 0;
 
 step5:
-       if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+       if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
                goto discard;
 
        /* ts_recent update must be made after we are sure that the packet
@@ -5646,8 +5654,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
         * the remote receives only the retransmitted (regular) SYNs: either
         * the original SYN-data or the corresponding SYN-ACK is lost.
         */
-       syn_drop = (cookie->len <= 0 && data &&
-                   inet_csk(sk)->icsk_retransmits);
+       syn_drop = (cookie->len <= 0 && data && tp->total_retrans);
 
        tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
 
@@ -5984,11 +5991,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
                        goto discard;
        }
+
+       if (!th->ack && !th->rst)
+               goto discard;
+
        if (!tcp_validate_incoming(sk, skb, th, 0))
                return 0;
 
        /* step 5: check the ACK field */
-       if (th->ack) {
+       if (true) {
                int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
 
                switch (sk->sk_state) {
@@ -6138,8 +6149,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                        }
                        break;
                }
-       } else
-               goto discard;
+       }
 
        /* ts_recent update must be made after we are sure that the packet
         * is in window.
index 54139fa514e6ee2d82c4cf9ca8528e012b546a90..eadb693eef55dffdaacf538b36ced145b09fa191 100644 (file)
@@ -369,11 +369,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
         * We do take care of PMTU discovery (RFC1191) special case :
         * we can receive locally generated ICMP messages while socket is held.
         */
-       if (sock_owned_by_user(sk) &&
-           type != ICMP_DEST_UNREACH &&
-           code != ICMP_FRAG_NEEDED)
-               NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
-
+       if (sock_owned_by_user(sk)) {
+               if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED))
+                       NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
+       }
        if (sk->sk_state == TCP_CLOSE)
                goto out;
 
@@ -497,6 +496,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                 * errors returned from accept().
                 */
                inet_csk_reqsk_queue_drop(sk, req, prev);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
        case TCP_SYN_SENT:
@@ -1501,8 +1501,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
         * clogging syn queue with openreqs with exponentially increasing
         * timeout.
         */
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
+       }
 
        req = inet_reqsk_alloc(&tcp_request_sock_ops);
        if (!req)
@@ -1667,6 +1669,7 @@ drop_and_release:
 drop_and_free:
        reqsk_free(req);
 drop:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return 0;
 }
 EXPORT_SYMBOL(tcp_v4_conn_request);
index 79c8dbe59b5474bdc3e23ba8adc227e1bee016a4..1f4d405eafba746d2b8085132a740b17a6658c80 100644 (file)
@@ -1952,6 +1952,7 @@ struct proto udp_prot = {
        .recvmsg           = udp_recvmsg,
        .sendpage          = udp_sendpage,
        .backlog_rcv       = __udp_queue_rcv_skb,
+       .release_cb        = ip4_datagram_release_cb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
        .rehash            = udp_v4_rehash,
index 408cac4ae00a41129e4bf89506e96f646c607380..1b5d8cb9b123dff17c85d59f6d1c8e44cfdefa4e 100644 (file)
@@ -154,6 +154,11 @@ static void addrconf_type_change(struct net_device *dev,
                                 unsigned long event);
 static int addrconf_ifdown(struct net_device *dev, int how);
 
+static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
+                                                 int plen,
+                                                 const struct net_device *dev,
+                                                 u32 flags, u32 noflags);
+
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_timer(unsigned long data);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
@@ -250,12 +255,6 @@ static inline bool addrconf_qdisc_ok(const struct net_device *dev)
        return !qdisc_tx_is_noop(dev);
 }
 
-/* Check if a route is valid prefix route */
-static inline int addrconf_is_prefix_route(const struct rt6_info *rt)
-{
-       return (rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0;
-}
-
 static void addrconf_del_timer(struct inet6_ifaddr *ifp)
 {
        if (del_timer(&ifp->timer))
@@ -941,17 +940,15 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
        if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
                struct in6_addr prefix;
                struct rt6_info *rt;
-               struct net *net = dev_net(ifp->idev->dev);
-               struct flowi6 fl6 = {};
 
                ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-               fl6.flowi6_oif = ifp->idev->dev->ifindex;
-               fl6.daddr = prefix;
-               rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
-                                                        RT6_LOOKUP_F_IFACE);
 
-               if (rt != net->ipv6.ip6_null_entry &&
-                   addrconf_is_prefix_route(rt)) {
+               rt = addrconf_get_prefix_route(&prefix,
+                                              ifp->prefix_len,
+                                              ifp->idev->dev,
+                                              0, RTF_GATEWAY | RTF_DEFAULT);
+
+               if (rt) {
                        if (onlink == 0) {
                                ip6_del_rt(rt);
                                rt = NULL;
@@ -1663,6 +1660,7 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)
        if (dev->addr_len != IEEE802154_ADDR_LEN)
                return -1;
        memcpy(eui, dev->dev_addr, 8);
+       eui[0] ^= 2;
        return 0;
 }
 
@@ -1877,7 +1875,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
                        continue;
                if ((rt->rt6i_flags & flags) != flags)
                        continue;
-               if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0))
+               if ((rt->rt6i_flags & noflags) != 0)
                        continue;
                dst_hold(&rt->dst);
                break;
index ecc35b93314bb1b73c70df219c9cf8f125c77908..384233188ac1e38468b5edf71c105c21e6bf38bc 100644 (file)
@@ -472,7 +472,10 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, hdr_len);
        __skb_pull(skb, ah_hlen + hdr_len);
-       skb_set_transport_header(skb, -hdr_len);
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -hdr_len);
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -593,9 +596,13 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
 
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, hdr_len);
-       skb->transport_header = skb->network_header;
        __skb_pull(skb, ah_hlen + hdr_len);
 
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -hdr_len);
+
        err = nexthdr;
 
 out_free:
index 8edf2601065af07790500809b8dee9fad0fc8eaa..7a778b9a7b859586219a37c7f80bd6ffeefe27c6 100644 (file)
@@ -380,7 +380,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
-                               datagram_recv_ctl(sk, msg, skb);
+                               ip6_datagram_recv_ctl(sk, msg, skb);
                        if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
                                sin->sin6_scope_id = IP6CB(skb)->iif;
                } else {
@@ -468,7 +468,8 @@ out:
 }
 
 
-int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
+int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+                         struct sk_buff *skb)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct inet6_skb_parm *opt = IP6CB(skb);
@@ -597,11 +598,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);
 
-int datagram_send_ctl(struct net *net, struct sock *sk,
-                     struct msghdr *msg, struct flowi6 *fl6,
-                     struct ipv6_txoptions *opt,
-                     int *hlimit, int *tclass, int *dontfrag)
+int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
+                         struct msghdr *msg, struct flowi6 *fl6,
+                         struct ipv6_txoptions *opt,
+                         int *hlimit, int *tclass, int *dontfrag)
 {
        struct in6_pktinfo *src_info;
        struct cmsghdr *cmsg;
@@ -871,4 +873,4 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
 exit_f:
        return err;
 }
-EXPORT_SYMBOL_GPL(datagram_send_ctl);
+EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
index 282f3723ee194704ab7fa0757e2c032254903300..40ffd72243a4f2d1ec9e5da494b3f2650dd027a6 100644 (file)
@@ -300,7 +300,10 @@ static int esp_input_done2(struct sk_buff *skb, int err)
 
        pskb_trim(skb, skb->len - alen - padlen - 2);
        __skb_pull(skb, hlen);
-       skb_set_transport_header(skb, -hdr_len);
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               skb_reset_transport_header(skb);
+       else
+               skb_set_transport_header(skb, -hdr_len);
 
        err = nexthdr[1];
 
index b4a9fd51dae74bd8143b2d32e791e089f1d8562f..fff5bdd8b6800d56679957a62e201e84fd846d09 100644 (file)
@@ -81,10 +81,22 @@ static inline struct sock *icmpv6_sk(struct net *net)
        return net->ipv6.icmp_sk[smp_processor_id()];
 }
 
+static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                      u8 type, u8 code, int offset, __be32 info)
+{
+       struct net *net = dev_net(skb->dev);
+
+       if (type == ICMPV6_PKT_TOOBIG)
+               ip6_update_pmtu(skb, net, info, 0, 0);
+       else if (type == NDISC_REDIRECT)
+               ip6_redirect(skb, net, 0, 0);
+}
+
 static int icmpv6_rcv(struct sk_buff *skb);
 
 static const struct inet6_protocol icmpv6_protocol = {
        .handler        =       icmpv6_rcv,
+       .err_handler    =       icmpv6_err,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
index 29124b7a04c8dfb335df69014b5348e22b3fb6ab..d6de4b447250b752ec810c5e21b07f667ef95a8c 100644 (file)
@@ -365,8 +365,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
                msg.msg_control = (void*)(fl->opt+1);
                memset(&flowi6, 0, sizeof(flowi6));
 
-               err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk,
-                                       &junk, &junk);
+               err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt,
+                                           &junk, &junk, &junk);
                if (err)
                        goto done;
                err = -EINVAL;
index 867466c96aac053c6bf39c956160171a099ff304..131dd097736d174800cff6c9d554d274a4951884 100644 (file)
@@ -758,8 +758,6 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
                skb_dst_set_noref(skb, dst);
        }
 
-       skb->transport_header = skb->network_header;
-
        proto = NEXTHDR_GRE;
        if (encap_limit >= 0) {
                init_tel_txopt(&opt, encap_limit);
@@ -768,6 +766,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 
        skb_push(skb, gre_hlen);
        skb_reset_network_header(skb);
+       skb_set_transport_header(skb, sizeof(*ipv6h));
 
        /*
         *      Push down and install the IP header.
@@ -961,7 +960,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
        int ret;
 
        if (!ip6_tnl_xmit_ctl(t))
-               return -1;
+               goto tx_err;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
index 5552d13ae92f8554c04ec912b82317dfeef065a5..0c7c03d50dc0342c7caad25c9d24c3931c50438b 100644 (file)
@@ -1213,10 +1213,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                if (dst_allfrag(rt->dst.path))
                        cork->flags |= IPCORK_ALLFRAG;
                cork->length = 0;
-               exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len;
+               exthdrlen = (opt ? opt->opt_flen : 0);
                length += exthdrlen;
                transhdrlen += exthdrlen;
-               dst_exthdrlen = rt->dst.header_len;
+               dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len;
        } else {
                rt = (struct rt6_info *)cork->dst;
                fl6 = &inet->cork.fl.u.ip6;
index 26dcdec9e3a5f6cbbe799402c39bb5d09c9d561d..8fd154e5f07966dd049bcdb8e93d9f7b8ab5452e 100644 (file)
@@ -1710,6 +1710,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
                        return -EINVAL;
                if (get_user(v, (u32 __user *)optval))
                        return -EFAULT;
+               /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
+               if (v != RT_TABLE_DEFAULT && v >= 100000000)
+                       return -EINVAL;
                if (sk == mrt->mroute6_sk)
                        return -EBUSY;
 
index ee94d31c9d4d494cdfe2dce1ac812e4e094fe65f..d1e2e8ef29c54abd86064728ec145f0478f360af 100644 (file)
@@ -476,8 +476,8 @@ sticky_done:
                msg.msg_controllen = optlen;
                msg.msg_control = (void*)(opt+1);
 
-               retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk,
-                                        &junk);
+               retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk,
+                                            &junk, &junk);
                if (retv)
                        goto done;
 update:
@@ -1002,7 +1002,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                release_sock(sk);
 
                if (skb) {
-                       int err = datagram_recv_ctl(sk, &msg, skb);
+                       int err = ip6_datagram_recv_ctl(sk, &msg, skb);
                        kfree_skb(skb);
                        if (err)
                                return err;
index e9486915eff6e9b8e71038e48e3bc85c483dee02..83acc1405a18dcef218625e8517431978393ac12 100644 (file)
@@ -9,47 +9,38 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ipv6.h>
+#include <net/ipv6.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_ipv6/ip6t_NPT.h>
 #include <linux/netfilter/x_tables.h>
 
-static __sum16 csum16_complement(__sum16 a)
-{
-       return (__force __sum16)(0xffff - (__force u16)a);
-}
-
-static __sum16 csum16_add(__sum16 a, __sum16 b)
-{
-       u16 sum;
-
-       sum = (__force u16)a + (__force u16)b;
-       sum += (__force u16)a < (__force u16)b;
-       return (__force __sum16)sum;
-}
-
-static __sum16 csum16_sub(__sum16 a, __sum16 b)
-{
-       return csum16_add(a, csum16_complement(b));
-}
-
 static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
 {
        struct ip6t_npt_tginfo *npt = par->targinfo;
-       __sum16 src_sum = 0, dst_sum = 0;
+       __wsum src_sum = 0, dst_sum = 0;
+       struct in6_addr pfx;
        unsigned int i;
 
        if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)
                return -EINVAL;
 
+       /* Ensure that LSB of prefix is zero */
+       ipv6_addr_prefix(&pfx, &npt->src_pfx.in6, npt->src_pfx_len);
+       if (!ipv6_addr_equal(&pfx, &npt->src_pfx.in6))
+               return -EINVAL;
+       ipv6_addr_prefix(&pfx, &npt->dst_pfx.in6, npt->dst_pfx_len);
+       if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6))
+               return -EINVAL;
+
        for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {
-               src_sum = csum16_add(src_sum,
-                               (__force __sum16)npt->src_pfx.in6.s6_addr16[i]);
-               dst_sum = csum16_add(dst_sum,
-                               (__force __sum16)npt->dst_pfx.in6.s6_addr16[i]);
+               src_sum = csum_add(src_sum,
+                               (__force __wsum)npt->src_pfx.in6.s6_addr16[i]);
+               dst_sum = csum_add(dst_sum,
+                               (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]);
        }
 
-       npt->adjustment = csum16_sub(src_sum, dst_sum);
+       npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum));
        return 0;
 }
 
@@ -70,7 +61,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
 
                idx = i / 32;
                addr->s6_addr32[idx] &= mask;
-               addr->s6_addr32[idx] |= npt->dst_pfx.in6.s6_addr32[idx];
+               addr->s6_addr32[idx] |= ~mask & npt->dst_pfx.in6.s6_addr32[idx];
        }
 
        if (pfx_len <= 48)
@@ -85,8 +76,8 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
                        return false;
        }
 
-       sum = csum16_add((__force __sum16)addr->s6_addr16[idx],
-                        npt->adjustment);
+       sum = ~csum_fold(csum_add(csum_unfold((__force __sum16)addr->s6_addr16[idx]),
+                                 csum_unfold(npt->adjustment)));
        if (sum == CSUM_MANGLED_0)
                sum = 0;
        *(__force __sum16 *)&addr->s6_addr16[idx] = sum;
index fd4fb34c51c7f5b9bd62294de2abb6da943ee494..029623dbd4118d18667a83d209131dc64b5ec7c4 100644 (file)
@@ -132,6 +132,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
        ip6h->saddr = oip6h->daddr;
        ip6h->daddr = oip6h->saddr;
 
+       skb_reset_transport_header(nskb);
        tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
        /* Truncate to length (no data) */
        tcph->doff = sizeof(struct tcphdr)/4;
index 6c8ae24b85eb15f525e2e43a1b0e7f93068e8d85..e0e788d25b1431624ae9470f0af904803fe5d92a 100644 (file)
@@ -127,23 +127,28 @@ nf_nat_ipv6_fn(unsigned int hooknum,
                        ret = nf_nat_rule_find(skb, hooknum, in, out, ct);
                        if (ret != NF_ACCEPT)
                                return ret;
-               } else
+               } else {
                        pr_debug("Already setup manip %s for ct %p\n",
                                 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
                                 ct);
+                       if (nf_nat_oif_changed(hooknum, ctinfo, nat, out))
+                               goto oif_changed;
+               }
                break;
 
        default:
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == IP_CT_ESTABLISHED_REPLY);
-               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
-                       nf_ct_kill_acct(ct, ctinfo, skb);
-                       return NF_DROP;
-               }
+               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out))
+                       goto oif_changed;
        }
 
        return nf_nat_packet(ct, ctinfo, hooknum, skb);
+
+oif_changed:
+       nf_ct_kill_acct(ct, ctinfo, skb);
+       return NF_DROP;
 }
 
 static unsigned int
index 00ee17c3e8939b1076ae2c2026ed6dfa1b3f68de..137e245860ab41a9ec923a8655f538c8cc8d4e52 100644 (file)
@@ -81,8 +81,8 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
        }
        protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off);
        /*
-        * (protoff == skb->len) mean that the packet doesn't have no data
-        * except of IPv6 & ext headers. but it's tracked anyway. - YK
+        * (protoff == skb->len) means the packet has not data, just
+        * IPv6 and possibly extensions headers, but it is tracked anyway
         */
        if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
                pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
index 22c8ea9511852e963b982ad68ed7066bda262ad2..3dacecc9906597e3f44fa9475dda0afb8f4981c2 100644 (file)
@@ -311,7 +311,10 @@ found:
        else
                fq->q.fragments = skb;
 
-       skb->dev = NULL;
+       if (skb->dev) {
+               fq->iif = skb->dev->ifindex;
+               skb->dev = NULL;
+       }
        fq->q.stamp = skb->tstamp;
        fq->q.meat += skb->len;
        if (payload_len > fq->q.max_size)
index 6cd29b1e8b926e26a7bc0df5b5c5263fc2e23d84..70fa8144999780cef19f5102247882ba6d24f6f6 100644 (file)
@@ -507,7 +507,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        sock_recv_ts_and_drops(msg, sk, skb);
 
        if (np->rxopt.all)
-               datagram_recv_ctl(sk, msg, skb);
+               ip6_datagram_recv_ctl(sk, msg, skb);
 
        err = copied;
        if (flags & MSG_TRUNC)
@@ -822,8 +822,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
index e229a3bc345dc4138a188282c4ab4f1717882832..363d8b7772e8d23f180a8db6c0ae707225ad8a63 100644 (file)
@@ -928,7 +928,7 @@ restart:
        dst_hold(&rt->dst);
        read_unlock_bh(&table->tb6_lock);
 
-       if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP))
+       if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))
                nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
        else if (!(rt->dst.flags & DST_HOST))
                nrt = rt6_alloc_clone(rt, &fl6->daddr);
index 93825dd3a7c070be4dd1e294a155b409525337e2..4f43537197ef805927e84a182ae1e703edb0f2c8 100644 (file)
@@ -423,6 +423,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                }
 
                inet_csk_reqsk_queue_drop(sk, req, prev);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
        case TCP_SYN_SENT:
@@ -958,8 +959,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
                        goto drop;
        }
 
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
+       }
 
        req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
        if (req == NULL)
@@ -1108,6 +1111,7 @@ drop_and_release:
 drop_and_free:
        reqsk_free(req);
 drop:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return 0; /* don't send reset */
 }
 
index dfaa29b8b2939c03fef13fa416f6fdaef031bf5d..fb083295ff0bde8029040b3f867be6ca46bf0901 100644 (file)
@@ -443,7 +443,7 @@ try_again:
                        ip_cmsg_recv(msg, skb);
        } else {
                if (np->rxopt.all)
-                       datagram_recv_ctl(sk, msg, skb);
+                       ip6_datagram_recv_ctl(sk, msg, skb);
        }
 
        err = copied;
@@ -1153,8 +1153,8 @@ do_udp_sendmsg:
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(*opt);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
index 3ad1f9db5f8b697167c8ed1ed249567f36ccf008..df082508362d892e623a80b57c732504e0b78581 100644 (file)
@@ -1806,7 +1806,7 @@ static void iucv_external_interrupt(struct ext_code ext_code,
        struct iucv_irq_data *p;
        struct iucv_irq_list *work;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_IUC]++;
+       inc_irq_stat(IRQEXT_IUC);
        p = iucv_irq_data[smp_processor_id()];
        if (p->ippathid >= iucv_max_pathid) {
                WARN_ON(p->ippathid >= iucv_max_pathid);
index 1a9f3723c13cb45b608bbc07fe4a9803df926523..2ac884d0e89bd06ff820073351004509b0838902 100644 (file)
@@ -168,6 +168,51 @@ l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
 
 }
 
+/* Lookup the tunnel socket, possibly involving the fs code if the socket is
+ * owned by userspace.  A struct sock returned from this function must be
+ * released using l2tp_tunnel_sock_put once you're done with it.
+ */
+struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
+{
+       int err = 0;
+       struct socket *sock = NULL;
+       struct sock *sk = NULL;
+
+       if (!tunnel)
+               goto out;
+
+       if (tunnel->fd >= 0) {
+               /* Socket is owned by userspace, who might be in the process
+                * of closing it.  Look the socket up using the fd to ensure
+                * consistency.
+                */
+               sock = sockfd_lookup(tunnel->fd, &err);
+               if (sock)
+                       sk = sock->sk;
+       } else {
+               /* Socket is owned by kernelspace */
+               sk = tunnel->sock;
+       }
+
+out:
+       return sk;
+}
+EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_lookup);
+
+/* Drop a reference to a tunnel socket obtained via. l2tp_tunnel_sock_put */
+void l2tp_tunnel_sock_put(struct sock *sk)
+{
+       struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
+       if (tunnel) {
+               if (tunnel->fd >= 0) {
+                       /* Socket is owned by userspace */
+                       sockfd_put(sk->sk_socket);
+               }
+               sock_put(sk);
+       }
+}
+EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put);
+
 /* Lookup a session by id in the global session list
  */
 static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id)
@@ -1123,8 +1168,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
        struct udphdr *uh;
        struct inet_sock *inet;
        __wsum csum;
-       int old_headroom;
-       int new_headroom;
        int headroom;
        int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
        int udp_len;
@@ -1136,16 +1179,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
         */
        headroom = NET_SKB_PAD + sizeof(struct iphdr) +
                uhlen + hdr_len;
-       old_headroom = skb_headroom(skb);
        if (skb_cow_head(skb, headroom)) {
                kfree_skb(skb);
                return NET_XMIT_DROP;
        }
 
-       new_headroom = skb_headroom(skb);
        skb_orphan(skb);
-       skb->truesize += new_headroom - old_headroom;
-
        /* Setup L2TP header */
        session->build_header(session, __skb_push(skb, hdr_len));
 
@@ -1607,6 +1646,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
        tunnel->sock = sk;
+       tunnel->fd = fd;
        lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
 
        sk->sk_allocation = GFP_ATOMIC;
@@ -1642,24 +1682,32 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
  */
 int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
-       int err = 0;
-       struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL;
+       int err = -EBADF;
+       struct socket *sock = NULL;
+       struct sock *sk = NULL;
+
+       sk = l2tp_tunnel_sock_lookup(tunnel);
+       if (!sk)
+               goto out;
+
+       sock = sk->sk_socket;
+       BUG_ON(!sock);
 
        /* Force the tunnel socket to close. This will eventually
         * cause the tunnel to be deleted via the normal socket close
         * mechanisms when userspace closes the tunnel socket.
         */
-       if (sock != NULL) {
-               err = inet_shutdown(sock, 2);
+       err = inet_shutdown(sock, 2);
 
-               /* If the tunnel's socket was created by the kernel,
-                * close the socket here since the socket was not
-                * created by userspace.
-                */
-               if (sock->file == NULL)
-                       err = inet_release(sock);
-       }
+       /* If the tunnel's socket was created by the kernel,
+        * close the socket here since the socket was not
+        * created by userspace.
+        */
+       if (sock->file == NULL)
+               err = inet_release(sock);
 
+       l2tp_tunnel_sock_put(sk);
+out:
        return err;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
index 56d583e083a7baf7b0cf707a76882a88701d8025..e62204cad4fe00c91e88f791c7c7896c130249fa 100644 (file)
@@ -188,7 +188,8 @@ struct l2tp_tunnel {
        int (*recv_payload_hook)(struct sk_buff *skb);
        void (*old_sk_destruct)(struct sock *);
        struct sock             *sock;          /* Parent socket */
-       int                     fd;
+       int                     fd;             /* Parent fd, if tunnel socket
+                                                * was created by userspace */
 
        uint8_t                 priv[0];        /* private data */
 };
@@ -228,6 +229,8 @@ out:
        return tunnel;
 }
 
+extern struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel);
+extern void l2tp_tunnel_sock_put(struct sock *sk);
 extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id);
 extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
 extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
index 927547171bc7119f57a7b8afecf453ec5eeabf61..8ee4a86ae996ca624e06a1422e4e07a2e957c584 100644 (file)
@@ -554,8 +554,8 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -646,7 +646,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                            struct msghdr *msg, size_t len, int noblock,
                            int flags, int *addr_len)
 {
-       struct inet_sock *inet = inet_sk(sk);
+       struct ipv6_pinfo *np = inet6_sk(sk);
        struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)msg->msg_name;
        size_t copied = 0;
        int err = -EOPNOTSUPP;
@@ -688,8 +688,8 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                        lsa->l2tp_scope_id = IP6CB(skb)->iif;
        }
 
-       if (inet->cmsg_flags)
-               ip_cmsg_recv(msg, skb);
+       if (np->rxopt.all)
+               ip6_datagram_recv_ctl(sk, msg, skb);
 
        if (flags & MSG_TRUNC)
                copied = skb->len;
index 286366ef8930a08981f04952d4459f2b9a413071..716605c241f482e4793e86bdb1dc61d1c3596602 100644 (file)
@@ -388,8 +388,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        struct l2tp_session *session;
        struct l2tp_tunnel *tunnel;
        struct pppol2tp_session *ps;
-       int old_headroom;
-       int new_headroom;
        int uhlen, headroom;
 
        if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
@@ -408,7 +406,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        if (tunnel == NULL)
                goto abort_put_sess;
 
-       old_headroom = skb_headroom(skb);
        uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
        headroom = NET_SKB_PAD +
                   sizeof(struct iphdr) + /* IP header */
@@ -418,9 +415,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        if (skb_cow_head(skb, headroom))
                goto abort_put_sess_tun;
 
-       new_headroom = skb_headroom(skb);
-       skb->truesize += new_headroom - old_headroom;
-
        /* Setup PPP header */
        __skb_push(skb, sizeof(ppph));
        skb->data[0] = ppph[0];
index 5c61677487cf831324994e24e22528d15f35aa3a..0479c64aa83cc8beb27a90dedd1340cbeb2065a2 100644 (file)
@@ -164,7 +164,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                        sta = sta_info_get(sdata, mac_addr);
                else
                        sta = sta_info_get_bss(sdata, mac_addr);
-               if (!sta) {
+               /*
+                * The ASSOC test makes sure the driver is ready to
+                * receive the key. When wpa_supplicant has roamed
+                * using FT, it attempts to set the key before
+                * association has completed, this rejects that attempt
+                * so it will set the key again after assocation.
+                *
+                * TODO: accept the key if we have a station entry and
+                *       add it to the device after the station.
+                */
+               if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
                        ieee80211_key_free(sdata->local, key);
                        err = -ENOENT;
                        goto out_unlock;
@@ -1009,6 +1019,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        if (old_probe_resp)
                kfree_rcu(old_probe_resp, rcu_head);
 
+       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+               sta_info_flush(local, vlan);
        sta_info_flush(local, sdata);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 
@@ -1992,7 +2004,8 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       memcpy(sdata->vif.bss_conf.mcast_rate, rate, sizeof(rate));
+       memcpy(sdata->vif.bss_conf.mcast_rate, rate,
+              sizeof(int) * IEEE80211_NUM_BANDS);
 
        return 0;
 }
index 53f03120db55dc3d2c1e8c775a054182d21dac69..80e55527504b91cd71b6d33a946507ad10b59c7e 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/export.h>
+#include <linux/rtnetlink.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
 #include "driver-ops.h"
@@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 
        ctx = container_of(conf, struct ieee80211_chanctx, conf);
 
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               struct ieee80211_sub_if_data *vlan;
+
+               /* for the VLAN list */
+               ASSERT_RTNL();
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       rcu_assign_pointer(vlan->vif.chanctx_conf, NULL);
+       }
+
        ieee80211_unassign_vif_chanctx(sdata, ctx);
        if (ctx->refcount == 0)
                ieee80211_free_chanctx(local, ctx);
@@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
                goto out;
        }
 
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               struct ieee80211_sub_if_data *vlan;
+
+               /* for the VLAN list */
+               ASSERT_RTNL();
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf);
+       }
+
        ieee80211_recalc_smps_chanctx(local, ctx);
  out:
        mutex_unlock(&local->chanctx_mtx);
@@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&sdata->local->chanctx_mtx);
 }
 
+void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *ap;
+       struct ieee80211_chanctx_conf *conf;
+
+       if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
+               return;
+
+       ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
+
+       mutex_lock(&local->chanctx_mtx);
+
+       conf = rcu_dereference_protected(ap->vif.chanctx_conf,
+                                        lockdep_is_held(&local->chanctx_mtx));
+       rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
+       mutex_unlock(&local->chanctx_mtx);
+}
+
 void ieee80211_iter_chan_contexts_atomic(
        struct ieee80211_hw *hw,
        void (*iter)(struct ieee80211_hw *hw,
index 8881fc77fb1324c50d79ca6dcc2dd5423d7a18c9..6b7644e818d8f30629513318d4f9a17e4e622606 100644 (file)
@@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
        sdata_info(sdata,
                   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
 
-       ieee80211_request_internal_scan(sdata,
-                       ifibss->ssid, ifibss->ssid_len, NULL);
+       ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
+                                   NULL);
 }
 
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -802,9 +802,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                                        IEEE80211_SCAN_INTERVAL)) {
                sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
 
-               ieee80211_request_internal_scan(sdata,
-                               ifibss->ssid, ifibss->ssid_len,
-                               ifibss->fixed_channel ? ifibss->channel : NULL);
+               ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+                                           ifibss->ssid_len, chan);
        } else {
                int interval = IEEE80211_SCAN_INTERVAL;
 
index 42d0d026773090633aec6cecf21d5c6065a4b69d..2ed065c095629403c42574872fec6a8b85819871 100644 (file)
@@ -92,8 +92,6 @@ struct ieee80211_bss {
 
        u32 device_ts;
 
-       u8 dtim_period;
-
        bool wmm_used;
        bool uapsd_supported;
 
@@ -140,7 +138,6 @@ enum ieee80211_bss_corrupt_data_flags {
 
 /**
  * enum ieee80211_valid_data_flags - BSS valid data flags
- * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
@@ -151,7 +148,6 @@ enum ieee80211_bss_corrupt_data_flags {
  * beacon/probe response.
  */
 enum ieee80211_bss_valid_data_flags {
-       IEEE80211_BSS_VALID_DTIM                = BIT(0),
        IEEE80211_BSS_VALID_WMM                 = BIT(1),
        IEEE80211_BSS_VALID_RATES               = BIT(2),
        IEEE80211_BSS_VALID_ERP                 = BIT(3)
@@ -440,6 +436,7 @@ struct ieee80211_if_managed {
        unsigned long timers_running; /* used for quiesce/restart */
        bool powersave; /* powersave requested for this iface */
        bool broken_ap; /* AP is broken -- turn off powersave */
+       u8 dtim_period;
        enum ieee80211_smps_mode req_smps, /* requested smps mode */
                                 driver_smps_mode; /* smps mode request */
 
@@ -773,6 +770,10 @@ struct ieee80211_sub_if_data {
                u32 mntr_flags;
        } u;
 
+       spinlock_t cleanup_stations_lock;
+       struct list_head cleanup_stations;
+       struct work_struct cleanup_stations_wk;
+
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct {
                struct dentry *dir;
@@ -1329,9 +1330,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
 /* scan/BSS handling */
 void ieee80211_scan_work(struct work_struct *work);
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-                                   const u8 *ssid, u8 ssid_len,
-                                   struct ieee80211_channel *chan);
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
+                               const u8 *ssid, u8 ssid_len,
+                               struct ieee80211_channel *chan);
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
                           struct cfg80211_scan_request *req);
 void ieee80211_scan_cancel(struct ieee80211_local *local);
@@ -1357,10 +1358,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sched_scan_stopped_work(struct work_struct *work);
 
 /* off-channel helpers */
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
-                                   bool offchannel_ps_enable);
-void ieee80211_offchannel_return(struct ieee80211_local *local,
-                                bool offchannel_ps_disable);
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
+void ieee80211_offchannel_return(struct ieee80211_local *local);
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
@@ -1628,6 +1627,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
                          const struct cfg80211_chan_def *chandef,
                          enum ieee80211_chanctx_mode mode);
 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
+void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
 
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx);
index 09a80b55cf5a1ffaf06fdbe892ac469f6790b2bf..8be854e86cd987d61e01cc7eabc8f7ddb068eff3 100644 (file)
@@ -207,17 +207,8 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
 
 static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
 {
-       int meshhdrlen;
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-       meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;
-
-       /* FIX: what would be proper limits for MTU?
-        * This interface uses 802.3 frames. */
-       if (new_mtu < 256 ||
-           new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
+       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
                return -EINVAL;
-       }
 
        dev->mtu = new_mtu;
        return 0;
@@ -586,11 +577,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP_VLAN:
-               /* no need to tell driver, but set carrier */
-               if (rtnl_dereference(sdata->bss->beacon))
+               /* no need to tell driver, but set carrier and chanctx */
+               if (rtnl_dereference(sdata->bss->beacon)) {
+                       ieee80211_vif_vlan_copy_chanctx(sdata);
                        netif_carrier_on(dev);
-               else
+               } else {
                        netif_carrier_off(dev);
+               }
                break;
        case NL80211_IFTYPE_MONITOR:
                if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
@@ -839,6 +832,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP_VLAN:
                list_del(&sdata->u.vlan.list);
+               rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
                /* no need to tell driver */
                break;
        case NL80211_IFTYPE_MONITOR:
@@ -865,20 +859,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                cancel_work_sync(&sdata->work);
                /*
                 * When we get here, the interface is marked down.
-                * Call rcu_barrier() to wait both for the RX path
+                * Call synchronize_rcu() to wait for the RX path
                 * should it be using the interface and enqueuing
-                * frames at this very time on another CPU, and
-                * for the sta free call_rcu callbacks.
-                */
-               rcu_barrier();
-
-               /*
-                * free_sta_rcu() enqueues a work for the actual
-                * sta cleanup, so we need to flush it while
-                * sdata is still valid.
+                * frames at this very time on another CPU.
                 */
-               flush_workqueue(local->workqueue);
-
+               synchronize_rcu();
                skb_queue_purge(&sdata->skb_queue);
 
                /*
@@ -1498,6 +1483,15 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
        mutex_unlock(&local->iflist_mtx);
 }
 
+static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
+
+       ieee80211_cleanup_sdata_stas(sdata);
+}
+
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                     struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params)
@@ -1573,6 +1567,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        INIT_LIST_HEAD(&sdata->key_list);
 
+       spin_lock_init(&sdata->cleanup_stations_lock);
+       INIT_LIST_HEAD(&sdata->cleanup_stations);
+       INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
+
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
                struct ieee80211_supported_band *sband;
                sband = local->hw.wiphy->bands[i];
index 1bf03f9ff3ba74394fb26201dfba3b3fd2e86a01..649ad513547f99728d43dbeeabcd2b58d7862c30 100644 (file)
@@ -163,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
                return -ENOMEM;
        sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
        for (i = 0; i < RMC_BUCKETS; i++)
-               INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
+               INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
        return 0;
 }
 
@@ -177,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
                return;
 
        for (i = 0; i < RMC_BUCKETS; i++)
-               list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
+               list_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
                        list_del(&p->list);
                        kmem_cache_free(rm_cache, p);
                }
@@ -210,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
        /* Don't care about endianness since only match matters */
        memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
        idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
-       list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
+       list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
                ++entries;
                if (time_after(jiffies, p->exp_time) ||
                                (entries == RMC_QUEUE_MAX_LEN)) {
@@ -229,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
        p->seqnum = seqnum;
        p->exp_time = jiffies + RMC_TIMEOUT;
        memcpy(p->sa, sa, ETH_ALEN);
-       list_add(&p->list, &rmc->bucket[idx].list);
+       list_add(&p->list, &rmc->bucket[idx]);
        return 0;
 }
 
index 7c9215fb2ac84ec5c17d3ee3d372a7a6bb4feedc..84c28c6101cdd2ef832920677d05b7f02b27ada2 100644 (file)
@@ -184,7 +184,7 @@ struct rmc_entry {
 };
 
 struct mesh_rmc {
-       struct rmc_entry bucket[RMC_BUCKETS];
+       struct list_head bucket[RMC_BUCKETS];
        u32 idx_mask;
 };
 
index 47aeee2d8db160f6fa9eb62c32131bbd686acc29..2659e428b80c86cf367a75b034c8d89a856f28a1 100644 (file)
@@ -215,6 +215,7 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
        skb->priority = 7;
 
        info->control.vif = &sdata->vif;
+       info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
        ieee80211_set_qos_hdr(sdata, skb);
 }
 
@@ -246,11 +247,13 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
                return -EAGAIN;
 
        skb = dev_alloc_skb(local->tx_headroom +
+                           IEEE80211_ENCRYPT_HEADROOM +
+                           IEEE80211_ENCRYPT_TAILROOM +
                            hdr_len +
                            2 + 15 /* PERR IE */);
        if (!skb)
                return -1;
-       skb_reserve(skb, local->tx_headroom);
+       skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
        memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
index 7753a9ca98a6c67870f68bd40b22f3af453a3945..5107248af7fbd87fae600240c48e570c591abc5f 100644 (file)
@@ -1074,12 +1074,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
                if (beaconint_us > latency) {
                        local->ps_sdata = NULL;
                } else {
-                       struct ieee80211_bss *bss;
                        int maxslp = 1;
-                       u8 dtimper;
-
-                       bss = (void *)found->u.mgd.associated->priv;
-                       dtimper = bss->dtim_period;
+                       u8 dtimper = found->u.mgd.dtim_period;
 
                        /* If the TIM IE is invalid, pretend the value is 1 */
                        if (!dtimper)
@@ -1410,10 +1406,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_led_assoc(local, 1);
 
-       if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
-               bss_conf->dtim_period = bss->dtim_period;
-       else
+       if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
+               /*
+                * If the AP is buggy we may get here with no DTIM period
+                * known, so assume it's 1 which is the only safe assumption
+                * in that case, although if the TIM IE is broken powersave
+                * probably just won't work at all.
+                */
+               bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
+       } else {
                bss_conf->dtim_period = 0;
+       }
 
        bss_conf->assoc = 1;
 
@@ -1562,6 +1565,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        sdata->u.mgd.timers_running = 0;
 
+       sdata->vif.bss_conf.dtim_period = 0;
+
        ifmgd->flags = 0;
        ieee80211_vif_release_channel(sdata);
 }
@@ -2373,11 +2378,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_channel *channel;
        bool need_ps = false;
 
-       if (sdata->u.mgd.associated &&
-           ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) {
-               bss = (void *)sdata->u.mgd.associated->priv;
+       if ((sdata->u.mgd.associated &&
+            ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
+           (sdata->u.mgd.assoc_data &&
+            ether_addr_equal(mgmt->bssid,
+                             sdata->u.mgd.assoc_data->bss->bssid))) {
                /* not previously set so we may need to recalc */
-               need_ps = !bss->dtim_period;
+               need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period;
+
+               if (elems->tim && !elems->parse_error) {
+                       struct ieee80211_tim_ie *tim_ie = elems->tim;
+                       sdata->u.mgd.dtim_period = tim_ie->dtim_period;
+               }
        }
 
        if (elems->ds_params && elems->ds_params_len == 1)
@@ -3388,6 +3400,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 
        ret = 0;
 
+out:
        while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
                                        IEEE80211_CHAN_DISABLED)) {
                if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
@@ -3396,14 +3409,13 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                        goto out;
                }
 
-               ret = chandef_downgrade(chandef);
+               ret |= chandef_downgrade(chandef);
        }
 
        if (chandef->width != vht_chandef.width)
                sdata_info(sdata,
-                          "local regulatory prevented using AP HT/VHT configuration, downgraded\n");
+                          "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
 
-out:
        WARN_ON_ONCE(!cfg80211_chandef_valid(chandef));
        return ret;
 }
@@ -3517,8 +3529,11 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
         */
        ret = ieee80211_vif_use_channel(sdata, &chandef,
                                        IEEE80211_CHANCTX_SHARED);
-       while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
+       while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
                ifmgd->flags |= chandef_downgrade(&chandef);
+               ret = ieee80211_vif_use_channel(sdata, &chandef,
+                                               IEEE80211_CHANCTX_SHARED);
+       }
        return ret;
 }
 
@@ -3896,20 +3911,41 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        /* kick off associate process */
 
        ifmgd->assoc_data = assoc_data;
+       ifmgd->dtim_period = 0;
 
        err = ieee80211_prep_connection(sdata, req->bss, true);
        if (err)
                goto err_clear;
 
-       if (!bss->dtim_period &&
-           sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
-               /*
-                * Wait up to one beacon interval ...
-                * should this be more if we miss one?
-                */
-               sdata_info(sdata, "waiting for beacon from %pM\n",
-                          ifmgd->bssid);
-               assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
+       if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
+               const struct cfg80211_bss_ies *beacon_ies;
+
+               rcu_read_lock();
+               beacon_ies = rcu_dereference(req->bss->beacon_ies);
+               if (!beacon_ies) {
+                       /*
+                        * Wait up to one beacon interval ...
+                        * should this be more if we miss one?
+                        */
+                       sdata_info(sdata, "waiting for beacon from %pM\n",
+                                  ifmgd->bssid);
+                       assoc_data->timeout =
+                               TU_TO_EXP_TIME(req->bss->beacon_interval);
+               } else {
+                       const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
+                                                           beacon_ies->data,
+                                                           beacon_ies->len);
+                       if (tim_ie && tim_ie[1] >=
+                                       sizeof(struct ieee80211_tim_ie)) {
+                               const struct ieee80211_tim_ie *tim;
+                               tim = (void *)(tim_ie + 2);
+                               ifmgd->dtim_period = tim->dtim_period;
+                       }
+                       assoc_data->have_beacon = true;
+                       assoc_data->sent_assoc = false;
+                       assoc_data->timeout = jiffies;
+               }
+               rcu_read_unlock();
        } else {
                assoc_data->have_beacon = true;
                assoc_data->sent_assoc = false;
index a5379aea7d09d2410c70a3b467a1f336aa32dc43..a3ad4c3c80a34229801bdbdd1124201485a2f671 100644 (file)
@@ -102,8 +102,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
        ieee80211_sta_reset_conn_monitor(sdata);
 }
 
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
-                                   bool offchannel_ps_enable)
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
 
@@ -134,8 +133,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
 
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
                        netif_tx_stop_all_queues(sdata->dev);
-                       if (offchannel_ps_enable &&
-                           (sdata->vif.type == NL80211_IFTYPE_STATION) &&
+                       if (sdata->vif.type == NL80211_IFTYPE_STATION &&
                            sdata->u.mgd.associated)
                                ieee80211_offchannel_ps_enable(sdata);
                }
@@ -143,8 +141,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
        mutex_unlock(&local->iflist_mtx);
 }
 
-void ieee80211_offchannel_return(struct ieee80211_local *local,
-                                bool offchannel_ps_disable)
+void ieee80211_offchannel_return(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
 
@@ -163,11 +160,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
                        continue;
 
                /* Tell AP we're back */
-               if (offchannel_ps_disable &&
-                   sdata->vif.type == NL80211_IFTYPE_STATION) {
-                       if (sdata->u.mgd.associated)
-                               ieee80211_offchannel_ps_disable(sdata);
-               }
+               if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+                   sdata->u.mgd.associated)
+                       ieee80211_offchannel_ps_disable(sdata);
 
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
                        /*
@@ -385,7 +380,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
                        local->tmp_channel = NULL;
                        ieee80211_hw_config(local, 0);
 
-                       ieee80211_offchannel_return(local, true);
+                       ieee80211_offchannel_return(local);
                }
 
                ieee80211_recalc_idle(local);
index 8ed83dcc149fc7f38ca9beaf83a2c67a82c336ec..bf82e69d0601bf9210e817837b2af7725a9f7d87 100644 (file)
@@ -113,18 +113,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
                        bss->valid_data |= IEEE80211_BSS_VALID_ERP;
        }
 
-       if (elems->tim && (!elems->parse_error ||
-                          !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
-               struct ieee80211_tim_ie *tim_ie = elems->tim;
-               bss->dtim_period = tim_ie->dtim_period;
-               if (!elems->parse_error)
-                       bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
-       }
-
-       /* If the beacon had no TIM IE, or it was invalid, use 1 */
-       if (beacon && !bss->dtim_period)
-               bss->dtim_period = 1;
-
        /* replace old supported rates if we get new values */
        if (!elems->parse_error ||
            !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
@@ -304,7 +292,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        if (!was_hw_scan) {
                ieee80211_configure_filter(local);
                drv_sw_scan_complete(local);
-               ieee80211_offchannel_return(local, true);
+               ieee80211_offchannel_return(local);
        }
 
        ieee80211_recalc_idle(local);
@@ -353,7 +341,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
        local->next_scan_state = SCAN_DECISION;
        local->scan_channel_idx = 0;
 
-       ieee80211_offchannel_stop_vifs(local, true);
+       ieee80211_offchannel_stop_vifs(local);
 
        ieee80211_configure_filter(local);
 
@@ -690,12 +678,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
        local->scan_channel = NULL;
        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
-       /*
-        * Re-enable vifs and beaconing.  Leave PS
-        * in off-channel state..will put that back
-        * on-channel at the end of scanning.
-        */
-       ieee80211_offchannel_return(local, false);
+       /* disable PS */
+       ieee80211_offchannel_return(local);
 
        *next_delay = HZ / 5;
        /* afterwards, resume scan & go to next channel */
@@ -705,8 +689,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
 static void ieee80211_scan_state_resume(struct ieee80211_local *local,
                                        unsigned long *next_delay)
 {
-       /* PS already is in off-channel mode */
-       ieee80211_offchannel_stop_vifs(local, false);
+       ieee80211_offchannel_stop_vifs(local);
 
        if (local->ops->flush) {
                drv_flush(local, false);
@@ -832,9 +815,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
        return res;
 }
 
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-                                   const u8 *ssid, u8 ssid_len,
-                                   struct ieee80211_channel *chan)
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
+                               const u8 *ssid, u8 ssid_len,
+                               struct ieee80211_channel *chan)
 {
        struct ieee80211_local *local = sdata->local;
        int ret = -EBUSY;
@@ -848,22 +831,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
 
        /* fill internal scan request */
        if (!chan) {
-               int i, nchan = 0;
+               int i, max_n;
+               int n_ch = 0;
 
                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                        if (!local->hw.wiphy->bands[band])
                                continue;
-                       for (i = 0;
-                            i < local->hw.wiphy->bands[band]->n_channels;
-                            i++) {
-                               local->int_scan_req->channels[nchan] =
+
+                       max_n = local->hw.wiphy->bands[band]->n_channels;
+                       for (i = 0; i < max_n; i++) {
+                               struct ieee80211_channel *tmp_ch =
                                    &local->hw.wiphy->bands[band]->channels[i];
-                               nchan++;
+
+                               if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
+                                                    IEEE80211_CHAN_DISABLED))
+                                       continue;
+
+                               local->int_scan_req->channels[n_ch] = tmp_ch;
+                               n_ch++;
                        }
                }
 
-               local->int_scan_req->n_channels = nchan;
+               if (WARN_ON_ONCE(n_ch == 0))
+                       goto unlock;
+
+               local->int_scan_req->n_channels = n_ch;
        } else {
+               if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
+                                               IEEE80211_CHAN_DISABLED)))
+                       goto unlock;
+
                local->int_scan_req->channels[0] = chan;
                local->int_scan_req->n_channels = 1;
        }
index f3e502502fee27374dc4c183733cbcc95217aed5..ca9fde1981889a559efa6b49385f071f1475a06f 100644 (file)
@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee80211_local *local,
        return -ENOENT;
 }
 
-static void free_sta_work(struct work_struct *wk)
+static void cleanup_single_sta(struct sta_info *sta)
 {
-       struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk);
        int ac, i;
        struct tid_ampdu_tx *tid_tx;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -153,11 +152,35 @@ static void free_sta_work(struct work_struct *wk)
        sta_info_free(local, sta);
 }
 
+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata)
+{
+       struct sta_info *sta;
+
+       spin_lock_bh(&sdata->cleanup_stations_lock);
+       while (!list_empty(&sdata->cleanup_stations)) {
+               sta = list_first_entry(&sdata->cleanup_stations,
+                                      struct sta_info, list);
+               list_del(&sta->list);
+               spin_unlock_bh(&sdata->cleanup_stations_lock);
+
+               cleanup_single_sta(sta);
+
+               spin_lock_bh(&sdata->cleanup_stations_lock);
+       }
+
+       spin_unlock_bh(&sdata->cleanup_stations_lock);
+}
+
 static void free_sta_rcu(struct rcu_head *h)
 {
        struct sta_info *sta = container_of(h, struct sta_info, rcu_head);
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
 
-       ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk);
+       spin_lock(&sdata->cleanup_stations_lock);
+       list_add_tail(&sta->list, &sdata->cleanup_stations);
+       spin_unlock(&sdata->cleanup_stations_lock);
+
+       ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk);
 }
 
 /* protected by RCU */
@@ -310,7 +333,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 
        spin_lock_init(&sta->lock);
        INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
-       INIT_WORK(&sta->free_sta_wk, free_sta_work);
        INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
        mutex_init(&sta->ampdu_mlme.mtx);
 
@@ -862,7 +884,7 @@ void sta_info_init(struct ieee80211_local *local)
 
 void sta_info_stop(struct ieee80211_local *local)
 {
-       del_timer(&local->sta_cleanup);
+       del_timer_sync(&local->sta_cleanup);
        sta_info_flush(local, NULL);
 }
 
@@ -891,6 +913,20 @@ int sta_info_flush(struct ieee80211_local *local,
        }
        mutex_unlock(&local->sta_mtx);
 
+       rcu_barrier();
+
+       if (sdata) {
+               ieee80211_cleanup_sdata_stas(sdata);
+               cancel_work_sync(&sdata->cleanup_stations_wk);
+       } else {
+               mutex_lock(&local->iflist_mtx);
+               list_for_each_entry(sdata, &local->interfaces, list) {
+                       ieee80211_cleanup_sdata_stas(sdata);
+                       cancel_work_sync(&sdata->cleanup_stations_wk);
+               }
+               mutex_unlock(&local->iflist_mtx);
+       }
+
        return ret;
 }
 
index 1489bca9ea97c19ee525ea44c0d1af794ec94cca..37c1889afd3ae02f9d9d5f2573738a28d26c266e 100644 (file)
@@ -299,7 +299,6 @@ struct sta_info {
        spinlock_t lock;
 
        struct work_struct drv_unblock_wk;
-       struct work_struct free_sta_wk;
 
        u16 listen_interval;
 
@@ -563,4 +562,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
+
 #endif /* STA_INFO_H */
index e9eadc40c09cc20bce9ad37531ef45ae767f62e8..467c1d1b66f2f5615182abd689349027b88abe64 100644 (file)
@@ -1673,10 +1673,13 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                        chanctx_conf =
                                rcu_dereference(tmp_sdata->vif.chanctx_conf);
        }
-       if (!chanctx_conf)
-               goto fail_rcu;
 
-       chan = chanctx_conf->def.chan;
+       if (chanctx_conf)
+               chan = chanctx_conf->def.chan;
+       else if (!local->use_chanctx)
+               chan = local->_oper_channel;
+       else
+               goto fail_rcu;
 
        /*
         * Frame injection is not allowed if beaconing is not allowed
index 1191039c2b1bc38bda25402dd395d7e3b1bbe7b4..199b92261e94281b7f774d30ba254d0468d204bc 100644 (file)
@@ -389,7 +389,7 @@ void mac802154_wpan_setup(struct net_device *dev)
 
 static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
 {
-       return netif_rx(skb);
+       return netif_rx_ni(skb);
 }
 
 static int
index fefa514b99170aae55620e4007565b0ad3e814b4..49e96df5fbc4b38e842540f65c5b23309440c597 100644 (file)
@@ -680,6 +680,13 @@ config NETFILTER_XT_TARGET_NFQUEUE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_NOTRACK
+       tristate  '"NOTRACK" target support (DEPRECATED)'
+       depends on NF_CONNTRACK
+       depends on IP_NF_RAW || IP6_NF_RAW
+       depends on NETFILTER_ADVANCED
+       select NETFILTER_XT_TARGET_CT
+
 config NETFILTER_XT_TARGET_RATEEST
        tristate '"RATEEST" target support'
        depends on NETFILTER_ADVANCED
index 746048b13ef3aff9659b7161199d2298960662ec..ae8ec6f2768888eec1fb8b8c68b4242eff033525 100644 (file)
@@ -61,14 +61,27 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
        return 1;
 }
 
+static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph,
+                         unsigned int sctphoff)
+{
+       __u32 crc32;
+       struct sk_buff *iter;
+
+       crc32 = sctp_start_cksum((__u8 *)sctph, skb_headlen(skb) - sctphoff);
+       skb_walk_frags(skb, iter)
+               crc32 = sctp_update_cksum((u8 *) iter->data,
+                                         skb_headlen(iter), crc32);
+       sctph->checksum = sctp_end_cksum(crc32);
+
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int
 sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
                  struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        sctp_sctphdr_t *sctph;
        unsigned int sctphoff = iph->len;
-       struct sk_buff *iter;
-       __be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
        if (cp->af == AF_INET6 && iph->fragoffs)
@@ -92,13 +105,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
        sctph = (void *) skb_network_header(skb) + sctphoff;
        sctph->source = cp->vport;
 
-       /* Calculate the checksum */
-       crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
-       skb_walk_frags(skb, iter)
-               crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter),
-                                         crc32);
-       crc32 = sctp_end_cksum(crc32);
-       sctph->checksum = crc32;
+       sctp_nat_csum(skb, sctph, sctphoff);
 
        return 1;
 }
@@ -109,8 +116,6 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
 {
        sctp_sctphdr_t *sctph;
        unsigned int sctphoff = iph->len;
-       struct sk_buff *iter;
-       __be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
        if (cp->af == AF_INET6 && iph->fragoffs)
@@ -134,13 +139,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
        sctph = (void *) skb_network_header(skb) + sctphoff;
        sctph->dest = cp->dport;
 
-       /* Calculate the checksum */
-       crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
-       skb_walk_frags(skb, iter)
-               crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter),
-                                         crc32);
-       crc32 = sctp_end_cksum(crc32);
-       sctph->checksum = crc32;
+       sctp_nat_csum(skb, sctph, sctphoff);
 
        return 1;
 }
index effa10c9e4e325bc3d5538f2d94988c191d7ba56..44fd10c539ac42dfaa967974051bdfacb17099fb 100644 (file)
@@ -1795,6 +1795,8 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid)
                                             GFP_KERNEL);
                        if (!tinfo->buf)
                                goto outtinfo;
+               } else {
+                       tinfo->buf = NULL;
                }
                tinfo->id = id;
 
index 08cdc71d8e8714b75782379929fa6b050dafa7f4..e4a0c4fb3a7cef64d1f15c9173d5a3e62ad616b4 100644 (file)
@@ -1376,11 +1376,12 @@ void nf_conntrack_cleanup(struct net *net)
        synchronize_net();
        nf_conntrack_proto_fini(net);
        nf_conntrack_cleanup_net(net);
+}
 
-       if (net_eq(net, &init_net)) {
-               RCU_INIT_POINTER(nf_ct_destroy, NULL);
-               nf_conntrack_cleanup_init_net();
-       }
+void nf_conntrack_cleanup_end(void)
+{
+       RCU_INIT_POINTER(nf_ct_destroy, NULL);
+       nf_conntrack_cleanup_init_net();
 }
 
 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
@@ -1526,6 +1527,7 @@ err_extend:
  */
 #define UNCONFIRMED_NULLS_VAL  ((1<<30)+0)
 #define DYING_NULLS_VAL                ((1<<30)+1)
+#define TEMPLATE_NULLS_VAL     ((1<<30)+2)
 
 static int nf_conntrack_init_net(struct net *net)
 {
@@ -1534,6 +1536,7 @@ static int nf_conntrack_init_net(struct net *net)
        atomic_set(&net->ct.count, 0);
        INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL);
        INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL);
+       INIT_HLIST_NULLS_HEAD(&net->ct.tmpl, TEMPLATE_NULLS_VAL);
        net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
        if (!net->ct.stat) {
                ret = -ENOMEM;
index 4e078cd84d83c2c15c70ab4270b87a05e590f4ad..627b0e50b2389120e86ed107a3af01d690e07a29 100644 (file)
@@ -2624,7 +2624,7 @@ ctnetlink_create_expect(struct net *net, u16 zone,
        if (!help) {
                if (!cda[CTA_EXPECT_TIMEOUT]) {
                        err = -EINVAL;
-                       goto out;
+                       goto err_out;
                }
                exp->timeout.expires =
                  jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
index 363285d544a1c7402152e6a7da3a7129d94b83ae..e7185c68481659445b571ab5e7866728dd3947ec 100644 (file)
@@ -575,6 +575,7 @@ static int __init nf_conntrack_standalone_init(void)
 static void __exit nf_conntrack_standalone_fini(void)
 {
        unregister_pernet_subsys(&nf_conntrack_net_ops);
+       nf_conntrack_cleanup_end();
 }
 
 module_init(nf_conntrack_standalone_init);
index 9f199f2e31fae16ff667e7a1f230e6826d015794..92fd8eca0d315ff241b066e3fab3c6f9fcdaa1bb 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
@@ -384,6 +385,7 @@ __build_packet_message(struct nfulnl_instance *inst,
        struct nfgenmsg *nfmsg;
        sk_buff_data_t old_tail = inst->skb->tail;
        struct sock *sk;
+       const unsigned char *hwhdrp;
 
        nlh = nlmsg_put(inst->skb, 0, 0,
                        NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
@@ -485,9 +487,17 @@ __build_packet_message(struct nfulnl_instance *inst,
        if (indev && skb_mac_header_was_set(skb)) {
                if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
                    nla_put_be16(inst->skb, NFULA_HWLEN,
-                                htons(skb->dev->hard_header_len)) ||
-                   nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
-                           skb_mac_header(skb)))
+                                htons(skb->dev->hard_header_len)))
+                       goto nla_put_failure;
+
+               hwhdrp = skb_mac_header(skb);
+
+               if (skb->dev->type == ARPHRD_SIT)
+                       hwhdrp -= ETH_HLEN;
+
+               if (hwhdrp >= skb->head &&
+                   nla_put(inst->skb, NFULA_HWHEADER,
+                           skb->dev->hard_header_len, hwhdrp))
                        goto nla_put_failure;
        }
 
index 8d987c3573fd4ca9e1708e188d487e53ebd7dfd7..7b3a9e5999c0664cebe524fefba7130a6df003ce 100644 (file)
@@ -345,19 +345,27 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
 }
 EXPORT_SYMBOL_GPL(xt_find_revision);
 
-static char *textify_hooks(char *buf, size_t size, unsigned int mask)
+static char *
+textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto)
 {
-       static const char *const names[] = {
+       static const char *const inetbr_names[] = {
                "PREROUTING", "INPUT", "FORWARD",
                "OUTPUT", "POSTROUTING", "BROUTING",
        };
-       unsigned int i;
+       static const char *const arp_names[] = {
+               "INPUT", "FORWARD", "OUTPUT",
+       };
+       const char *const *names;
+       unsigned int i, max;
        char *p = buf;
        bool np = false;
        int res;
 
+       names = (nfproto == NFPROTO_ARP) ? arp_names : inetbr_names;
+       max   = (nfproto == NFPROTO_ARP) ? ARRAY_SIZE(arp_names) :
+                                          ARRAY_SIZE(inetbr_names);
        *p = '\0';
-       for (i = 0; i < ARRAY_SIZE(names); ++i) {
+       for (i = 0; i < max; ++i) {
                if (!(mask & (1 << i)))
                        continue;
                res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]);
@@ -402,8 +410,10 @@ int xt_check_match(struct xt_mtchk_param *par,
                pr_err("%s_tables: %s match: used from hooks %s, but only "
                       "valid from %s\n",
                       xt_prefix[par->family], par->match->name,
-                      textify_hooks(used, sizeof(used), par->hook_mask),
-                      textify_hooks(allow, sizeof(allow), par->match->hooks));
+                      textify_hooks(used, sizeof(used), par->hook_mask,
+                                    par->family),
+                      textify_hooks(allow, sizeof(allow), par->match->hooks,
+                                    par->family));
                return -EINVAL;
        }
        if (par->match->proto && (par->match->proto != proto || inv_proto)) {
@@ -575,8 +585,10 @@ int xt_check_target(struct xt_tgchk_param *par,
                pr_err("%s_tables: %s target: used from hooks %s, but only "
                       "usable from %s\n",
                       xt_prefix[par->family], par->target->name,
-                      textify_hooks(used, sizeof(used), par->hook_mask),
-                      textify_hooks(allow, sizeof(allow), par->target->hooks));
+                      textify_hooks(used, sizeof(used), par->hook_mask,
+                                    par->family),
+                      textify_hooks(allow, sizeof(allow), par->target->hooks,
+                                    par->family));
                return -EINVAL;
        }
        if (par->target->proto && (par->target->proto != proto || inv_proto)) {
index ae7f5daeee4362bff5aee9a30a85347de70a2ccc..bde009ed8d3bf36d6defdbdbad8aca991c539281 100644 (file)
@@ -109,7 +109,7 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
        struct xt_ct_target_info *info = par->targinfo;
        struct nf_conntrack_tuple t;
        struct nf_conn *ct;
-       int ret;
+       int ret = -EOPNOTSUPP;
 
        if (info->flags & ~XT_CT_NOTRACK)
                return -EINVAL;
@@ -149,6 +149,10 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
 
        __set_bit(IPS_TEMPLATE_BIT, &ct->status);
        __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+
+       /* Overload tuple linked list to put us in template list. */
+       hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                                &par->net->ct.tmpl);
 out:
        info->ct = ct;
        return 0;
@@ -243,7 +247,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
        struct xt_ct_target_info_v1 *info = par->targinfo;
        struct nf_conntrack_tuple t;
        struct nf_conn *ct;
-       int ret;
+       int ret = -EOPNOTSUPP;
 
        if (info->flags & ~XT_CT_NOTRACK)
                return -EINVAL;
@@ -289,6 +293,10 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
 
        __set_bit(IPS_TEMPLATE_BIT, &ct->status);
        __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+
+       /* Overload tuple linked list to put us in template list. */
+       hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                                &par->net->ct.tmpl);
 out:
        info->ct = ct;
        return 0;
@@ -377,14 +385,60 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
        },
 };
 
+static unsigned int
+notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+       /* Previously seen (loopback)? Ignore. */
+       if (skb->nfct != NULL)
+               return XT_CONTINUE;
+
+       skb->nfct = &nf_ct_untracked_get()->ct_general;
+       skb->nfctinfo = IP_CT_NEW;
+       nf_conntrack_get(skb->nfct);
+
+       return XT_CONTINUE;
+}
+
+static int notrack_chk(const struct xt_tgchk_param *par)
+{
+       if (!par->net->xt.notrack_deprecated_warning) {
+               pr_info("netfilter: NOTRACK target is deprecated, "
+                       "use CT instead or upgrade iptables\n");
+               par->net->xt.notrack_deprecated_warning = true;
+       }
+       return 0;
+}
+
+static struct xt_target notrack_tg_reg __read_mostly = {
+       .name           = "NOTRACK",
+       .revision       = 0,
+       .family         = NFPROTO_UNSPEC,
+       .checkentry     = notrack_chk,
+       .target         = notrack_tg,
+       .table          = "raw",
+       .me             = THIS_MODULE,
+};
+
 static int __init xt_ct_tg_init(void)
 {
-       return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       int ret;
+
+       ret = xt_register_target(&notrack_tg_reg);
+       if (ret < 0)
+               return ret;
+
+       ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       if (ret < 0) {
+               xt_unregister_target(&notrack_tg_reg);
+               return ret;
+       }
+       return 0;
 }
 
 static void __exit xt_ct_tg_exit(void)
 {
        xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
+       xt_unregister_target(&notrack_tg_reg);
 }
 
 module_init(xt_ct_tg_init);
@@ -394,3 +448,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Xtables: connection tracking target");
 MODULE_ALIAS("ipt_CT");
 MODULE_ALIAS("ip6t_CT");
+MODULE_ALIAS("ipt_NOTRACK");
+MODULE_ALIAS("ip6t_NOTRACK");
index 26a668a84aa288a82dc3eb243df2728a3169b2a2..a9d7af953ceb8bcd1d961eef21d0f3cb3ee22919 100644 (file)
@@ -157,11 +157,22 @@ dsthash_find(const struct xt_hashlimit_htable *ht,
 /* allocate dsthash_ent, initialize dst, put in htable and lock it */
 static struct dsthash_ent *
 dsthash_alloc_init(struct xt_hashlimit_htable *ht,
-                  const struct dsthash_dst *dst)
+                  const struct dsthash_dst *dst, bool *race)
 {
        struct dsthash_ent *ent;
 
        spin_lock(&ht->lock);
+
+       /* Two or more packets may race to create the same entry in the
+        * hashtable, double check if this packet lost race.
+        */
+       ent = dsthash_find(ht, dst);
+       if (ent != NULL) {
+               spin_unlock(&ht->lock);
+               *race = true;
+               return ent;
+       }
+
        /* initialize hash with random val at the time we allocate
         * the first hashtable entry */
        if (unlikely(!ht->rnd_initialized)) {
@@ -318,7 +329,10 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo)
                parent = hashlimit_net->ipt_hashlimit;
        else
                parent = hashlimit_net->ip6t_hashlimit;
-       remove_proc_entry(hinfo->pde->name, parent);
+
+       if(parent != NULL)
+               remove_proc_entry(hinfo->pde->name, parent);
+
        htable_selective_cleanup(hinfo, select_all);
        vfree(hinfo);
 }
@@ -585,6 +599,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
        unsigned long now = jiffies;
        struct dsthash_ent *dh;
        struct dsthash_dst dst;
+       bool race = false;
        u32 cost;
 
        if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
@@ -593,13 +608,18 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
        rcu_read_lock_bh();
        dh = dsthash_find(hinfo, &dst);
        if (dh == NULL) {
-               dh = dsthash_alloc_init(hinfo, &dst);
+               dh = dsthash_alloc_init(hinfo, &dst, &race);
                if (dh == NULL) {
                        rcu_read_unlock_bh();
                        goto hotdrop;
+               } else if (race) {
+                       /* Already got an entry, update expiration timeout */
+                       dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
+                       rateinfo_recalc(dh, now, hinfo->cfg.mode);
+               } else {
+                       dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
+                       rateinfo_init(dh, hinfo);
                }
-               dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
-               rateinfo_init(dh, hinfo);
        } else {
                /* update expiration timeout */
                dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
@@ -856,6 +876,27 @@ static int __net_init hashlimit_proc_net_init(struct net *net)
 
 static void __net_exit hashlimit_proc_net_exit(struct net *net)
 {
+       struct xt_hashlimit_htable *hinfo;
+       struct hlist_node *pos;
+       struct proc_dir_entry *pde;
+       struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
+
+       /* recent_net_exit() is called before recent_mt_destroy(). Make sure
+        * that the parent xt_recent proc entry is is empty before trying to
+        * remove it.
+        */
+       mutex_lock(&hashlimit_mutex);
+       pde = hashlimit_net->ipt_hashlimit;
+       if (pde == NULL)
+               pde = hashlimit_net->ip6t_hashlimit;
+
+       hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node)
+               remove_proc_entry(hinfo->pde->name, pde);
+
+       hashlimit_net->ipt_hashlimit = NULL;
+       hashlimit_net->ip6t_hashlimit = NULL;
+       mutex_unlock(&hashlimit_mutex);
+
        proc_net_remove(net, "ipt_hashlimit");
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
        proc_net_remove(net, "ip6t_hashlimit");
@@ -872,9 +913,6 @@ static int __net_init hashlimit_net_init(struct net *net)
 
 static void __net_exit hashlimit_net_exit(struct net *net)
 {
-       struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
-
-       BUG_ON(!hlist_empty(&hashlimit_net->htables));
        hashlimit_proc_net_exit(net);
 }
 
index 4635c9b0045981d862cb3b31a34ac9ab735eb85e..978efc9b555a3e1936cb5e49c0537055e3b642f9 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/skbuff.h>
 #include <linux/inet.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
@@ -310,6 +311,14 @@ out:
        return ret;
 }
 
+static void recent_table_free(void *addr)
+{
+       if (is_vmalloc_addr(addr))
+               vfree(addr);
+       else
+               kfree(addr);
+}
+
 static int recent_mt_check(const struct xt_mtchk_param *par,
                           const struct xt_recent_mtinfo_v1 *info)
 {
@@ -322,6 +331,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
 #endif
        unsigned int i;
        int ret = -EINVAL;
+       size_t sz;
 
        if (unlikely(!hash_rnd_inited)) {
                get_random_bytes(&hash_rnd, sizeof(hash_rnd));
@@ -360,8 +370,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
                goto out;
        }
 
-       t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
-                   GFP_KERNEL);
+       sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size;
+       if (sz <= PAGE_SIZE)
+               t = kzalloc(sz, GFP_KERNEL);
+       else
+               t = vzalloc(sz);
        if (t == NULL) {
                ret = -ENOMEM;
                goto out;
@@ -377,14 +390,14 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
        uid = make_kuid(&init_user_ns, ip_list_uid);
        gid = make_kgid(&init_user_ns, ip_list_gid);
        if (!uid_valid(uid) || !gid_valid(gid)) {
-               kfree(t);
+               recent_table_free(t);
                ret = -EINVAL;
                goto out;
        }
        pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
                  &recent_mt_fops, t);
        if (pde == NULL) {
-               kfree(t);
+               recent_table_free(t);
                ret = -ENOMEM;
                goto out;
        }
@@ -431,10 +444,11 @@ static void recent_mt_destroy(const struct xt_mtdtor_param *par)
                list_del(&t->list);
                spin_unlock_bh(&recent_lock);
 #ifdef CONFIG_PROC_FS
-               remove_proc_entry(t->name, recent_net->xt_recent);
+               if (recent_net->xt_recent != NULL)
+                       remove_proc_entry(t->name, recent_net->xt_recent);
 #endif
                recent_table_flush(t);
-               kfree(t);
+               recent_table_free(t);
        }
        mutex_unlock(&recent_mutex);
 }
@@ -615,6 +629,20 @@ static int __net_init recent_proc_net_init(struct net *net)
 
 static void __net_exit recent_proc_net_exit(struct net *net)
 {
+       struct recent_net *recent_net = recent_pernet(net);
+       struct recent_table *t;
+
+       /* recent_net_exit() is called before recent_mt_destroy(). Make sure
+        * that the parent xt_recent proc entry is is empty before trying to
+        * remove it.
+        */
+       spin_lock_bh(&recent_lock);
+       list_for_each_entry(t, &recent_net->tables, list)
+               remove_proc_entry(t->name, recent_net->xt_recent);
+
+       recent_net->xt_recent = NULL;
+       spin_unlock_bh(&recent_lock);
+
        proc_net_remove(net, "xt_recent");
 }
 #else
@@ -638,9 +666,6 @@ static int __net_init recent_net_init(struct net *net)
 
 static void __net_exit recent_net_exit(struct net *net)
 {
-       struct recent_net *recent_net = recent_pernet(net);
-
-       BUG_ON(!list_empty(&recent_net->tables));
        recent_proc_net_exit(net);
 }
 
index a9327e2e48ce8450212feef7085f91e446766faa..670cbc3518ded5930f900eaca7e0677835cf750b 100644 (file)
 /* Must be called with rcu_read_lock. */
 static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 {
-       if (unlikely(!vport)) {
-               kfree_skb(skb);
-               return;
-       }
+       if (unlikely(!vport))
+               goto error;
+
+       if (unlikely(skb_warn_if_lro(skb)))
+               goto error;
 
        /* Make our own copy of the packet.  Otherwise we will mangle the
         * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
@@ -50,6 +51,10 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 
        skb_push(skb, ETH_HLEN);
        ovs_vport_receive(vport, skb);
+       return;
+
+error:
+       kfree_skb(skb);
 }
 
 /* Called with rcu_read_lock and bottom-halves disabled. */
@@ -169,9 +174,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
                goto error;
        }
 
-       if (unlikely(skb_warn_if_lro(skb)))
-               goto error;
-
        skb->dev = netdev_vport->dev;
        len = skb->len;
        dev_queue_xmit(skb);
index e639645e8fec8ca365c8fc1bc4fb3650db04b5f4..c111bd0e083a5576d86dfc8f9ad91ab320c46efa 100644 (file)
@@ -2361,13 +2361,15 @@ static int packet_release(struct socket *sock)
 
        packet_flush_mclist(sk);
 
-       memset(&req_u, 0, sizeof(req_u));
-
-       if (po->rx_ring.pg_vec)
+       if (po->rx_ring.pg_vec) {
+               memset(&req_u, 0, sizeof(req_u));
                packet_set_ring(sk, &req_u, 1, 0);
+       }
 
-       if (po->tx_ring.pg_vec)
+       if (po->tx_ring.pg_vec) {
+               memset(&req_u, 0, sizeof(req_u));
                packet_set_ring(sk, &req_u, 1, 1);
+       }
 
        fanout_release(sk);
 
index a1e116277477541606e51e0c4af31aa53af4b673..31b74f5e61adbd37535b636b1499c384bdd992f5 100644 (file)
@@ -434,12 +434,11 @@ static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
                version = RDS_PROTOCOL_3_0;
                while ((common >>= 1) != 0)
                        version++;
-       }
-       printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using "
-                       "incompatible protocol version %u.%u\n",
-                       &dp->dp_saddr,
-                       dp->dp_protocol_major,
-                       dp->dp_protocol_minor);
+       } else
+               printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using incompatible protocol version %u.%u\n",
+                               &dp->dp_saddr,
+                               dp->dp_protocol_major,
+                               dp->dp_protocol_minor);
        return version;
 }
 
index 8c5bc857f04d92dd85986f4c292437223a4de557..8eb9501e3d60d41d30c3af511551f039a6264958 100644 (file)
@@ -339,8 +339,8 @@ static int rds_ib_recv_refill_one(struct rds_connection *conn,
        sge->length = sizeof(struct rds_header);
 
        sge = &recv->r_sge[1];
-       sge->addr = sg_dma_address(&recv->r_frag->f_sg);
-       sge->length = sg_dma_len(&recv->r_frag->f_sg);
+       sge->addr = ib_sg_dma_address(ic->i_cm_id->device, &recv->r_frag->f_sg);
+       sge->length = ib_sg_dma_len(ic->i_cm_id->device, &recv->r_frag->f_sg);
 
        ret = 0;
 out:
@@ -381,7 +381,10 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill)
                ret = ib_post_recv(ic->i_cm_id->qp, &recv->r_wr, &failed_wr);
                rdsdebug("recv %p ibinc %p page %p addr %lu ret %d\n", recv,
                         recv->r_ibinc, sg_page(&recv->r_frag->f_sg),
-                        (long) sg_dma_address(&recv->r_frag->f_sg), ret);
+                        (long) ib_sg_dma_address(
+                               ic->i_cm_id->device,
+                               &recv->r_frag->f_sg),
+                       ret);
                if (ret) {
                        rds_ib_conn_error(conn, "recv post on "
                               "%pI4 returned %d, disconnecting and "
index d2922c0ef57a65047e82e9fbf8f1a890dcdbea85..79e8ed4ac7ce7de355895b63fc06991be0b6af26 100644 (file)
@@ -919,7 +919,7 @@ ok:
        q->now = ktime_to_ns(ktime_get());
        start_at = jiffies;
 
-       next_event = q->now + 5 * NSEC_PER_SEC;
+       next_event = q->now + 5LLU * NSEC_PER_SEC;
 
        for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
                /* common case optimization - skip event handler quickly */
@@ -1135,9 +1135,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
        memset(&opt, 0, sizeof(opt));
 
        opt.rate.rate = cl->rate.rate_bps >> 3;
-       opt.buffer = cl->buffer;
+       opt.buffer = PSCHED_NS2TICKS(cl->buffer);
        opt.ceil.rate = cl->ceil.rate_bps >> 3;
-       opt.cbuffer = cl->cbuffer;
+       opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer);
        opt.quantum = cl->quantum;
        opt.prio = cl->prio;
        opt.level = cl->level;
index 298c0ddfb57e3e5625a69d412c548d198005fd3b..3d2acc7a9c8099e677412276eeafe5a8b3f90fcb 100644 (file)
@@ -438,18 +438,18 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                if (q->rate) {
                        struct sk_buff_head *list = &sch->q;
 
-                       delay += packet_len_2_sched_time(skb->len, q);
-
                        if (!skb_queue_empty(list)) {
                                /*
-                                * Last packet in queue is reference point (now).
-                                * First packet in queue is already in flight,
-                                * calculate this time bonus and substract
+                                * Last packet in queue is reference point (now),
+                                * calculate this time bonus and subtract
                                 * from delay.
                                 */
-                               delay -= now - netem_skb_cb(skb_peek(list))->time_to_send;
+                               delay -= netem_skb_cb(skb_peek_tail(list))->time_to_send - now;
+                               delay = max_t(psched_tdiff_t, 0, delay);
                                now = netem_skb_cb(skb_peek_tail(list))->time_to_send;
                        }
+
+                       delay += packet_len_2_sched_time(skb->len, q);
                }
 
                cb->time_to_send = now + delay;
index c26210618e14cadca832f933a886a1250f0490db..cf4852814e0c667b85be0e7b763bd7fe8964f546 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 menuconfig IP_SCTP
-       tristate "The SCTP Protocol (EXPERIMENTAL)"
-       depends on INET && EXPERIMENTAL
+       tristate "The SCTP Protocol"
+       depends on INET
        depends on IPV6 || IPV6=n
        select CRYPTO
        select CRYPTO_HMAC
@@ -68,7 +68,7 @@ config SCTP_DBG_OBJCNT
          If unsure, say N
 choice
        prompt "Default SCTP cookie HMAC encoding"
-       default SCTP_COOKIE_HMAC_MD5
+       default SCTP_DEFAULT_COOKIE_HMAC_MD5
        help
          This option sets the default sctp cookie hmac algorithm
          when in doubt select 'md5'
index 159b9bc5d63300e53560cf6495f8f65b9fd06449..d8420ae614dcaa2b12dfbe5cef78a39c7bfda8ca 100644 (file)
@@ -71,7 +71,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
                return;
 
        if (atomic_dec_and_test(&key->refcnt)) {
-               kfree(key);
+               kzfree(key);
                SCTP_DBG_OBJCNT_DEC(keys);
        }
 }
index 17a001bac2cc3c81ab052c2b603b02091bd924e0..1a9c5fb77310a22f609d07918ed5629c0d7cc7d7 100644 (file)
@@ -249,6 +249,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)
 /* Final destructor for endpoint.  */
 static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 {
+       int i;
+
        SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
 
        /* Free up the HMAC transform. */
@@ -271,6 +273,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
        sctp_inq_free(&ep->base.inqueue);
        sctp_bind_addr_free(&ep->base.bind_addr);
 
+       for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i)
+               memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE);
+
        /* Remove and free the port */
        if (sctp_sk(ep->base.sk)->bind_hash)
                sctp_put_port(ep->base.sk);
index f3f0f4dc31dd3adf33033e071e02cb891b982719..391a245d520316c865aad51424b94b9fe6fb8bf7 100644 (file)
@@ -326,9 +326,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
         */
        rcu_read_lock();
        list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-               if (!laddr->valid && laddr->state != SCTP_ADDR_SRC)
+               if (!laddr->valid)
                        continue;
-               if ((laddr->a.sa.sa_family == AF_INET6) &&
+               if ((laddr->state == SCTP_ADDR_SRC) &&
+                   (laddr->a.sa.sa_family == AF_INET6) &&
                    (scope <= sctp_scope(&laddr->a))) {
                        bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
                        if (!baddr || (matchlen < bmatchlen)) {
index 379c81dee9d1256b3a1af84b84bc23b28092f12b..9bcdbd02d77713a5973dd9afd71a9c4783919648 100644 (file)
@@ -224,7 +224,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
 
 /* Free the outqueue structure and any related pending chunks.
  */
-void sctp_outq_teardown(struct sctp_outq *q)
+static void __sctp_outq_teardown(struct sctp_outq *q)
 {
        struct sctp_transport *transport;
        struct list_head *lchunk, *temp;
@@ -277,8 +277,6 @@ void sctp_outq_teardown(struct sctp_outq *q)
                sctp_chunk_free(chunk);
        }
 
-       q->error = 0;
-
        /* Throw away any leftover control chunks. */
        list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
                list_del_init(&chunk->list);
@@ -286,11 +284,17 @@ void sctp_outq_teardown(struct sctp_outq *q)
        }
 }
 
+void sctp_outq_teardown(struct sctp_outq *q)
+{
+       __sctp_outq_teardown(q);
+       sctp_outq_init(q->asoc, q);
+}
+
 /* Free the outqueue structure and any related pending chunks.  */
 void sctp_outq_free(struct sctp_outq *q)
 {
        /* Throw away leftover chunks. */
-       sctp_outq_teardown(q);
+       __sctp_outq_teardown(q);
 
        /* If we were kmalloc()'d, free the memory.  */
        if (q->malloced)
index 618ec7e216cae9bb17038c07ff5d87a75c8f6208..5131fcfedb03c0b09e8c7e451341cebd82e49692 100644 (file)
@@ -1779,8 +1779,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
 
        /* Update the content of current association. */
        sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+                       SCTP_STATE(SCTP_STATE_ESTABLISHED));
+       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
index 9e65758cb03814f9372eafbf86c4821af124be00..cedd9bf67b8c5942aa0cbf5441342be62abd5e69 100644 (file)
@@ -3390,7 +3390,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
 
        ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);
 out:
-       kfree(authkey);
+       kzfree(authkey);
        return ret;
 }
 
index 043889ac86c0419b3d368481b202864077034efa..bf3c6e8fc4017a64f93ff91c0ce96c8debbf44f4 100644 (file)
@@ -366,7 +366,11 @@ int sctp_sysctl_net_register(struct net *net)
 
 void sctp_sysctl_net_unregister(struct net *net)
 {
+       struct ctl_table *table;
+
+       table = net->sctp.sysctl_header->ctl_table_arg;
        unregister_net_sysctl_table(net->sctp.sysctl_header);
+       kfree(table);
 }
 
 static struct ctl_table_header * sctp_sysctl_header;
index 822f020fa7f458e07a8e216e6609447daefb8747..507b5e84fbdb26f88fab789e37f65a976ef6f198 100644 (file)
@@ -555,7 +555,7 @@ EXPORT_SYMBOL_GPL(rpc_clone_client);
  * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
  *
  * @clnt: RPC client whose parameters are copied
- * @auth: security flavor for new client
+ * @flavor: security flavor for new client
  *
  * Returns a fresh RPC client or an ERR_PTR.
  */
@@ -610,11 +610,6 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks);
  */
 void rpc_shutdown_client(struct rpc_clnt *clnt)
 {
-       /*
-        * To avoid deadlock, never call rpc_shutdown_client from a
-        * workqueue context!
-        */
-       WARN_ON_ONCE(current->flags & PF_WQ_WORKER);
        might_sleep();
 
        dprintk_rcu("RPC:       shutting down %s client for %s\n",
index 411f332de0b316b2ae33bda6e9385a498bd7fabd..795a0f4e920bf8b4e52e78458b210fea02df8132 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/nsproxy.h>
 #include <net/ipv6.h>
 
 #include <linux/sunrpc/clnt.h>
index d17a704aaf5f2251674b3fa23421fa087b8ddd14..fb20f25ddec9b70c805ad65d675441d02b62055b 100644 (file)
@@ -98,9 +98,25 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
        list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
 }
 
+static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue)
+{
+       struct list_head *q = &queue->tasks[queue->priority];
+       struct rpc_task *task;
+
+       if (!list_empty(q)) {
+               task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
+               if (task->tk_owner == queue->owner)
+                       list_move_tail(&task->u.tk_wait.list, q);
+       }
+}
+
 static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
 {
-       queue->priority = priority;
+       if (queue->priority != priority) {
+               /* Fairness: rotate the list when changing priority */
+               rpc_rotate_queue_owner(queue);
+               queue->priority = priority;
+       }
 }
 
 static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid)
@@ -934,16 +950,35 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data)
        return task;
 }
 
+/*
+ * rpc_free_task - release rpc task and perform cleanups
+ *
+ * Note that we free up the rpc_task _after_ rpc_release_calldata()
+ * in order to work around a workqueue dependency issue.
+ *
+ * Tejun Heo states:
+ * "Workqueue currently considers two work items to be the same if they're
+ * on the same address and won't execute them concurrently - ie. it
+ * makes a work item which is queued again while being executed wait
+ * for the previous execution to complete.
+ *
+ * If a work function frees the work item, and then waits for an event
+ * which should be performed by another work item and *that* work item
+ * recycles the freed work item, it can create a false dependency loop.
+ * There really is no reliable way to detect this short of verifying
+ * every memory free."
+ *
+ */
 static void rpc_free_task(struct rpc_task *task)
 {
-       const struct rpc_call_ops *tk_ops = task->tk_ops;
-       void *calldata = task->tk_calldata;
+       unsigned short tk_flags = task->tk_flags;
+
+       rpc_release_calldata(task->tk_ops, task->tk_calldata);
 
-       if (task->tk_flags & RPC_TASK_DYNAMIC) {
+       if (tk_flags & RPC_TASK_DYNAMIC) {
                dprintk("RPC: %5u freeing task\n", task->tk_pid);
                mempool_free(task, rpc_task_mempool);
        }
-       rpc_release_calldata(tk_ops, calldata);
 }
 
 static void rpc_async_release(struct work_struct *work)
@@ -953,8 +988,7 @@ static void rpc_async_release(struct work_struct *work)
 
 static void rpc_release_resources_task(struct rpc_task *task)
 {
-       if (task->tk_rqstp)
-               xprt_release(task);
+       xprt_release(task);
        if (task->tk_msg.rpc_cred) {
                put_rpccred(task->tk_msg.rpc_cred);
                task->tk_msg.rpc_cred = NULL;
index dfa4ba69ff4503748ed22bad836643540221af39..dbf12ac5ecb7f611fac1a06d5db643a7a5a39ac4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/slab.h>
-#include <linux/nsproxy.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
@@ -1041,7 +1040,7 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net)
 }
 
 /*
- * Printk the given error with the address of the client that caused it.
+ * dprintk the given error with the address of the client that caused it.
  */
 static __printf(2, 3)
 void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
@@ -1055,8 +1054,7 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
        vaf.fmt = fmt;
        vaf.va = &args;
 
-       net_warn_ratelimited("svc: %s: %pV",
-                            svc_print_addr(rqstp, buf, sizeof(buf)), &vaf);
+       dprintk("svc: %s: %pV", svc_print_addr(rqstp, buf, sizeof(buf)), &vaf);
 
        va_end(args);
 }
@@ -1305,7 +1303,7 @@ svc_process(struct svc_rqst *rqstp)
         * Setup response xdr_buf.
         * Initially it has just one page
         */
-       rqstp->rq_resused = 1;
+       rqstp->rq_next_page = &rqstp->rq_respages[1];
        resv->iov_base = page_address(rqstp->rq_respages[0]);
        resv->iov_len = 0;
        rqstp->rq_res.pages = rqstp->rq_respages + 1;
index cc3020d1678905a9f6930cab28753dfbbe99713e..0f679df7d072794094ece1aa48988e834395d849 100644 (file)
@@ -465,7 +465,7 @@ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp,
 }
 
 /*
- * See net/ipv6/datagram.c : datagram_recv_ctl
+ * See net/ipv6/datagram.c : ip6_datagram_recv_ctl
  */
 static int svc_udp_get_dest_address6(struct svc_rqst *rqstp,
                                     struct cmsghdr *cmh)
@@ -605,6 +605,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
                rqstp->rq_respages = rqstp->rq_pages + 1 +
                        DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE);
        }
+       rqstp->rq_next_page = rqstp->rq_respages+1;
 
        if (serv->sv_stats)
                serv->sv_stats->netudpcnt++;
@@ -878,9 +879,9 @@ static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst
 {
        unsigned int i, len, npages;
 
-       if (svsk->sk_tcplen <= sizeof(rpc_fraghdr))
+       if (svsk->sk_datalen == 0)
                return 0;
-       len = svsk->sk_tcplen - sizeof(rpc_fraghdr);
+       len = svsk->sk_datalen;
        npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < npages; i++) {
                if (rqstp->rq_pages[i] != NULL)
@@ -897,9 +898,9 @@ static void svc_tcp_save_pages(struct svc_sock *svsk, struct svc_rqst *rqstp)
 {
        unsigned int i, len, npages;
 
-       if (svsk->sk_tcplen <= sizeof(rpc_fraghdr))
+       if (svsk->sk_datalen == 0)
                return;
-       len = svsk->sk_tcplen - sizeof(rpc_fraghdr);
+       len = svsk->sk_datalen;
        npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < npages; i++) {
                svsk->sk_pages[i] = rqstp->rq_pages[i];
@@ -911,9 +912,9 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
 {
        unsigned int i, len, npages;
 
-       if (svsk->sk_tcplen <= sizeof(rpc_fraghdr))
+       if (svsk->sk_datalen == 0)
                goto out;
-       len = svsk->sk_tcplen - sizeof(rpc_fraghdr);
+       len = svsk->sk_datalen;
        npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < npages; i++) {
                BUG_ON(svsk->sk_pages[i] == NULL);
@@ -922,13 +923,12 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
        }
 out:
        svsk->sk_tcplen = 0;
+       svsk->sk_datalen = 0;
 }
 
 /*
- * Receive data.
+ * Receive fragment record header.
  * If we haven't gotten the record length yet, get the next four bytes.
- * Otherwise try to gobble up as much as possible up to the complete
- * record length.
  */
 static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
 {
@@ -954,32 +954,16 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
                        return -EAGAIN;
                }
 
-               svsk->sk_reclen = ntohl(svsk->sk_reclen);
-               if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) {
-                       /* FIXME: technically, a record can be fragmented,
-                        *  and non-terminal fragments will not have the top
-                        *  bit set in the fragment length header.
-                        *  But apparently no known nfs clients send fragmented
-                        *  records. */
-                       net_notice_ratelimited("RPC: multiple fragments per record not supported\n");
-                       goto err_delete;
-               }
-
-               svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
-               dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
-               if (svsk->sk_reclen > serv->sv_max_mesg) {
-                       net_notice_ratelimited("RPC: fragment too large: 0x%08lx\n",
-                                              (unsigned long)svsk->sk_reclen);
+               dprintk("svc: TCP record, %d bytes\n", svc_sock_reclen(svsk));
+               if (svc_sock_reclen(svsk) + svsk->sk_datalen >
+                                                       serv->sv_max_mesg) {
+                       net_notice_ratelimited("RPC: fragment too large: %d\n",
+                                       svc_sock_reclen(svsk));
                        goto err_delete;
                }
        }
 
-       if (svsk->sk_reclen < 8)
-               goto err_delete; /* client is nuts. */
-
-       len = svsk->sk_reclen;
-
-       return len;
+       return svc_sock_reclen(svsk);
 error:
        dprintk("RPC: TCP recv_record got %d\n", len);
        return len;
@@ -1023,7 +1007,7 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
        if (dst->iov_len < src->iov_len)
                return -EAGAIN; /* whatever; just giving up. */
        memcpy(dst->iov_base, src->iov_base, src->iov_len);
-       xprt_complete_rqst(req->rq_task, svsk->sk_reclen);
+       xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
        rqstp->rq_arg.len = 0;
        return 0;
 }
@@ -1042,6 +1026,17 @@ static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
        return i;
 }
 
+static void svc_tcp_fragment_received(struct svc_sock *svsk)
+{
+       /* If we have more data, signal svc_xprt_enqueue() to try again */
+       if (svc_recv_available(svsk) > sizeof(rpc_fraghdr))
+               set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+       dprintk("svc: TCP %s record (%d bytes)\n",
+               svc_sock_final_rec(svsk) ? "final" : "nonfinal",
+               svc_sock_reclen(svsk));
+       svsk->sk_tcplen = 0;
+       svsk->sk_reclen = 0;
+}
 
 /*
  * Receive data from a TCP socket.
@@ -1068,29 +1063,39 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                goto error;
 
        base = svc_tcp_restore_pages(svsk, rqstp);
-       want = svsk->sk_reclen - base;
+       want = svc_sock_reclen(svsk) - (svsk->sk_tcplen - sizeof(rpc_fraghdr));
 
        vec = rqstp->rq_vec;
 
        pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0],
-                                               svsk->sk_reclen);
+                                               svsk->sk_datalen + want);
 
        rqstp->rq_respages = &rqstp->rq_pages[pnum];
+       rqstp->rq_next_page = rqstp->rq_respages + 1;
 
        /* Now receive data */
        len = svc_partial_recvfrom(rqstp, vec, pnum, want, base);
-       if (len >= 0)
+       if (len >= 0) {
                svsk->sk_tcplen += len;
-       if (len != want) {
+               svsk->sk_datalen += len;
+       }
+       if (len != want || !svc_sock_final_rec(svsk)) {
                svc_tcp_save_pages(svsk, rqstp);
                if (len < 0 && len != -EAGAIN)
-                       goto err_other;
-               dprintk("svc: incomplete TCP record (%d of %d)\n",
-                       svsk->sk_tcplen, svsk->sk_reclen);
+                       goto err_delete;
+               if (len == want)
+                       svc_tcp_fragment_received(svsk);
+               else
+                       dprintk("svc: incomplete TCP record (%d of %d)\n",
+                               (int)(svsk->sk_tcplen - sizeof(rpc_fraghdr)),
+                               svc_sock_reclen(svsk));
                goto err_noclose;
        }
 
-       rqstp->rq_arg.len = svsk->sk_reclen;
+       if (svc_sock_reclen(svsk) < 8)
+               goto err_delete; /* client is nuts. */
+
+       rqstp->rq_arg.len = svsk->sk_datalen;
        rqstp->rq_arg.page_base = 0;
        if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
                rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
@@ -1107,11 +1112,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                len = receive_cb_reply(svsk, rqstp);
 
        /* Reset TCP read info */
-       svsk->sk_reclen = 0;
-       svsk->sk_tcplen = 0;
-       /* If we have more data, signal svc_xprt_enqueue() to try again */
-       if (svc_recv_available(svsk) > sizeof(rpc_fraghdr))
-               set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+       svsk->sk_datalen = 0;
+       svc_tcp_fragment_received(svsk);
 
        if (len < 0)
                goto error;
@@ -1120,15 +1122,14 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
        if (serv->sv_stats)
                serv->sv_stats->nettcpcnt++;
 
-       dprintk("svc: TCP complete record (%d bytes)\n", rqstp->rq_arg.len);
        return rqstp->rq_arg.len;
 
 error:
        if (len != -EAGAIN)
-               goto err_other;
+               goto err_delete;
        dprintk("RPC: TCP recvfrom got EAGAIN\n");
        return 0;
-err_other:
+err_delete:
        printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
               svsk->sk_xprt.xpt_server->sv_name, -len);
        set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
@@ -1305,6 +1306,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
 
                svsk->sk_reclen = 0;
                svsk->sk_tcplen = 0;
+               svsk->sk_datalen = 0;
                memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages));
 
                tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
index bd462a532acfa695906887db429896ae569eac26..33811db8788a2e74e5781a0c20bdbceb829b5018 100644 (file)
@@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
 void xprt_release(struct rpc_task *task)
 {
        struct rpc_xprt *xprt;
-       struct rpc_rqst *req;
+       struct rpc_rqst *req = task->tk_rqstp;
 
-       if (!(req = task->tk_rqstp))
+       if (req == NULL) {
+               if (task->tk_client) {
+                       rcu_read_lock();
+                       xprt = rcu_dereference(task->tk_client->cl_xprt);
+                       if (xprt->snd_task == task)
+                               xprt_release_write(xprt, task);
+                       rcu_read_unlock();
+               }
                return;
+       }
 
        xprt = req->rq_xprt;
        if (task->tk_ops->rpc_count_stats != NULL)
index 41cb63b623dfa5033388740d454f937c84ae1db3..0ce75524ed2159982414da7cbf304a0ff3db7044 100644 (file)
@@ -521,11 +521,11 @@ next_sge:
                rqstp->rq_pages[ch_no] = NULL;
 
        /*
-        * Detach res pages. svc_release must see a resused count of
-        * zero or it will attempt to put them.
+        * Detach res pages. If svc_release sees any it will attempt to
+        * put them.
         */
-       while (rqstp->rq_resused)
-               rqstp->rq_respages[--rqstp->rq_resused] = NULL;
+       while (rqstp->rq_next_page != rqstp->rq_respages)
+               *(--rqstp->rq_next_page) = NULL;
 
        return err;
 }
@@ -550,7 +550,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
 
        /* rq_respages starts after the last arg page */
        rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
-       rqstp->rq_resused = 0;
+       rqstp->rq_next_page = &rqstp->rq_arg.pages[page_no];
 
        /* Rebuild rq_arg head and tail. */
        rqstp->rq_arg.head[0] = head->arg.head[0];
index 42eb7ba0b9034afc1ade6770fea5d49fe305cc97..c1d124dc772be5f9381f11ad87d9519c5e200613 100644 (file)
@@ -548,6 +548,7 @@ static int send_reply(struct svcxprt_rdma *rdma,
        int sge_no;
        int sge_bytes;
        int page_no;
+       int pages;
        int ret;
 
        /* Post a recv buffer to handle another request. */
@@ -611,7 +612,8 @@ static int send_reply(struct svcxprt_rdma *rdma,
         * respages array. They are our pages until the I/O
         * completes.
         */
-       for (page_no = 0; page_no < rqstp->rq_resused; page_no++) {
+       pages = rqstp->rq_next_page - rqstp->rq_respages;
+       for (page_no = 0; page_no < pages; page_no++) {
                ctxt->pages[page_no+1] = rqstp->rq_respages[page_no];
                ctxt->count++;
                rqstp->rq_respages[page_no] = NULL;
index 14d990400354200056e99d14132d6e7ab2504ccb..b677eab55b68465494bffae68a2c38c2321f18ca 100644 (file)
@@ -866,8 +866,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                /* allow mac80211 to determine the timeout */
                wdev->ps_timeout = -1;
 
-               if (!dev->ethtool_ops)
-                       dev->ethtool_ops = &cfg80211_ethtool_ops;
+               netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops);
 
                if ((wdev->iftype == NL80211_IFTYPE_STATION ||
                     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
index 6e5308998e30738377894073acd7b0e824db9687..82c4fc7c994cbe3a0dc89b4a6708f873fcc783d9 100644 (file)
@@ -2365,7 +2365,6 @@ int set_regdom(const struct ieee80211_regdomain *rd)
        return r;
 }
 
-#ifdef CONFIG_HOTPLUG
 int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        if (last_request && !last_request->processed) {
@@ -2377,12 +2376,6 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 
        return 0;
 }
-#else
-int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       return -ENODEV;
-}
-#endif /* CONFIG_HOTPLUG */
 
 void wiphy_regulatory_register(struct wiphy *wiphy)
 {
index 01592d7d4789e389fd565e7cf9fb194dc7ee7bb0..45f1618c8e239c2db21692cfa5358f460918b76d 100644 (file)
@@ -1358,7 +1358,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
                                                  &iwe, IW_EV_UINT_LEN);
        }
 
-       buf = kmalloc(30, GFP_ATOMIC);
+       buf = kmalloc(31, GFP_ATOMIC);
        if (buf) {
                memset(&iwe, 0, sizeof(iwe));
                iwe.cmd = IWEVCUSTOM;
index 9bf6d5e32166c47f315c0c8819a84128b857bc1c..1f6f01e2dc4cb9f0a5528f459b6e6c49dba47cb1 100644 (file)
@@ -77,13 +77,11 @@ static void wiphy_dev_release(struct device *dev)
        cfg80211_dev_free(rdev);
 }
 
-#ifdef CONFIG_HOTPLUG
 static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        /* TODO, we probably need stuff here */
        return 0;
 }
-#endif
 
 static int wiphy_suspend(struct device *dev, pm_message_t state)
 {
@@ -134,9 +132,7 @@ struct class ieee80211_class = {
        .owner = THIS_MODULE,
        .dev_release = wiphy_dev_release,
        .dev_attrs = ieee80211_dev_attrs,
-#ifdef CONFIG_HOTPLUG
        .dev_uevent = wiphy_uevent,
-#endif
        .suspend = wiphy_suspend,
        .resume = wiphy_resume,
        .ns_type = &net_ns_type_operations,
index 41eabc46f110d9cb607cb24f8af68054b91bcccd..07c585756d2a52530dc3fd1f5b14192b1a3c4cd6 100644 (file)
@@ -2656,7 +2656,7 @@ static void xfrm_policy_fini(struct net *net)
                WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
 
                htab = &net->xfrm.policy_bydst[dir];
-               sz = (htab->hmask + 1);
+               sz = (htab->hmask + 1) * sizeof(struct hlist_head);
                WARN_ON(!hlist_empty(htab->table));
                xfrm_hash_free(htab->table, sz);
        }
index 765f6fe951ebc7ed8fabaed3a4dc6ea4299aebfa..35754cc8a9e5b9c51cdaf52693128ee2098718f7 100644 (file)
@@ -242,11 +242,13 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
        u32 diff;
        struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
        u32 seq = ntohl(net_seq);
-       u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+       u32 pos;
 
        if (!replay_esn->replay_window)
                return;
 
+       pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
        if (seq > replay_esn->seq) {
                diff = seq - replay_esn->seq;
 
index 7b6792a18c051a94438493c55513f0c47c4d3483..6181c2cc9ca06221047025771950bfc37eb8ca7e 100644 (file)
@@ -5,12 +5,6 @@ menuconfig SAMPLES
 
 if SAMPLES
 
-config SAMPLE_TRACEPOINTS
-       tristate "Build tracepoints examples -- loadable modules only"
-       depends on TRACEPOINTS && m
-       help
-         This build tracepoints example modules.
-
 config SAMPLE_TRACE_EVENTS
        tristate "Build trace_events examples -- loadable modules only"
        depends on EVENT_TRACING && m
index 5ef08bba96ceaf817adff74aa4969e3bfdf3c37f..1a60c62e20454eeb8961fb9be7f80d2eaabef3fa 100644 (file)
@@ -1,4 +1,4 @@
 # Makefile for Linux samples code
 
-obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ tracepoints/ trace_events/ \
+obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ trace_events/ \
                           hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/
index 23ea9f2ae11dab8040d70884adff6c35d318ca16..59b13440813d59da2f4fd7869e960da29739c3b9 100644 (file)
@@ -64,7 +64,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
        return 0;
 }
 
-static void __devexit rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
 {
        dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
 }
@@ -81,7 +81,7 @@ static struct rpmsg_driver rpmsg_sample_client = {
        .id_table       = rpmsg_driver_sample_id_table,
        .probe          = rpmsg_sample_probe,
        .callback       = rpmsg_sample_cb,
-       .remove         = __devexit_p(rpmsg_sample_remove),
+       .remove         = rpmsg_sample_remove,
 };
 
 static int __init rpmsg_client_sample_init(void)
index bbbd276659ba5edad0e01b915d03639c7980803f..7203e66dcd6f9e035a0710147ec179bab9acabb9 100644 (file)
@@ -19,6 +19,7 @@ bpf-direct-objs := bpf-direct.o
 
 # Try to match the kernel target.
 ifndef CONFIG_64BIT
+ifndef CROSS_COMPILE
 
 # s390 has -m31 flag to build 31 bit binaries
 ifndef CONFIG_S390
@@ -35,6 +36,7 @@ HOSTLOADLIBES_bpf-direct += $(MFLAG)
 HOSTLOADLIBES_bpf-fancy += $(MFLAG)
 HOSTLOADLIBES_dropper += $(MFLAG)
 endif
+endif
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
diff --git a/samples/tracepoints/Makefile b/samples/tracepoints/Makefile
deleted file mode 100644 (file)
index 36479ad..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# builds the tracepoint example kernel modules;
-# then to use one (as root):  insmod <module_name.ko>
-
-obj-$(CONFIG_SAMPLE_TRACEPOINTS) += tracepoint-sample.o
-obj-$(CONFIG_SAMPLE_TRACEPOINTS) += tracepoint-probe-sample.o
-obj-$(CONFIG_SAMPLE_TRACEPOINTS) += tracepoint-probe-sample2.o
diff --git a/samples/tracepoints/tp-samples-trace.h b/samples/tracepoints/tp-samples-trace.h
deleted file mode 100644 (file)
index 4d46be9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _TP_SAMPLES_TRACE_H
-#define _TP_SAMPLES_TRACE_H
-
-#include <linux/proc_fs.h>     /* for struct inode and struct file */
-#include <linux/tracepoint.h>
-
-DECLARE_TRACE(subsys_event,
-       TP_PROTO(struct inode *inode, struct file *file),
-       TP_ARGS(inode, file));
-DECLARE_TRACE_NOARGS(subsys_eventb);
-#endif
diff --git a/samples/tracepoints/tracepoint-probe-sample.c b/samples/tracepoints/tracepoint-probe-sample.c
deleted file mode 100644 (file)
index 744c0b9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * tracepoint-probe-sample.c
- *
- * sample tracepoint probes.
- */
-
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/dcache.h>
-#include "tp-samples-trace.h"
-
-/*
- * Here the caller only guarantees locking for struct file and struct inode.
- * Locking must therefore be done in the probe to use the dentry.
- */
-static void probe_subsys_event(void *ignore,
-                              struct inode *inode, struct file *file)
-{
-       path_get(&file->f_path);
-       dget(file->f_path.dentry);
-       printk(KERN_INFO "Event is encountered with filename %s\n",
-               file->f_path.dentry->d_name.name);
-       dput(file->f_path.dentry);
-       path_put(&file->f_path);
-}
-
-static void probe_subsys_eventb(void *ignore)
-{
-       printk(KERN_INFO "Event B is encountered\n");
-}
-
-static int __init tp_sample_trace_init(void)
-{
-       int ret;
-
-       ret = register_trace_subsys_event(probe_subsys_event, NULL);
-       WARN_ON(ret);
-       ret = register_trace_subsys_eventb(probe_subsys_eventb, NULL);
-       WARN_ON(ret);
-
-       return 0;
-}
-
-module_init(tp_sample_trace_init);
-
-static void __exit tp_sample_trace_exit(void)
-{
-       unregister_trace_subsys_eventb(probe_subsys_eventb, NULL);
-       unregister_trace_subsys_event(probe_subsys_event, NULL);
-       tracepoint_synchronize_unregister();
-}
-
-module_exit(tp_sample_trace_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("Tracepoint Probes Samples");
diff --git a/samples/tracepoints/tracepoint-probe-sample2.c b/samples/tracepoints/tracepoint-probe-sample2.c
deleted file mode 100644 (file)
index 9fcf990..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * tracepoint-probe-sample2.c
- *
- * 2nd sample tracepoint probes.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include "tp-samples-trace.h"
-
-/*
- * Here the caller only guarantees locking for struct file and struct inode.
- * Locking must therefore be done in the probe to use the dentry.
- */
-static void probe_subsys_event(void *ignore,
-                              struct inode *inode, struct file *file)
-{
-       printk(KERN_INFO "Event is encountered with inode number %lu\n",
-               inode->i_ino);
-}
-
-static int __init tp_sample_trace_init(void)
-{
-       int ret;
-
-       ret = register_trace_subsys_event(probe_subsys_event, NULL);
-       WARN_ON(ret);
-
-       return 0;
-}
-
-module_init(tp_sample_trace_init);
-
-static void __exit tp_sample_trace_exit(void)
-{
-       unregister_trace_subsys_event(probe_subsys_event, NULL);
-       tracepoint_synchronize_unregister();
-}
-
-module_exit(tp_sample_trace_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("Tracepoint Probes Samples");
diff --git a/samples/tracepoints/tracepoint-sample.c b/samples/tracepoints/tracepoint-sample.c
deleted file mode 100644 (file)
index f4d89e0..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* tracepoint-sample.c
- *
- * Executes a tracepoint when /proc/tracepoint-sample is opened.
- *
- * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
- *
- * This file is released under the GPLv2.
- * See the file COPYING for more details.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include "tp-samples-trace.h"
-
-DEFINE_TRACE(subsys_event);
-DEFINE_TRACE(subsys_eventb);
-
-struct proc_dir_entry *pentry_sample;
-
-static int my_open(struct inode *inode, struct file *file)
-{
-       int i;
-
-       trace_subsys_event(inode, file);
-       for (i = 0; i < 10; i++)
-               trace_subsys_eventb();
-       return -EPERM;
-}
-
-static const struct file_operations mark_ops = {
-       .open = my_open,
-       .llseek = noop_llseek,
-};
-
-static int __init sample_init(void)
-{
-       printk(KERN_ALERT "sample init\n");
-       pentry_sample = proc_create("tracepoint-sample", 0444, NULL,
-               &mark_ops);
-       if (!pentry_sample)
-               return -EPERM;
-       return 0;
-}
-
-static void __exit sample_exit(void)
-{
-       printk(KERN_ALERT "sample exit\n");
-       remove_proc_entry("tracepoint-sample", NULL);
-}
-
-module_init(sample_init)
-module_exit(sample_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("Tracepoint sample");
index 1d6e4c541370c832840f540399d5f7627488399c..2bb08a962ce3168a7fe1c01d3f397349e0143bc5 100755 (executable)
@@ -230,12 +230,12 @@ our $Inline       = qr{inline|__always_inline|noinline};
 our $Member    = qr{->$Ident|\.$Ident|\[[^]]*\]};
 our $Lval      = qr{$Ident(?:$Member)*};
 
-our $Float_hex = qr{(?i:0x[0-9a-f]+p-?[0-9]+[fl]?)};
-our $Float_dec = qr{(?i:((?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?))};
-our $Float_int = qr{(?i:[0-9]+e-?[0-9]+[fl]?)};
+our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
+our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
+our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
 our $Float     = qr{$Float_hex|$Float_dec|$Float_int};
-our $Constant  = qr{(?:$Float|(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*))};
-our $Assignment        = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
+our $Constant  = qr{$Float|(?i)(?:0x[0-9a-f]+|[0-9]+)[ul]*};
+our $Assignment        = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
 our $Compare    = qr{<=|>=|==|!=|<|>};
 our $Operators = qr{
                        <=|>=|==|!=|
@@ -2226,8 +2226,11 @@ sub process {
                        my $path = $1;
                        if ($path =~ m{//}) {
                                ERROR("MALFORMED_INCLUDE",
-                                     "malformed #include filename\n" .
-                                       $herecurr);
+                                     "malformed #include filename\n" . $herecurr);
+                       }
+                       if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
+                               ERROR("UAPI_INCLUDE",
+                                     "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
                        }
                }
 
diff --git a/scripts/coccinelle/misc/warn.cocci b/scripts/coccinelle/misc/warn.cocci
new file mode 100644 (file)
index 0000000..fda8c35
--- /dev/null
@@ -0,0 +1,109 @@
+/// Use WARN(1,...) rather than printk followed by WARN_ON(1)
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@bad1@
+position p;
+@@
+
+printk(...);
+printk@p(...);
+WARN_ON(1);
+
+@r1 depends on context || report || org@
+position p != bad1.p;
+@@
+
+ printk@p(...);
+*WARN_ON(1);
+
+@script:python depends on org@
+p << r1.p;
+@@
+
+cocci.print_main("printk + WARN_ON can be just WARN",p)
+
+@script:python depends on report@
+p << r1.p;
+@@
+
+msg = "SUGGESTION: printk + WARN_ON can be just WARN"
+coccilib.report.print_report(p[0],msg)
+
+@ok1 depends on patch@
+expression list es;
+position p != bad1.p;
+@@
+
+-printk@p(
++WARN(1,
+  es);
+-WARN_ON(1);
+
+@depends on patch@
+expression list ok1.es;
+@@
+
+if (...)
+- {
+  WARN(1,es);
+- }
+
+// --------------------------------------------------------------------
+
+@bad2@
+position p;
+@@
+
+printk(...);
+printk@p(...);
+WARN_ON_ONCE(1);
+
+@r2 depends on context || report || org@
+position p != bad1.p;
+@@
+
+ printk@p(...);
+*WARN_ON_ONCE(1);
+
+@script:python depends on org@
+p << r2.p;
+@@
+
+cocci.print_main("printk + WARN_ON_ONCE can be just WARN_ONCE",p)
+
+@script:python depends on report@
+p << r2.p;
+@@
+
+msg = "SUGGESTION: printk + WARN_ON_ONCE can be just WARN_ONCE"
+coccilib.report.print_report(p[0],msg)
+
+@ok2 depends on patch@
+expression list es;
+position p != bad2.p;
+@@
+
+-printk@p(
++WARN_ONCE(1,
+  es);
+-WARN_ON_ONCE(1);
+
+@depends on patch@
+expression list ok2.es;
+@@
+
+if (...)
+- {
+  WARN_ONCE(1,es);
+- }
index ee355394f4ef76eeb6d6f74dac00729d8cc942e3..bb4d3deb6d1c0add7815115a14a574212c0f3d90 100755 (executable)
@@ -101,7 +101,6 @@ while [ "$1" != "" ] ; do
        case "$CMD" in
        --keep-case|-k)
                MUNGE_CASE=no
-               shift
                continue
                ;;
        --refresh)
index 6c353ae8a4517b1e7ab4b2b4fa28012e96de9921..581ca99c96f29829507c6b43fdd278781fc3b2a9 100644 (file)
@@ -42,9 +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 /* !;
+               $line =~ s/#ifndef\s+_UAPI/#ifndef /;
+               $line =~ s/#define\s+_UAPI/#define /;
+               $line =~ s!#endif\s+/[*]\s*_UAPI!#endif /* !;
                printf {$out} "%s", $line;
        }
        close $out;
index 28b7615678154180c16d950252dea460c2e8e29e..f565536a2bef17a8f6b88193d0b2db01e12dd716 100755 (executable)
@@ -2079,7 +2079,6 @@ sub dump_function($$) {
     $prototype =~ s/^__inline +//;
     $prototype =~ s/^__always_inline +//;
     $prototype =~ s/^noinline +//;
-    $prototype =~ s/__devinit +//;
     $prototype =~ s/__init +//;
     $prototype =~ s/__init_or_module +//;
     $prototype =~ s/__must_check +//;
index 5c113123ed9f208840d5af7283e6df4769a4bc12..68bb4efc5af429a2f5d1ec359a06d3f2e7af8bb4 100644 (file)
@@ -74,6 +74,7 @@ static unsigned int logo_height;
 static struct color **logo_data;
 static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
 static unsigned int logo_clutsize;
+static int is_plain_pbm = 0;
 
 static void die(const char *fmt, ...)
     __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
@@ -103,6 +104,11 @@ static unsigned int get_number(FILE *fp)
     val = 0;
     while (isdigit(c)) {
        val = 10*val+c-'0';
+       /* some PBM are 'broken'; GiMP for example exports a PBM without space
+        * between the digits. This is Ok cause we know a PBM can only have a '1'
+        * or a '0' for the digit. */
+       if (is_plain_pbm)
+               break;
        c = fgetc(fp);
        if (c == EOF)
            die("%s: end of file\n", filename);
@@ -167,6 +173,7 @@ static void read_image(void)
     switch (magic) {
        case '1':
            /* Plain PBM */
+           is_plain_pbm = 1;
            for (i = 0; i < logo_height; i++)
                for (j = 0; j < logo_width; j++)
                    logo_data[i][j].red = logo_data[i][j].green =
index 79fdafb0d26325acb65d8e2b31f814770b826a07..08f06c00745e408d967e7e42121ec00ae016d90a 100755 (executable)
@@ -48,13 +48,14 @@ find_arch_sources()
        for i in $archincludedir; do
                prune="$prune -wholename $i -prune -o"
        done
-       find ${tree}arch/$1 $ignore $prune -name "$2" -print;
+       find ${tree}arch/$1 $ignore $subarchprune $prune -name "$2" -print;
 }
 
 # find sources in arch/$1/include
 find_arch_include_sources()
 {
-       include=$(find ${tree}arch/$1/ -name include -type d);
+       include=$(find ${tree}arch/$1/ $subarchprune \
+                                       -name include -type d -print);
        if [ -n "$include" ]; then
                archincludedir="$archincludedir $include"
                find $include $ignore -name "$2" -print;
@@ -95,6 +96,32 @@ all_sources()
        find_other_sources '*.[chS]'
 }
 
+all_compiled_sources()
+{
+       for i in $(all_sources); do
+               case "$i" in
+                       *.[cS])
+                               j=${i/\.[cS]/\.o}
+                               if [ -e $j ]; then
+                                       echo $i
+                               fi
+                               ;;
+                       *)
+                               echo $i
+                               ;;
+               esac
+       done
+}
+
+all_target_sources()
+{
+       if [ -n "$COMPILED_SOURCE" ]; then
+               all_compiled_sources
+       else
+               all_sources
+       fi
+}
+
 all_kconfigs()
 {
        for arch in $ALLSOURCE_ARCHS; do
@@ -110,18 +137,18 @@ all_defconfigs()
 
 docscope()
 {
-       (echo \-k; echo \-q; all_sources) > cscope.files
+       (echo \-k; echo \-q; all_target_sources) > cscope.files
        cscope -b -f cscope.out
 }
 
 dogtags()
 {
-       all_sources | gtags -i -f -
+       all_target_sources | gtags -i -f -
 }
 
 exuberant()
 {
-       all_sources | xargs $1 -a                               \
+       all_target_sources | xargs $1 -a                        \
        -I __initdata,__exitdata,__acquires,__releases          \
        -I __read_mostly,____cacheline_aligned                  \
        -I ____cacheline_aligned_in_smp                         \
@@ -173,7 +200,7 @@ exuberant()
 
 emacs()
 {
-       all_sources | xargs $1 -a                               \
+       all_target_sources | xargs $1 -a                        \
        --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/'            \
        --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/'   \
        --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/'          \
@@ -220,11 +247,10 @@ xtags()
        elif $1 --version 2>&1 | grep -iq emacs; then
                emacs $1
        else
-               all_sources | xargs $1 -a
+               all_target_sources | xargs $1 -a
         fi
 }
 
-
 # Support um (which uses SUBARCH)
 if [ "${ARCH}" = "um" ]; then
        if [ "$SUBARCH" = "i386" ]; then
@@ -234,6 +260,21 @@ if [ "${ARCH}" = "um" ]; then
        else
                archinclude=${SUBARCH}
        fi
+elif [ "${SRCARCH}" = "arm" -a "${SUBARCH}" != "" ]; then
+       subarchdir=$(find ${tree}arch/$SRCARCH/ -name "mach-*" -type d -o \
+                                                       -name "plat-*" -type d);
+       for i in $subarchdir; do
+               case "$i" in
+                       *"mach-"${SUBARCH})
+                               ;;
+                       *"plat-"${SUBARCH})
+                               ;;
+                       *)
+                               subarchprune="$subarchprune \
+                                               -wholename $i -prune -o"
+                               ;;
+               esac
+       done
 fi
 
 remove_structs=
index 0fe5a026aef8d22ac83619dd0bbc2ba50965b63e..579775088967fdb11a044beb75c70de48d572ad6 100644 (file)
@@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req,
 {
 }
 
+static int cap_tun_dev_alloc_security(void **security)
+{
+       return 0;
+}
+
+static void cap_tun_dev_free_security(void *security)
+{
+}
+
 static int cap_tun_dev_create(void)
 {
        return 0;
 }
 
-static void cap_tun_dev_post_create(struct sock *sk)
+static int cap_tun_dev_attach_queue(void *security)
+{
+       return 0;
+}
+
+static int cap_tun_dev_attach(struct sock *sk, void *security)
 {
+       return 0;
 }
 
-static int cap_tun_dev_attach(struct sock *sk)
+static int cap_tun_dev_open(void *security)
 {
        return 0;
 }
@@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops)
        set_to_cap_if_null(ops, secmark_refcount_inc);
        set_to_cap_if_null(ops, secmark_refcount_dec);
        set_to_cap_if_null(ops, req_classify_flow);
+       set_to_cap_if_null(ops, tun_dev_alloc_security);
+       set_to_cap_if_null(ops, tun_dev_free_security);
        set_to_cap_if_null(ops, tun_dev_create);
-       set_to_cap_if_null(ops, tun_dev_post_create);
+       set_to_cap_if_null(ops, tun_dev_open);
+       set_to_cap_if_null(ops, tun_dev_attach_queue);
        set_to_cap_if_null(ops, tun_dev_attach);
 #endif /* CONFIG_SECURITY_NETWORK */
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
index 19ecc8de9e6bfd837e2589546fdfe49b04b23ed0..d794abcc4b3b7e5e87173ba8ca45deca5b6d09d8 100644 (file)
@@ -215,7 +215,9 @@ static void devcgroup_css_free(struct cgroup *cgroup)
        struct dev_cgroup *dev_cgroup;
 
        dev_cgroup = cgroup_to_devcgroup(cgroup);
+       mutex_lock(&devcgroup_mutex);
        dev_exception_clean(dev_cgroup);
+       mutex_unlock(&devcgroup_mutex);
        kfree(dev_cgroup);
 }
 
index dfb26918699c5be5cffcfe4f37295914561096d4..7dd538ef5b8319e645465eb62294158f3dbe271a 100644 (file)
@@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
                rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
                                           &xattr_data,
                                           sizeof(xattr_data), 0);
-       }
-       else if (rc == -ENODATA)
+       } else if (rc == -ENODATA && inode->i_op->removexattr) {
                rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+       }
        return rc;
 }
 
index 3b2adb794f15506311a52b2ec5442297907ee8e2..079a85dc37b2ba9fd7d649a1a0da0e2843a9252c 100644 (file)
@@ -139,6 +139,7 @@ void ima_delete_rules(void);
 /* Appraise integrity measurements */
 #define IMA_APPRAISE_ENFORCE   0x01
 #define IMA_APPRAISE_FIX       0x02
+#define IMA_APPRAISE_MODULES   0x04
 
 #ifdef CONFIG_IMA_APPRAISE
 int ima_appraise_measurement(struct integrity_iint_cache *iint,
index 45de18e9a6f224aac3b90512fb1e4b6453b795be..dba965de90d3f838c82e1a93202bf585fa1e5cd6 100644 (file)
@@ -291,11 +291,15 @@ EXPORT_SYMBOL_GPL(ima_file_check);
  */
 int ima_module_check(struct file *file)
 {
-       int rc;
+       int rc = 0;
 
-       if (!file)
-               rc = INTEGRITY_UNKNOWN;
-       else
+       if (!file) {
+               if (ima_appraise & IMA_APPRAISE_MODULES) {
+#ifndef CONFIG_MODULE_SIG_FORCE
+                       rc = -EACCES;   /* INTEGRITY_UNKNOWN */
+#endif
+               }
+       } else
                rc = process_measurement(file, file->f_dentry->d_name.name,
                                         MAY_EXEC, MODULE_CHECK);
        return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
index af7d182d5a46123ca9308cf2e231f006aa71215d..479fca940bb5552df6591723f09408c3325054f0 100644 (file)
@@ -523,7 +523,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
        }
        if (!result && (entry->action == UNKNOWN))
                result = -EINVAL;
-
+       else if (entry->func == MODULE_CHECK)
+               ima_appraise |= IMA_APPRAISE_MODULES;
        audit_log_format(ab, "res=%d", !result);
        audit_log_end(ab);
        return result;
index 58dfe089094793030f56fdb895f6621e403e4157..20e4bf57aec8b6418bf4d4df86c616903121c28c 100644 (file)
@@ -367,8 +367,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
 
                switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
-                       if (ret)
-                               break;
                case -ENOKEY: /* negative key */
                        ret = key_ref;
                        break;
index daa97f4ac9d13515909028bf1ffa6903d8aed0c7..7b88c6aeaed43e5f37b449fd8ec87610b3b69a93 100644 (file)
@@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void)
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);
 
+int security_tun_dev_alloc_security(void **security)
+{
+       return security_ops->tun_dev_alloc_security(security);
+}
+EXPORT_SYMBOL(security_tun_dev_alloc_security);
+
+void security_tun_dev_free_security(void *security)
+{
+       security_ops->tun_dev_free_security(security);
+}
+EXPORT_SYMBOL(security_tun_dev_free_security);
+
 int security_tun_dev_create(void)
 {
        return security_ops->tun_dev_create();
 }
 EXPORT_SYMBOL(security_tun_dev_create);
 
-void security_tun_dev_post_create(struct sock *sk)
+int security_tun_dev_attach_queue(void *security)
 {
-       return security_ops->tun_dev_post_create(sk);
+       return security_ops->tun_dev_attach_queue(security);
 }
-EXPORT_SYMBOL(security_tun_dev_post_create);
+EXPORT_SYMBOL(security_tun_dev_attach_queue);
 
-int security_tun_dev_attach(struct sock *sk)
+int security_tun_dev_attach(struct sock *sk, void *security)
 {
-       return security_ops->tun_dev_attach(sk);
+       return security_ops->tun_dev_attach(sk, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach);
 
+int security_tun_dev_open(void *security)
+{
+       return security_ops->tun_dev_open(security);
+}
+EXPORT_SYMBOL(security_tun_dev_open);
+
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
index 61a53367d0292600fbb2d11da95c21118164fca4..ef26e9611ffbab91ad50faefa81a56a425cefb93 100644 (file)
@@ -4399,6 +4399,24 @@ static void selinux_req_classify_flow(const struct request_sock *req,
        fl->flowi_secid = req->secid;
 }
 
+static int selinux_tun_dev_alloc_security(void **security)
+{
+       struct tun_security_struct *tunsec;
+
+       tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
+       if (!tunsec)
+               return -ENOMEM;
+       tunsec->sid = current_sid();
+
+       *security = tunsec;
+       return 0;
+}
+
+static void selinux_tun_dev_free_security(void *security)
+{
+       kfree(security);
+}
+
 static int selinux_tun_dev_create(void)
 {
        u32 sid = current_sid();
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)
                            NULL);
 }
 
-static void selinux_tun_dev_post_create(struct sock *sk)
+static int selinux_tun_dev_attach_queue(void *security)
 {
+       struct tun_security_struct *tunsec = security;
+
+       return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
+                           TUN_SOCKET__ATTACH_QUEUE, NULL);
+}
+
+static int selinux_tun_dev_attach(struct sock *sk, void *security)
+{
+       struct tun_security_struct *tunsec = security;
        struct sk_security_struct *sksec = sk->sk_security;
 
        /* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)
         * cause confusion to the TUN user that had no idea network labeling
         * protocols were being used */
 
-       /* see the comments in selinux_tun_dev_create() about why we don't use
-        * the sockcreate SID here */
-
-       sksec->sid = current_sid();
+       sksec->sid = tunsec->sid;
        sksec->sclass = SECCLASS_TUN_SOCKET;
+
+       return 0;
 }
 
-static int selinux_tun_dev_attach(struct sock *sk)
+static int selinux_tun_dev_open(void *security)
 {
-       struct sk_security_struct *sksec = sk->sk_security;
+       struct tun_security_struct *tunsec = security;
        u32 sid = current_sid();
        int err;
 
-       err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
+       err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
                           TUN_SOCKET__RELABELFROM, NULL);
        if (err)
                return err;
@@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk)
                           TUN_SOCKET__RELABELTO, NULL);
        if (err)
                return err;
-
-       sksec->sid = sid;
+       tunsec->sid = sid;
 
        return 0;
 }
@@ -5642,9 +5667,12 @@ static struct security_operations selinux_ops = {
        .secmark_refcount_inc =         selinux_secmark_refcount_inc,
        .secmark_refcount_dec =         selinux_secmark_refcount_dec,
        .req_classify_flow =            selinux_req_classify_flow,
+       .tun_dev_alloc_security =       selinux_tun_dev_alloc_security,
+       .tun_dev_free_security =        selinux_tun_dev_free_security,
        .tun_dev_create =               selinux_tun_dev_create,
-       .tun_dev_post_create =          selinux_tun_dev_post_create,
+       .tun_dev_attach_queue =         selinux_tun_dev_attach_queue,
        .tun_dev_attach =               selinux_tun_dev_attach,
+       .tun_dev_open =                 selinux_tun_dev_open,
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
        .xfrm_policy_alloc_security =   selinux_xfrm_policy_alloc,
index df2de54a958debfab56caf3483cd5d93856e5be4..14d04e63b1f0e09ef15b4cf64057bd7cc861ed1d 100644 (file)
@@ -150,6 +150,6 @@ struct security_class_mapping secclass_map[] = {
            NULL } },
        { "kernel_service", { "use_as_override", "create_files_as", NULL } },
        { "tun_socket",
-         { COMMON_SOCK_PERMS, NULL } },
+         { COMMON_SOCK_PERMS, "attach_queue", NULL } },
        { NULL }
   };
index 26c7eee1c309b0a2f45a23c8b70d2157841c1670..aa47bcabb5f65e728aadbaa39cdecfa55d20aa16 100644 (file)
@@ -110,6 +110,10 @@ struct sk_security_struct {
        u16 sclass;                     /* sock security class */
 };
 
+struct tun_security_struct {
+       u32 sid;                        /* SID for the tun device sockets */
+};
+
 struct key_security_struct {
        u32 sid;        /* SID of key */
 };
index 6fc0ae90e5b1de99992b288d35035e2a0d061df2..fff7753e35c15ba6f82612594fbda19e7203b66e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <sound/ac97_codec.h>
 #include <sound/pxa2xx-lib.h>
@@ -148,6 +149,8 @@ static inline void pxa_ac97_warm_pxa27x(void)
 
 static inline void pxa_ac97_cold_pxa27x(void)
 {
+       unsigned int timeout;
+
        GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
        GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -157,8 +160,10 @@ static inline void pxa_ac97_cold_pxa27x(void)
        clk_enable(ac97conf_clk);
        udelay(5);
        clk_disable(ac97conf_clk);
-       GCR = GCR_COLD_RST;
-       udelay(50);
+       GCR = GCR_COLD_RST | GCR_WARM_RST;
+       timeout = 100;     /* wait for the codec-ready bit to be set */
+       while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+               mdelay(1);
 }
 #endif
 
@@ -340,8 +345,21 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
        }
 
        if (cpu_is_pxa27x()) {
-               /* Use GPIO 113 as AC97 Reset on Bulverde */
+               /*
+                * This gpio is needed for a work-around to a bug in the ac97
+                * controller during warm reset.  The direction and level is set
+                * here so that it is an output driven high when switching from
+                * AC97_nRESET alt function to generic gpio.
+                */
+               ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,
+                                      "pxa27x ac97 reset");
+               if (ret < 0) {
+                       pr_err("%s: gpio_request_one() failed: %d\n",
+                              __func__, ret);
+                       goto err_conf;
+               }
                pxa27x_assert_ac97reset(reset_gpio, 0);
+
                ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
                if (IS_ERR(ac97conf_clk)) {
                        ret = PTR_ERR(ac97conf_clk);
@@ -384,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
 
 void pxa2xx_ac97_hw_remove(struct platform_device *dev)
 {
+       if (cpu_is_pxa27x())
+               gpio_free(reset_gpio);
        GCR |= GCR_ACLINK_OFF;
        free_irq(IRQ_AC97, NULL);
        if (ac97conf_clk) {
index dabf8a871dcc26b75166712e3ee109136f7babd6..7004e24d209f167c196e231ffc1f883033eb8d54 100644 (file)
@@ -333,6 +333,11 @@ static void __init attach_pas_card(struct address_info *hw_config)
                {
                        char            temp[100];
 
+                       if (pas_model < 0 ||
+                           pas_model >= ARRAY_SIZE(pas_model_names)) {
+                               printk(KERN_ERR "pas2 unrecognized model.\n");
+                               return;
+                       }
                        sprintf(temp,
                            "%s rev %d", pas_model_names[(int) pas_model],
                                    pas_read(0x2789));
index 2805e34bd41d715a44c3ba645165a71295260095..8bef47311e45025aeeb6552054c50dd520a8ad9d 100644 (file)
@@ -58,7 +58,7 @@ static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en)
        if (en)
                temp |= (1 << (wt & 0x1f));
        else
-               temp &= (1 << ~(wt & 0x1f));
+               temp &= ~(1 << (wt & 0x1f));
        hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp);
 }
 
index 8353c77536ac51c0e9ed13ff6fb94732c9e80469..822df971972c1ff54ea7886a3524356ff92fca50 100644 (file)
@@ -2531,7 +2531,7 @@ static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_info *uinfo)
 {
        static const char * const texts[] = {
-               "Off", "On", "Follow Master"
+               "On", "Off", "Follow Master"
        };
        unsigned int index;
 
@@ -3654,6 +3654,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        hda_set_power_state(codec, AC_PWRST_D0);
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
+       snd_hda_jack_set_dirty_all(codec);
        if (codec->patch_ops.resume)
                codec->patch_ops.resume(codec);
        else {
@@ -3665,10 +3666,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
 
        if (codec->jackpoll_interval)
                hda_jackpoll_work(&codec->jackpoll_work.work);
-       else {
-               snd_hda_jack_set_dirty_all(codec);
+       else
                snd_hda_jack_report_sync(codec);
-       }
 
        codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
index cca87277baf088b273279c6b1621aa52a981a47e..c78286f6e5d8133e070d34e3927a12c70be626f1 100644 (file)
@@ -573,9 +573,12 @@ enum {
 #define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
 
 /* quirks for Intel PCH */
-#define AZX_DCAPS_INTEL_PCH \
+#define AZX_DCAPS_INTEL_PCH_NOPM \
        (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
-        AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
+        AZX_DCAPS_COUNT_LPIB_DELAY)
+
+#define AZX_DCAPS_INTEL_PCH \
+       (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -653,29 +656,43 @@ static char *driver_short_names[] = {
 #define get_azx_dev(substream) (substream->runtime->private_data)
 
 #ifdef CONFIG_X86
-static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on)
+static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 {
+       int pages;
+
        if (azx_snoop(chip))
                return;
-       if (addr && size) {
-               int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       if (!dmab || !dmab->area || !dmab->bytes)
+               return;
+
+#ifdef CONFIG_SND_DMA_SGBUF
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
+               struct snd_sg_buf *sgbuf = dmab->private_data;
                if (on)
-                       set_memory_wc((unsigned long)addr, pages);
+                       set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
                else
-                       set_memory_wb((unsigned long)addr, pages);
+                       set_pages_array_wb(sgbuf->page_table, sgbuf->pages);
+               return;
        }
+#endif
+
+       pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       if (on)
+               set_memory_wc((unsigned long)dmab->area, pages);
+       else
+               set_memory_wb((unsigned long)dmab->area, pages);
 }
 
 static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
                                 bool on)
 {
-       __mark_pages_wc(chip, buf->area, buf->bytes, on);
+       __mark_pages_wc(chip, buf, on);
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-                                  struct snd_pcm_runtime *runtime, bool on)
+                                  struct snd_pcm_substream *substream, bool on)
 {
        if (azx_dev->wc_marked != on) {
-               __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on);
+               __mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on);
                azx_dev->wc_marked = on;
        }
 }
@@ -686,7 +703,7 @@ static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
 {
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-                                  struct snd_pcm_runtime *runtime, bool on)
+                                  struct snd_pcm_substream *substream, bool on)
 {
 }
 #endif
@@ -1965,11 +1982,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
        struct azx *chip = apcm->chip;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct azx_dev *azx_dev = get_azx_dev(substream);
        int ret;
 
-       mark_runtime_wc(chip, azx_dev, runtime, false);
+       mark_runtime_wc(chip, azx_dev, substream, false);
        azx_dev->bufsize = 0;
        azx_dev->period_bytes = 0;
        azx_dev->format_val = 0;
@@ -1977,7 +1993,7 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
                                        params_buffer_bytes(hw_params));
        if (ret < 0)
                return ret;
-       mark_runtime_wc(chip, azx_dev, runtime, true);
+       mark_runtime_wc(chip, azx_dev, substream, true);
        return ret;
 }
 
@@ -1986,7 +2002,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
        struct azx_dev *azx_dev = get_azx_dev(substream);
        struct azx *chip = apcm->chip;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
 
        /* reset BDL address */
@@ -1999,7 +2014,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
 
        snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
-       mark_runtime_wc(chip, azx_dev, runtime, false);
+       mark_runtime_wc(chip, azx_dev, substream, false);
        return snd_pcm_lib_free_pages(substream);
 }
 
@@ -3586,13 +3601,13 @@ static void 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_INTEL_PCH },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@@ -3610,13 +3625,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
-       /* SCH */
+       /* Poulsbo */
        { PCI_DEVICE(0x8086, 0x811b),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+       /* Oaktrail */
        { PCI_DEVICE(0x8086, 0x080a),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* ICH */
        { PCI_DEVICE(0x8086, 0x2668),
          .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
index 60890bfecc196600ffa15ab5979c06aef8891f9b..009b77a693cf3326a3cdec7b6fa335a4c51c80be 100644 (file)
@@ -558,24 +558,12 @@ static int conexant_build_controls(struct hda_codec *codec)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int conexant_suspend(struct hda_codec *codec)
-{
-       snd_hda_shutup_pins(codec);
-       return 0;
-}
-#endif
-
 static const struct hda_codec_ops conexant_patch_ops = {
        .build_controls = conexant_build_controls,
        .build_pcms = conexant_build_pcms,
        .init = conexant_init,
        .free = conexant_free,
        .set_power_state = conexant_set_power,
-#ifdef CONFIG_PM
-       .suspend = conexant_suspend,
-#endif
-       .reboot_notify = snd_hda_shutup_pins,
 };
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -4405,10 +4393,6 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
        .init = cx_auto_init,
        .free = conexant_free,
        .unsol_event = snd_hda_jack_unsol_event,
-#ifdef CONFIG_PM
-       .suspend = conexant_suspend,
-#endif
-       .reboot_notify = snd_hda_shutup_pins,
 };
 
 /*
@@ -4652,6 +4636,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = {
          .patch = patch_conexant_auto },
        { .id = 0x14f15111, .name = "CX20753/4",
          .patch = patch_conexant_auto },
+       { .id = 0x14f15113, .name = "CX20755",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f15114, .name = "CX20756",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f15115, .name = "CX20757",
+         .patch = patch_conexant_auto },
        {} /* terminator */
 };
 
@@ -4675,6 +4665,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150b9");
 MODULE_ALIAS("snd-hda-codec-id:14f1510f");
 MODULE_ALIAS("snd-hda-codec-id:14f15110");
 MODULE_ALIAS("snd-hda-codec-id:14f15111");
+MODULE_ALIAS("snd-hda-codec-id:14f15113");
+MODULE_ALIAS("snd-hda-codec-id:14f15114");
+MODULE_ALIAS("snd-hda-codec-id:14f15115");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Conexant HD-audio codec");
index b6c21ea187ca00df7233416f516111567b6b9ca7..807a2aa1ff384e5a54f64a6f951f8d8e44e3061b 100644 (file)
@@ -1502,7 +1502,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
        ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
        substream = snd_pcm_chmap_substream(info, ctl_idx);
        if (!substream || !substream->runtime)
-               return -EBADFD;
+               return 0; /* just for avoiding error from alsactl restore */
        switch (substream->runtime->status->state) {
        case SNDRV_PCM_STATE_OPEN:
        case SNDRV_PCM_STATE_SETUP:
index 6ee34593774a4d155cd595ab96bbc7318f2dc6d9..5faaad219a7f37e588e8b5a27b298cbb7adfa69d 100644 (file)
@@ -4694,6 +4694,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
        SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
        SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+       SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST),
        SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
        SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
        SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
@@ -5708,6 +5709,7 @@ static const struct alc_model_fixup alc268_fixup_models[] = {
 };
 
 static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
        /* below is codec SSID since multiple Toshiba laptops have the
         * same PCI SSID 1179:ff00
         */
@@ -5817,6 +5819,9 @@ enum {
        ALC269_TYPE_ALC269VB,
        ALC269_TYPE_ALC269VC,
        ALC269_TYPE_ALC269VD,
+       ALC269_TYPE_ALC280,
+       ALC269_TYPE_ALC282,
+       ALC269_TYPE_ALC284,
 };
 
 /*
@@ -5833,10 +5838,13 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        switch (spec->codec_variant) {
        case ALC269_TYPE_ALC269VA:
        case ALC269_TYPE_ALC269VC:
+       case ALC269_TYPE_ALC280:
+       case ALC269_TYPE_ALC284:
                ssids = alc269va_ssids;
                break;
        case ALC269_TYPE_ALC269VB:
        case ALC269_TYPE_ALC269VD:
+       case ALC269_TYPE_ALC282:
                ssids = alc269_ssids;
                break;
        default:
@@ -5992,6 +6000,30 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec,
        spec->automute_hook = alc269_quanta_automute;
 }
 
+/* update mute-LED according to the speaker mute state via mic1 VREF pin */
+static void alc269_fixup_mic1_mute_hook(void *private_data, int enabled)
+{
+       struct hda_codec *codec = private_data;
+       unsigned int pinval = AC_PINCTL_IN_EN + (enabled ?
+                             AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80);
+       snd_hda_set_pin_ctl_cache(codec, 0x18, pinval);
+}
+
+static void alc269_fixup_mic1_mute(struct hda_codec *codec,
+                                  const struct alc_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       switch (action) {
+       case ALC_FIXUP_ACT_BUILD:
+               spec->vmaster_mute.hook = alc269_fixup_mic1_mute_hook;
+               snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
+               /* fallthru */
+       case ALC_FIXUP_ACT_INIT:
+               snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+               break;
+       }
+}
+
 /* update mute-LED according to the speaker mute state via mic2 VREF pin */
 static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
 {
@@ -6043,6 +6075,7 @@ enum {
        ALC269_FIXUP_DMIC,
        ALC269VB_FIXUP_AMIC,
        ALC269VB_FIXUP_DMIC,
+       ALC269_FIXUP_MIC1_MUTE_LED,
        ALC269_FIXUP_MIC2_MUTE_LED,
        ALC269_FIXUP_INV_DMIC,
        ALC269_FIXUP_LENOVO_DOCK,
@@ -6171,6 +6204,10 @@ static const struct alc_fixup alc269_fixups[] = {
                        { }
                },
        },
+       [ALC269_FIXUP_MIC1_MUTE_LED] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc269_fixup_mic1_mute,
+       },
        [ALC269_FIXUP_MIC2_MUTE_LED] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc269_fixup_mic2_mute,
@@ -6215,6 +6252,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x1972, "HP Pavilion 17", ALC269_FIXUP_MIC1_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x1977, "HP Pavilion 14", ALC269_FIXUP_MIC1_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -6229,6 +6268,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
@@ -6370,7 +6410,8 @@ static int patch_alc269(struct hda_codec *codec)
 
        alc_auto_parse_customize_define(codec);
 
-       if (codec->vendor_id == 0x10ec0269) {
+       switch (codec->vendor_id) {
+       case 0x10ec0269:
                spec->codec_variant = ALC269_TYPE_ALC269VA;
                switch (alc_get_coef0(codec) & 0x00f0) {
                case 0x0010:
@@ -6395,6 +6436,20 @@ static int patch_alc269(struct hda_codec *codec)
                        goto error;
                spec->init_hook = alc269_fill_coef;
                alc269_fill_coef(codec);
+               break;
+
+       case 0x10ec0280:
+       case 0x10ec0290:
+               spec->codec_variant = ALC269_TYPE_ALC280;
+               break;
+       case 0x10ec0282:
+       case 0x10ec0283:
+               spec->codec_variant = ALC269_TYPE_ALC282;
+               break;
+       case 0x10ec0284:
+       case 0x10ec0292:
+               spec->codec_variant = ALC269_TYPE_ALC284;
+               break;
        }
 
        /* automatic parse from the BIOS config */
@@ -7099,6 +7154,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
        { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
        { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
+       { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
        { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
        { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
index 6e02e064d7b43df1159554899f1007a9f223bc7b..223c3d9cc69efa1af38e6dee6c45ffc0f3733c55 100644 (file)
@@ -441,6 +441,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 */
 /* status */
 #define HDSPM_AES32_wcLock     0x0200000
+#define HDSPM_AES32_wcSync     0x0100000
 #define HDSPM_AES32_wcFreq_bit  22
 /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
   HDSPM_bit2freq */
@@ -3467,10 +3468,12 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm)
        switch (hdspm->io_type) {
        case AES32:
                status = hdspm_read(hdspm, HDSPM_statusRegister);
-               if (status & HDSPM_wcSync)
-                       return 2;
-               else if (status & HDSPM_wcLock)
-                       return 1;
+               if (status & HDSPM_AES32_wcLock) {
+                       if (status & HDSPM_AES32_wcSync)
+                               return 2;
+                       else
+                               return 1;
+               }
                return 0;
                break;
 
@@ -4658,6 +4661,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
        unsigned int status;
        unsigned int status2;
        unsigned int timecode;
+       unsigned int wcLock, wcSync;
        int pref_syncref;
        char *autosync_ref;
        int x;
@@ -4751,8 +4755,11 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 
        snd_iprintf(buffer, "--- Status:\n");
 
+       wcLock = status & HDSPM_AES32_wcLock;
+       wcSync = wcLock && (status & HDSPM_AES32_wcSync);
+
        snd_iprintf(buffer, "Word: %s  Frequency: %d\n",
-                   (status & HDSPM_AES32_wcLock) ? "Sync   " : "No Lock",
+                   (wcLock) ? (wcSync ? "Sync   " : "Lock   ") : "No Lock",
                    HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
 
        for (x = 0; x < 8; x++) {
index adf397b9d0e650eb19768e7bc6c592352014a595..ef62c435848eb776421776d7e80e90527e3f2b72 100644 (file)
@@ -446,15 +446,9 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        case SND_SOC_DAIFMT_DSP_A:
                mode = 0;
                break;
-       case SND_SOC_DAIFMT_DSP_B:
-               mode = 1;
-               break;
        case SND_SOC_DAIFMT_I2S:
                mode = 2;
                break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               mode = 3;
-               break;
        default:
                arizona_aif_err(dai, "Unsupported DAI format %d\n",
                                fmt & SND_SOC_DAIFMT_FORMAT_MASK);
@@ -691,7 +685,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
        }
        sr_val = i;
 
-       lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
+       lrclk = rates[bclk] / params_rate(params);
 
        arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
                        rates[bclk], rates[bclk] / lrclk);
@@ -714,7 +708,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
                snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
                                    ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
                snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
-                                   ARIZONA_AIF1_RATE_MASK, 8);
+                                   ARIZONA_AIF1_RATE_MASK,
+                                   8 << ARIZONA_AIF1_RATE_SHIFT);
                break;
        default:
                arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
@@ -1087,6 +1082,9 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
                        id, ret);
        }
 
+       regmap_update_bits(arizona->regmap, fll->base + 1,
+                          ARIZONA_FLL1_FREERUN, 0);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_init_fll);
index 41dae1ed3b714a4734448b1d3c99938af1fe9d9a..4deebeb0717754085edceb38e7c00b141f4502fb 100644 (file)
 
 #define ARIZONA_FLL_SRC_MCLK1      0
 #define ARIZONA_FLL_SRC_MCLK2      1
-#define ARIZONA_FLL_SRC_SLIMCLK    2
-#define ARIZONA_FLL_SRC_FLL1       3
-#define ARIZONA_FLL_SRC_FLL2       4
-#define ARIZONA_FLL_SRC_AIF1BCLK   5
-#define ARIZONA_FLL_SRC_AIF2BCLK   6
-#define ARIZONA_FLL_SRC_AIF3BCLK   7
-#define ARIZONA_FLL_SRC_AIF1LRCLK  8
-#define ARIZONA_FLL_SRC_AIF2LRCLK  9
-#define ARIZONA_FLL_SRC_AIF3LRCLK 10
+#define ARIZONA_FLL_SRC_SLIMCLK    3
+#define ARIZONA_FLL_SRC_FLL1       4
+#define ARIZONA_FLL_SRC_FLL2       5
+#define ARIZONA_FLL_SRC_AIF1BCLK   8
+#define ARIZONA_FLL_SRC_AIF2BCLK   9
+#define ARIZONA_FLL_SRC_AIF3BCLK  10
+#define ARIZONA_FLL_SRC_AIF1LRCLK 12
+#define ARIZONA_FLL_SRC_AIF2LRCLK 13
+#define ARIZONA_FLL_SRC_AIF3LRCLK 14
 
 #define ARIZONA_MIXER_VOL_MASK             0x00FE
 #define ARIZONA_MIXER_VOL_SHIFT                 1
index 4f1127935fdf5f9578970b13fcf73b8815d469e5..ac8742a1f25ab7c69fcca2b22458ae02acf3d67e 100644 (file)
@@ -474,16 +474,16 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
        int ret;
        int gpio_nreset = -EINVAL;
-       int amutec_eq_bmutec = 0;
+       bool amutec_eq_bmutec = false;
 
 #ifdef CONFIG_OF
        if (of_match_device(cs4271_dt_ids, codec->dev)) {
                gpio_nreset = of_get_named_gpio(codec->dev->of_node,
                                                "reset-gpio", 0);
 
-               if (!of_get_property(codec->dev->of_node,
+               if (of_get_property(codec->dev->of_node,
                                     "cirrus,amutec-eq-bmutec", NULL))
-                       amutec_eq_bmutec = 1;
+                       amutec_eq_bmutec = true;
        }
 #endif
 
index 99bb1c69499e42a6791ae12c55dde2d53efb7f49..9811a5478c87649da6c42806a3a43bfcc5a5767e 100644 (file)
@@ -737,7 +737,7 @@ static const struct cs42l52_clk_para clk_map_table[] = {
 
 static int cs42l52_get_clk(int mclk, int rate)
 {
-       int i, ret = 0;
+       int i, ret = -EINVAL;
        u_int mclk1, mclk2 = 0;
 
        for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
@@ -749,8 +749,6 @@ static int cs42l52_get_clk(int mclk, int rate)
                        }
                }
        }
-       if (ret > ARRAY_SIZE(clk_map_table))
-               return -EINVAL;
        return ret;
 }
 
index d75257d40a496d26e9bb513f6fd000abe6f13a76..e19490cfb3a8bde2036e61d877b3a8c407cc510c 100644 (file)
@@ -111,9 +111,9 @@ static struct reg_default lm49453_reg_defs[] = {
        { 101, 0x00 },
        { 102, 0x00 },
        { 103, 0x01 },
-       { 105, 0x01 },
-       { 106, 0x00 },
-       { 107, 0x01 },
+       { 104, 0x01 },
+       { 105, 0x00 },
+       { 106, 0x01 },
        { 107, 0x00 },
        { 108, 0x00 },
        { 109, 0x00 },
@@ -163,56 +163,25 @@ static struct reg_default lm49453_reg_defs[] = {
        { 184, 0x00 },
        { 185, 0x00 },
        { 186, 0x00 },
-       { 189, 0x00 },
+       { 187, 0x00 },
        { 188, 0x00 },
-       { 194, 0x00 },
-       { 195, 0x00 },
-       { 196, 0x00 },
-       { 197, 0x00 },
-       { 200, 0x00 },
-       { 201, 0x00 },
-       { 202, 0x00 },
-       { 203, 0x00 },
-       { 204, 0x00 },
-       { 205, 0x00 },
-       { 208, 0x00 },
+       { 189, 0x00 },
+       { 208, 0x06 },
        { 209, 0x00 },
-       { 210, 0x00 },
-       { 211, 0x00 },
-       { 213, 0x00 },
-       { 214, 0x00 },
-       { 215, 0x00 },
-       { 216, 0x00 },
-       { 217, 0x00 },
-       { 218, 0x00 },
-       { 219, 0x00 },
+       { 210, 0x08 },
+       { 211, 0x54 },
+       { 212, 0x14 },
+       { 213, 0x0d },
+       { 214, 0x0d },
+       { 215, 0x14 },
+       { 216, 0x60 },
        { 221, 0x00 },
        { 222, 0x00 },
+       { 223, 0x00 },
        { 224, 0x00 },
-       { 225, 0x00 },
-       { 226, 0x00 },
-       { 227, 0x00 },
-       { 228, 0x00 },
-       { 229, 0x00 },
-       { 230, 0x13 },
-       { 231, 0x00 },
-       { 232, 0x80 },
-       { 233, 0x0C },
-       { 234, 0xDD },
-       { 235, 0x00 },
-       { 236, 0x04 },
-       { 237, 0x00 },
-       { 238, 0x00 },
-       { 239, 0x00 },
-       { 240, 0x00 },
-       { 241, 0x00 },
-       { 242, 0x00 },
-       { 243, 0x00 },
-       { 244, 0x00 },
-       { 245, 0x00 },
        { 248, 0x00 },
        { 249, 0x00 },
-       { 254, 0x00 },
+       { 250, 0x00 },
        { 255, 0x00 },
 };
 
@@ -525,36 +494,41 @@ SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_PORT2_TX2_REG, 7, 1, 0),
 };
 
 /* TLV Declarations */
-static const DECLARE_TLV_DB_SCALE(digital_tlv, -7650, 150, 1);
-static const DECLARE_TLV_DB_SCALE(port_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(adc_dac_tlv, -7650, 150, 1);
+static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 200, 1);
+static const DECLARE_TLV_DB_SCALE(port_tlv, -1800, 600, 0);
+static const DECLARE_TLV_DB_SCALE(stn_tlv, -7200, 150, 0);
 
 static const struct snd_kcontrol_new lm49453_sidetone_mixer_controls[] = {
 /* Sidetone supports mono only */
 SOC_DAPM_SINGLE_TLV("Sidetone ADCL Volume", LM49453_P0_STN_VOL_ADCL_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone ADCR Volume", LM49453_P0_STN_VOL_ADCR_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC1L Volume", LM49453_P0_STN_VOL_DMIC1L_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC1R Volume", LM49453_P0_STN_VOL_DMIC1R_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC2L Volume", LM49453_P0_STN_VOL_DMIC2L_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC2R Volume", LM49453_P0_STN_VOL_DMIC2R_REG,
-                    0, 0x3F, 0, digital_tlv),
+                    0, 0x3F, 0, stn_tlv),
 };
 
 static const struct snd_kcontrol_new lm49453_snd_controls[] = {
        /* mic1 and mic2 supports mono only */
-       SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_ADC_LEVELL_REG, 0, 6,
-                       0, digital_tlv),
-       SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_ADC_LEVELR_REG, 0, 6,
-                       0, digital_tlv),
+       SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_MICL_REG, 0, 15, 0, mic_tlv),
+       SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_MICR_REG, 0, 15, 0, mic_tlv),
+
+       SOC_SINGLE_TLV("ADCL Volume", LM49453_P0_ADC_LEVELL_REG, 0, 63,
+                       0, adc_dac_tlv),
+       SOC_SINGLE_TLV("ADCR Volume", LM49453_P0_ADC_LEVELR_REG, 0, 63,
+                       0, adc_dac_tlv),
 
        SOC_DOUBLE_R_TLV("DMIC1 Volume", LM49453_P0_DMIC1_LEVELL_REG,
-                         LM49453_P0_DMIC1_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DMIC1_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
        SOC_DOUBLE_R_TLV("DMIC2 Volume", LM49453_P0_DMIC2_LEVELL_REG,
-                         LM49453_P0_DMIC2_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DMIC2_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 
        SOC_DAPM_ENUM("Mic2Mode", lm49453_mic2mode_enum),
        SOC_DAPM_ENUM("DMIC12 SRC", lm49453_dmic12_cfg_enum),
@@ -569,16 +543,16 @@ static const struct snd_kcontrol_new lm49453_snd_controls[] = {
                                          2, 1, 0),
 
        SOC_DOUBLE_R_TLV("DAC HP Volume", LM49453_P0_DAC_HP_LEVELL_REG,
-                         LM49453_P0_DAC_HP_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DAC_HP_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
        SOC_DOUBLE_R_TLV("DAC LO Volume", LM49453_P0_DAC_LO_LEVELL_REG,
-                         LM49453_P0_DAC_LO_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DAC_LO_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
        SOC_DOUBLE_R_TLV("DAC LS Volume", LM49453_P0_DAC_LS_LEVELL_REG,
-                         LM49453_P0_DAC_LS_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DAC_LS_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
        SOC_DOUBLE_R_TLV("DAC HA Volume", LM49453_P0_DAC_HA_LEVELL_REG,
-                         LM49453_P0_DAC_HA_LEVELR_REG, 0, 6, 0, digital_tlv),
+                         LM49453_P0_DAC_HA_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 
        SOC_SINGLE_TLV("EP Volume", LM49453_P0_DAC_LS_LEVELL_REG,
-                       0, 6, 0, digital_tlv),
+                       0, 63, 0, adc_dac_tlv),
 
        SOC_SINGLE_TLV("PORT1_1_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
                        0, 3, 0, port_tlv),
@@ -1218,7 +1192,7 @@ static int lm49453_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        }
 
        snd_soc_update_bits(codec, LM49453_P0_AUDIO_PORT1_BASIC_REG,
-                           LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(1)|BIT(5),
+                           LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(0)|BIT(5),
                            (aif_val | mode | clk_phase));
 
        snd_soc_write(codec, LM49453_P0_AUDIO_PORT1_RX_MSB_REG, clk_shift);
index cb1675cd8e1c5ffd9b404b9d12ee9c404f6f2efd..92bbfec9b107a0ec5ee55205b9272ce9e67caa74 100644 (file)
@@ -401,7 +401,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
                        5, 1, 0),
 
        SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL,
-                       0, 4, 0, mic_gain_tlv),
+                       0, 3, 0, mic_gain_tlv),
 };
 
 /* mute the codec used by alsa core */
@@ -1344,7 +1344,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
                        SGTL5000_HP_ZCD_EN |
                        SGTL5000_ADC_ZCD_EN);
 
-       snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0);
+       snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2);
 
        /*
         * disable DAP
index ab355c4f0b2de0aa786e754360a6a877a0855756..40c07be9b5814f170f73fa1b3670d3813101bb67 100644 (file)
                                SNDRV_PCM_FMTBIT_S32_LE)
 #define        S2PC_VALUE              0x98
 #define CLOCK_OUT              0x60
-#define LEFT_J_DATA_FORMAT     0x10
-#define I2S_DATA_FORMAT                0x12
-#define RIGHT_J_DATA_FORMAT    0x14
+#define DATA_FORMAT_MSK                0x0E
+#define LEFT_J_DATA_FORMAT     0x00
+#define I2S_DATA_FORMAT                0x02
+#define RIGHT_J_DATA_FORMAT    0x04
 #define CODEC_MUTE_VAL         0x80
 
 #define POWER_CNTLMSAK         0x40
@@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode);
+       snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode);
 
        return 0;
 }
index 1cbe88f01d634137e0d7e85218556e1c81710d59..12bcae63a7f020f2dab718b535ad8b3d41d49ccd 100644 (file)
@@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
 
        ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY);
        if (wm2000->speech_clarity)
-               ret &= ~WM2000_SPEECH_CLARITY;
-       else
                ret |= WM2000_SPEECH_CLARITY;
+       else
+               ret &= ~WM2000_SPEECH_CLARITY;
        wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret);
 
        wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33);
index afcf31df77e06efe19c709630f53990741348227..d8c65f5746583474b4cdfb286d339c512f3562d6 100644 (file)
@@ -1019,8 +1019,6 @@ static const char *wm2200_mixer_texts[] = {
        "EQR",
        "LHPF1",
        "LHPF2",
-       "LHPF3",
-       "LHPF4",
        "DSP1.1",
        "DSP1.2",
        "DSP1.3",
@@ -1053,7 +1051,6 @@ static int wm2200_mixer_values[] = {
        0x25,
        0x50,   /* EQ */
        0x51,
-       0x52,
        0x60,   /* LHPF1 */
        0x61,   /* LHPF2 */
        0x68,   /* DSP1 */
@@ -1566,15 +1563,9 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        case SND_SOC_DAIFMT_DSP_A:
                fmt_val = 0;
                break;
-       case SND_SOC_DAIFMT_DSP_B:
-               fmt_val = 1;
-               break;
        case SND_SOC_DAIFMT_I2S:
                fmt_val = 2;
                break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               fmt_val = 3;
-               break;
        default:
                dev_err(codec->dev, "Unsupported DAI format %d\n",
                        fmt & SND_SOC_DAIFMT_FORMAT_MASK);
@@ -1626,7 +1617,7 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                            WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
                            lrclk);
        snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
-                           WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+                           WM2200_AIF1_FMT_MASK, fmt_val);
 
        return 0;
 }
index 5a5f3693623568d2d6268e9bc10e7055664c5d3d..54397a50807379bf2e625b4f980773ad72515164 100644 (file)
@@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        case SND_SOC_DAIFMT_DSP_A:
                mask = 0;
                break;
-       case SND_SOC_DAIFMT_DSP_B:
-               mask = 1;
-               break;
        case SND_SOC_DAIFMT_I2S:
                mask = 2;
                break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               mask = 3;
-               break;
        default:
                dev_err(codec->dev, "Unsupported DAI format %d\n",
                        fmt & SND_SOC_DAIFMT_FORMAT_MASK);
index 688ade0805897557baac586aeb6387a70361fd2c..1440b3f9b7bbe1e04afdfd3d6857808f52972fa9 100644 (file)
@@ -36,6 +36,9 @@
 struct wm5102_priv {
        struct arizona_priv core;
        struct arizona_fll fll[2];
+
+       unsigned int spk_ena:2;
+       unsigned int spk_ena_pending:1;
 };
 
 static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
@@ -787,6 +790,47 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
 };
 
+static int wm5102_spk_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->parent);
+       struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
+
+       if (arizona->rev < 1)
+               return 0;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               if (!wm5102->spk_ena) {
+                       snd_soc_write(codec, 0x4f5, 0x25a);
+                       wm5102->spk_ena_pending = true;
+               }
+               break;
+       case SND_SOC_DAPM_POST_PMU:
+               if (wm5102->spk_ena_pending) {
+                       msleep(75);
+                       snd_soc_write(codec, 0x4f5, 0xda);
+                       wm5102->spk_ena_pending = false;
+                       wm5102->spk_ena++;
+               }
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               wm5102->spk_ena--;
+               if (!wm5102->spk_ena)
+                       snd_soc_write(codec, 0x4f5, 0x25a);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               if (!wm5102->spk_ena)
+                       snd_soc_write(codec, 0x4f5, 0x0da);
+               break;
+       }
+
+       return 0;
+}
+
+
 ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
@@ -852,8 +896,7 @@ static const unsigned int wm5102_aec_loopback_values[] = {
 
 static const struct soc_enum wm5102_aec_loopback =
        SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
-                             ARIZONA_AEC_LOOPBACK_SRC_SHIFT,
-                             ARIZONA_AEC_LOOPBACK_SRC_MASK,
+                             ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
                              ARRAY_SIZE(wm5102_aec_loopback_texts),
                              wm5102_aec_loopback_texts,
                              wm5102_aec_loopback_values);
@@ -1034,10 +1077,10 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
                   ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
                   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
-                  ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+                  ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
                   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
-                  ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+                  ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
                   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
                   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
index ae80c8c285360cffd1ef82af06626ceccf2769d2..7a090968c4f737bd360f05c2c7a66dc362350d21 100644 (file)
@@ -344,8 +344,7 @@ static const unsigned int wm5110_aec_loopback_values[] = {
 
 static const struct soc_enum wm5110_aec_loopback =
        SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
-                             ARIZONA_AEC_LOOPBACK_SRC_SHIFT,
-                             ARIZONA_AEC_LOOPBACK_SRC_MASK,
+                             ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
                              ARRAY_SIZE(wm5110_aec_loopback_texts),
                              wm5110_aec_loopback_texts,
                              wm5110_aec_loopback_values);
index ffc89fab96fbf4b6ccc81973f69df863132da1ec..b6b65483758518f8b8cab7672af882ef923d2768 100644 (file)
@@ -169,6 +169,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
        const struct wm_adsp_region *mem;
        const char *region_name;
        char *file, *text;
+       void *buf;
        unsigned int reg;
        int regions = 0;
        int ret, offset, type, sizes;
@@ -322,8 +323,18 @@ static int wm_adsp_load(struct wm_adsp *dsp)
                }
 
                if (reg) {
-                       ret = regmap_raw_write(regmap, reg, region->data,
+                       buf = kmemdup(region->data, le32_to_cpu(region->len),
+                                     GFP_KERNEL | GFP_DMA);
+                       if (!buf) {
+                               adsp_err(dsp, "Out of memory\n");
+                               return -ENOMEM;
+                       }
+
+                       ret = regmap_raw_write(regmap, reg, buf,
                                               le32_to_cpu(region->len));
+
+                       kfree(buf);
+
                        if (ret != 0) {
                                adsp_err(dsp,
                                        "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
@@ -359,6 +370,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
        const char *region_name;
        int ret, pos, blocks, type, offset, reg;
        char *file;
+       void *buf;
 
        file = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (file == NULL)
@@ -384,7 +396,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
        hdr = (void*)&firmware->data[0];
        if (memcmp(hdr->magic, "WMDR", 4) != 0) {
                adsp_err(dsp, "%s: invalid magic\n", file);
-               return -EINVAL;
+               goto out_fw;
        }
 
        adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
@@ -426,6 +438,13 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                }
 
                if (reg) {
+                       buf = kmemdup(blk->data, le32_to_cpu(blk->len),
+                                     GFP_KERNEL | GFP_DMA);
+                       if (!buf) {
+                               adsp_err(dsp, "Out of memory\n");
+                               return -ENOMEM;
+                       }
+
                        ret = regmap_raw_write(regmap, reg, blk->data,
                                               le32_to_cpu(blk->len));
                        if (ret != 0) {
@@ -433,6 +452,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                                        "%s.%d: Failed to write to %x in %s\n",
                                        file, blocks, reg, region_name);
                        }
+
+                       kfree(buf);
                }
 
                pos += le32_to_cpu(blk->len) + sizeof(*blk);
index bf363d8d044aa2f1c38d44f0c66a20f1131a65de..500f8ce55d78f0891bcf71dabf1c98cae3e8379e 100644 (file)
@@ -154,26 +154,7 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
        .pcm_free       = imx_pcm_free,
 };
 
-static int imx_soc_platform_probe(struct platform_device *pdev)
+int imx_pcm_dma_init(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
 }
-
-static int imx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver imx_pcm_driver = {
-       .driver = {
-                       .name = "imx-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-       .probe = imx_soc_platform_probe,
-       .remove = imx_soc_platform_remove,
-};
-
-module_platform_driver(imx_pcm_driver);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-pcm-audio");
index 5ec362ae4d012b654cdadbfeace42036ed76764e..920f945cb2f4e17d721f7e5f542ca0b454ba9b74 100644 (file)
@@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
        .pcm_free       = imx_pcm_fiq_free,
 };
 
-static int imx_soc_platform_probe(struct platform_device *pdev)
+int imx_pcm_fiq_init(struct platform_device *pdev)
 {
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
        int ret;
@@ -314,23 +314,3 @@ failed_register:
 
        return ret;
 }
-
-static int imx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver imx_pcm_driver = {
-       .driver = {
-                       .name = "imx-fiq-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = imx_soc_platform_probe,
-       .remove = imx_soc_platform_remove,
-};
-
-module_platform_driver(imx_pcm_driver);
-
-MODULE_LICENSE("GPL");
index d5cd9eff3b48e92ca77349b930fe84056fcd7017..0d0625bfcb65a990e0ff119fa080a1b61f535857 100644 (file)
@@ -104,6 +104,38 @@ void imx_pcm_free(struct snd_pcm *pcm)
 }
 EXPORT_SYMBOL_GPL(imx_pcm_free);
 
+static int imx_pcm_probe(struct platform_device *pdev)
+{
+       if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
+               return imx_pcm_fiq_init(pdev);
+
+       return imx_pcm_dma_init(pdev);
+}
+
+static int imx_pcm_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_device_id imx_pcm_devtype[] = {
+       { .name = "imx-pcm-audio", },
+       { .name = "imx-fiq-pcm-audio", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, imx_pcm_devtype);
+
+static struct platform_driver imx_pcm_driver = {
+       .driver = {
+                       .name = "imx-pcm",
+                       .owner = THIS_MODULE,
+       },
+       .id_table = imx_pcm_devtype,
+       .probe = imx_pcm_probe,
+       .remove = imx_pcm_remove,
+};
+module_platform_driver(imx_pcm_driver);
+
 MODULE_DESCRIPTION("Freescale i.MX PCM driver");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_LICENSE("GPL");
index 83c0ed7d55c9a4710b75846bb0bd5569d257ed0f..5ae13a13a353834f72bec2c933b3c4b19dfc3012 100644 (file)
@@ -30,4 +30,22 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
 void imx_pcm_free(struct snd_pcm *pcm);
 
+#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
+int imx_pcm_dma_init(struct platform_device *pdev);
+#else
+static inline int imx_pcm_dma_init(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
+#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
+int imx_pcm_fiq_init(struct platform_device *pdev);
+#else
+static inline int imx_pcm_fiq_init(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
 #endif /* _IMX_PCM_H */
index 91d592ff67b7914cdbeec98c24eb3b4c1cb6a364..2370063b58245946f71adfa05f361097d3e53374 100644 (file)
@@ -1255,6 +1255,8 @@ static int soc_post_component_init(struct snd_soc_card *card,
        INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
        ret = device_add(rtd->dev);
        if (ret < 0) {
+               /* calling put_device() here to free the rtd->dev */
+               put_device(rtd->dev);
                dev_err(card->dev,
                        "ASoC: failed to register runtime device: %d\n", ret);
                return ret;
@@ -1554,7 +1556,7 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
        /* unregister the rtd device */
        if (rtd->dev_registered) {
                device_remove_file(rtd->dev, &dev_attr_codec_reg);
-               device_del(rtd->dev);
+               device_unregister(rtd->dev);
                rtd->dev_registered = 0;
        }
 
@@ -2917,7 +2919,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
        platform_max = mc->platform_max;
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
+       uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = platform_max - min;
 
@@ -2941,12 +2943,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int rreg = mc->rreg;
        unsigned int shift = mc->shift;
        int min = mc->min;
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
        unsigned int val, val_mask;
+       int ret;
 
        val = ((ucontrol->value.integer.value[0] + min) & mask);
        if (invert)
@@ -2954,7 +2958,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
        val_mask = mask << shift;
        val = val << shift;
 
-       return snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (ret != 0)
+               return ret;
+
+       if (snd_soc_volsw_is_stereo(mc)) {
+               val = ((ucontrol->value.integer.value[1] + min) & mask);
+               if (invert)
+                       val = max - val;
+               val_mask = mask << shift;
+               val = val << shift;
+
+               ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val);
+       }
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
 
@@ -2974,6 +2992,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int rreg = mc->rreg;
        unsigned int shift = mc->shift;
        int min = mc->min;
        int max = mc->max;
@@ -2988,6 +3007,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
        ucontrol->value.integer.value[0] =
                ucontrol->value.integer.value[0] - min;
 
+       if (snd_soc_volsw_is_stereo(mc)) {
+               ucontrol->value.integer.value[1] =
+                       (snd_soc_read(codec, rreg) >> shift) & mask;
+               if (invert)
+                       ucontrol->value.integer.value[1] =
+                               max - ucontrol->value.integer.value[1];
+               ucontrol->value.integer.value[1] =
+                       ucontrol->value.integer.value[1] - min;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
index 1e36bc81e5af1fb015ffef62f628781910984bbb..258acadb9e7d238a97b7af6508ffc21bd1a4488e 100644 (file)
@@ -1023,7 +1023,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
 
        if (SND_SOC_DAPM_EVENT_ON(event)) {
                if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
-                       ret = regulator_allow_bypass(w->regulator, true);
+                       ret = regulator_allow_bypass(w->regulator, false);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
                                         "ASoC: Failed to bypass %s: %d\n",
@@ -1033,7 +1033,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                return regulator_enable(w->regulator);
        } else {
                if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
-                       ret = regulator_allow_bypass(w->regulator, false);
+                       ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
                                         "ASoC: Failed to unbypass %s: %d\n",
@@ -3039,6 +3039,14 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                                w->name, ret);
                        return NULL;
                }
+
+               if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+                       ret = regulator_allow_bypass(w->regulator, true);
+                       if (ret != 0)
+                               dev_warn(w->dapm->dev,
+                                        "ASoC: Failed to unbypass %s: %d\n",
+                                        w->name, ret);
+               }
                break;
        case snd_soc_dapm_clock_supply:
 #ifdef CONFIG_CLKDEV_LOOKUP
index d7711fce119b7b949bc521759b2f13e177dd657d..cf191e6aebbe1d1bfeb9dd511d0fe9b5e5bd3bbd 100644 (file)
@@ -1243,6 +1243,7 @@ static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
                if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
                        continue;
 
index c183d34842accdc69ac8b1dec5424bb4373b1bbc..34b9bb7fe87c8eabed83df8b7b77f510bedbc2b1 100644 (file)
@@ -2181,10 +2181,6 @@ int snd_usbmidi_create(struct snd_card *card,
                umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
                err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
                break;
-       case QUIRK_MIDI_MBOX2:
-               umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
-               err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
-               break;
        case QUIRK_MIDI_RAW_BYTES:
                umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
                /*
index ed4d89c8b52a52e6425ce5c992cc5d324b339d35..e90daf8cdaa8726f8311092636461a9fee10b187 100644 (file)
@@ -1331,16 +1331,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
                }
                channels = (hdr->bLength - 7) / csize - 1;
                bmaControls = hdr->bmaControls;
+               if (hdr->bLength < 7 + csize) {
+                       snd_printk(KERN_ERR "usbaudio: unit %u: "
+                                  "invalid UAC_FEATURE_UNIT descriptor\n",
+                                  unitid);
+                       return -EINVAL;
+               }
        } else {
                struct uac2_feature_unit_descriptor *ftr = _ftr;
                csize = 4;
                channels = (hdr->bLength - 6) / 4 - 1;
                bmaControls = ftr->bmaControls;
-       }
-
-       if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) {
-               snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid);
-               return -EINVAL;
+               if (hdr->bLength < 6 + csize) {
+                       snd_printk(KERN_ERR "usbaudio: unit %u: "
+                                  "invalid UAC_FEATURE_UNIT descriptor\n",
+                                  unitid);
+                       return -EINVAL;
+               }
        }
 
        /* parse the source unit */
index e71fe55cebefa8285963643e7a592a0b71fbfc73..0e2ed3d05c451c32a53032b735bc95c7868df143 100644 (file)
@@ -179,6 +179,15 @@ static struct usbmix_name_map audigy2nx_map[] = {
        { 0 } /* terminator */
 };
 
+static struct usbmix_selector_map c400_selectors[] = {
+       {
+               .id = 0x80,
+               .count = 2,
+               .names = (const char*[]) {"Internal", "SPDIF"}
+       },
+       { 0 } /* terminator */
+};
+
 static struct usbmix_selector_map audigy2nx_selectors[] = {
        {
                .id = 14, /* Capture Source */
@@ -366,6 +375,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x06f8, 0xc000),
                .map = hercules_usb51_map,
        },
+       {
+               .id = USB_ID(0x0763, 0x2030),
+               .selector_map = c400_selectors,
+       },
        {
                .id = USB_ID(0x08bb, 0x2702),
                .map = linex_map,
index 0422b1360af3a896da708a79365e3370be771fd8..15520de1df5647c95a4ffe1a13d8ede4485dee09 100644 (file)
@@ -1206,7 +1206,7 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
  * are valid they presents mono controls as L and R channels of
  * stereo. So we provide a good mixer here.
  */
-struct std_mono_table ebox44_table[] = {
+static struct std_mono_table ebox44_table[] = {
        {
                .unitid = 4,
                .control = 1,
index c6593101c049b88ca6e5661f8765b3f3df0b4d33..d82e378d37cbb7202aaa487b6003b6b171b79eab 100644 (file)
@@ -511,6 +511,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
        struct snd_usb_substream *sync_subs =
                &subs->stream->substream[subs->direction ^ 1];
 
+       if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA ||
+           !subs->stream)
+               return snd_usb_endpoint_set_params(subs->sync_endpoint,
+                                                  subs->pcm_format,
+                                                  subs->channels,
+                                                  subs->period_bytes,
+                                                  subs->cur_rate,
+                                                  subs->cur_audiofmt,
+                                                  NULL);
+
        /* Try to find the best matching audioformat. */
        list_for_each_entry(fp, &sync_subs->fmt_list, list) {
                int score = match_endpoint_audioformats(fp, subs->cur_audiofmt,
index cdcf6b45e8a887746a2f087e680b2c45a3198462..64d25a7a4d599538398e5a14d37d11a154ec65fd 100644 (file)
        }
 },
 
+{
+       /* Creative BT-D1 */
+       USB_DEVICE(0x041e, 0x0005),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = 1,
+               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+               .data = &(const struct audioformat) {
+                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels = 2,
+                       .iface = 1,
+                       .altsetting = 1,
+                       .altset_idx = 1,
+                       .endpoint = 0x03,
+                       .ep_attr = USB_ENDPOINT_XFER_ISOC,
+                       .attributes = 0,
+                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+                       .rate_min = 48000,
+                       .rate_max = 48000,
+               }
+       }
+},
+
 /* Creative/Toshiba Multimedia Center SB-0500 */
 {
        USB_DEVICE(0x041e, 0x3048),
@@ -2267,7 +2289,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                                        .rate_table = (unsigned int[]) {
                                                        44100, 48000, 88200, 96000
                                        },
-                                       .clock = 0x81,
+                                       .clock = 0x80,
                                }
                        },
                        /* Capture */
@@ -2293,7 +2315,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                                        .rate_table = (unsigned int[]) {
                                                44100, 48000, 88200, 96000
                                        },
-                                       .clock = 0x81,
+                                       .clock = 0x80,
                                }
                        },
                        /* MIDI */
@@ -2993,7 +3015,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                        },
                        {
                                .ifnum = 6,
-                               .type = QUIRK_MIDI_MBOX2,
+                               .type = QUIRK_MIDI_MIDIMAN,
                                .data = &(const struct snd_usb_midi_endpoint_info) {
                                        .out_ep =  0x02,
                                        .out_cables = 0x0001,
index f104c68fe1e0546bfbc43bdb51dc635a8ad642af..2c971858d6b70a146e57266bfa0afe7a1bfe80cb 100644 (file)
@@ -306,7 +306,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
                [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
                [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
-               [QUIRK_MIDI_MBOX2] = create_any_midi_quirk,
                [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
                [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
@@ -388,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
                 * rules
                 */
                err = usb_driver_set_configuration(dev, 2);
-               if (err < 0) {
+               if (err < 0)
                        snd_printdd("error usb_driver_set_configuration: %d\n",
                                    err);
-                       return -ENODEV;
-               }
+               /* Always return an error, so that we stop creating a device
+                  that will just be destroyed and recreated with a new
+                  configuration */
+               return -ENODEV;
        } else
                snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
 
@@ -528,11 +529,11 @@ static void mbox2_setup_48_24_magic(struct usb_device *dev)
 #define MBOX2_BOOT_LOADING     0x01 /* Hard coded into the device */
 #define MBOX2_BOOT_READY       0x02 /* Hard coded into the device */
 
-int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
+static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
 {
        struct usb_host_config *config = dev->actconfig;
        int err;
-       u8 bootresponse;
+       u8 bootresponse[12];
        int fwsize;
        int count;
 
@@ -546,20 +547,20 @@ int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
        snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
 
        count = 0;
-       bootresponse = MBOX2_BOOT_LOADING;
-       while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) {
+       bootresponse[0] = MBOX2_BOOT_LOADING;
+       while ((bootresponse[0] == MBOX2_BOOT_LOADING) && (count < 10)) {
                msleep(500); /* 0.5 second delay */
                snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
                        /* Control magic - load onboard firmware */
                        0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
-               if (bootresponse == MBOX2_BOOT_READY)
+               if (bootresponse[0] == MBOX2_BOOT_READY)
                        break;
                snd_printd("usb-audio: device not ready, resending boot sequence...\n");
                count++;
        }
 
-       if (bootresponse != MBOX2_BOOT_READY) {
-               snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse);
+       if (bootresponse[0] != MBOX2_BOOT_READY) {
+               snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]);
                return -ENODEV;
        }
 
@@ -660,7 +661,6 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
        return 0; /* keep this altsetting */
 }
 
-
 static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip,
                                           int iface, int altno)
 {
@@ -861,6 +861,17 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
        if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) &&
            ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
                ep->skip_packets = 4;
+
+       /*
+        * M-Audio Fast Track C400 - when packets are not skipped, real world
+        * latency varies by approx. +/- 50 frames (at 96KHz) each time the
+        * stream is (re)started. When skipping packets 16 at endpoint start
+        * up, the real world latency is stable within +/- 1 frame (also
+        * across power cycles).
+        */
+       if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) &&
+           ep->type == SND_USB_ENDPOINT_TYPE_DATA)
+               ep->skip_packets = 16;
 }
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
index a8172c119796015fa2edd0a675d4568c27f83ba7..1ac3fd9cc5a625e89cc1290ab3274ebac6982793 100644 (file)
@@ -76,7 +76,6 @@ enum quirk_type {
        QUIRK_MIDI_YAMAHA,
        QUIRK_MIDI_MIDIMAN,
        QUIRK_MIDI_NOVATION,
-       QUIRK_MIDI_MBOX2,
        QUIRK_MIDI_RAW_BYTES,
        QUIRK_MIDI_EMAGIC,
        QUIRK_MIDI_CME,
index 1f9a529fe544f768c4322e884e4c34d02d482b5e..798fa0ef048e99002678a20e2ddc477e7ff54079 100644 (file)
@@ -15,7 +15,7 @@ help:
        @echo '  x86_energy_perf_policy - Intel energy policy tool'
        @echo ''
        @echo 'You can do:'
-       @echo ' $$ make -C tools/<tool>_install'
+       @echo ' $$ make -C tools/ <tool>_install'
        @echo ''
        @echo '  from the kernel command line to build and install one of'
        @echo '  the tools above'
index 5a824e355d04d61a694853d285078effa2e2985e..82b0606dcb8ab04ed08920abf9c2c193e4ee42bf 100644 (file)
@@ -13,8 +13,7 @@
  * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -1224,6 +1223,34 @@ static int field_is_long(struct format_field *field)
        return 0;
 }
 
+static unsigned int type_size(const char *name)
+{
+       /* This covers all FIELD_IS_STRING types. */
+       static struct {
+               const char *type;
+               unsigned int size;
+       } table[] = {
+               { "u8",   1 },
+               { "u16",  2 },
+               { "u32",  4 },
+               { "u64",  8 },
+               { "s8",   1 },
+               { "s16",  2 },
+               { "s32",  4 },
+               { "s64",  8 },
+               { "char", 1 },
+               { },
+       };
+       int i;
+
+       for (i = 0; table[i].type; i++) {
+               if (!strcmp(table[i].type, name))
+                       return table[i].size;
+       }
+
+       return 0;
+}
+
 static int event_read_fields(struct event_format *event, struct format_field **fields)
 {
        struct format_field *field = NULL;
@@ -1233,6 +1260,8 @@ static int event_read_fields(struct event_format *event, struct format_field **f
        int count = 0;
 
        do {
+               unsigned int size_dynamic = 0;
+
                type = read_token(&token);
                if (type == EVENT_NEWLINE) {
                        free_token(token);
@@ -1391,6 +1420,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                field->type = new_type;
                                strcat(field->type, " ");
                                strcat(field->type, field->name);
+                               size_dynamic = type_size(field->name);
                                free_token(field->name);
                                strcat(field->type, brackets);
                                field->name = token;
@@ -1463,7 +1493,8 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                        if (read_expect_type(EVENT_ITEM, &token))
                                goto fail;
 
-                       /* add signed type */
+                       if (strtoul(token, NULL, 0))
+                               field->flags |= FIELD_IS_SIGNED;
 
                        free_token(token);
                        if (read_expected(EVENT_OP, ";") < 0)
@@ -1478,10 +1509,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                if (field->flags & FIELD_IS_ARRAY) {
                        if (field->arraylen)
                                field->elementsize = field->size / field->arraylen;
+                       else if (field->flags & FIELD_IS_DYNAMIC)
+                               field->elementsize = size_dynamic;
                        else if (field->flags & FIELD_IS_STRING)
                                field->elementsize = 1;
-                       else
-                               field->elementsize = event->pevent->long_size;
+                       else if (field->flags & FIELD_IS_LONG)
+                               field->elementsize = event->pevent ?
+                                                    event->pevent->long_size :
+                                                    sizeof(long);
                } else
                        field->elementsize = field->size;
 
@@ -1785,6 +1820,8 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
                   strcmp(token, "/") == 0 ||
                   strcmp(token, "<") == 0 ||
                   strcmp(token, ">") == 0 ||
+                  strcmp(token, "<=") == 0 ||
+                  strcmp(token, ">=") == 0 ||
                   strcmp(token, "==") == 0 ||
                   strcmp(token, "!=") == 0) {
 
@@ -2481,7 +2518,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
 
        free_token(token);
        arg = alloc_arg();
-       if (!field) {
+       if (!arg) {
                do_warning("%s: not enough memory!", __func__);
                *tok = NULL;
                return EVENT_ERROR;
index 24a4bbabc5d550c5c3a09113a8277f37ad1182b4..7be7e89533e4fed9979dae191cbb2aa808c45121 100644 (file)
@@ -13,8 +13,7 @@
  * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
index bc075006966eb69c9dc8f0fcc7a6d636da413cff..e76c9acb92cd5ab693ee70bc7851fffd237a4a4e 100644 (file)
@@ -13,8 +13,7 @@
  * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
index 5ea4326ad11f5d16901d49ff68ddc36648671bf4..2500e75583fcc26e6380731d407dc6d985ba6929 100644 (file)
@@ -13,8 +13,7 @@
  * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
index f023a133abb625bcecb171ae499cf43126edecaf..bba701cf10e6e28bf2efde0f2089c37131d88d01 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * 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;
+ * version 2.1 of the License (not later!)
+ *
+ * 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 Lesser 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,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index b1ccc923e8a50d47fdaf1cb766ab61197b8f37ef..a57db805136a2c205c6284d65045c2cbd5ee471d 100644 (file)
@@ -13,8 +13,7 @@
  * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
index ef6d22e879eb59dbf370096aaecda6d2344a42b0..eb30044a922a3fa2669371c859eadc231083635f 100644 (file)
@@ -222,10 +222,14 @@ install-pdf: pdf
 #install-html: html
 #      '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
 
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)
 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
        $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
 
 -include $(OUTPUT)PERF-VERSION-FILE
+endif
+endif
 
 #
 # Determine "include::" file references in asciidoc files.
index c8ffd9fd5c6afdd53d1722cd2cbd41737cee0992..5ad07ef417f0e28dd1ab0a5fb4d26940c7f707d0 100644 (file)
@@ -61,11 +61,13 @@ OPTIONS
 
 --stdio:: Use the stdio interface.
 
---tui:: Use the TUI interface Use of --tui requires a tty, if one is not
+--tui:: Use the TUI interface. Use of --tui requires a tty, if one is not
        present, as when piping to other commands, the stdio interface is
        used. This interfaces starts by centering on the line with more
        samples, TAB/UNTAB cycles through the lines with more samples.
 
+--gtk:: Use the GTK interface.
+
 -C::
 --cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
        be provided as a comma-separated list with no space: 0,1. Ranges of
@@ -88,6 +90,9 @@ OPTIONS
 --objdump=<path>::
         Path to objdump binary.
 
+--skip-missing::
+       Skip symbols that cannot be annotated.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-report[1]
index c1057701a7dc7d61e49f9b827d747e686a06bfd1..e9a8349a7172f7533fe970062c5936b4fd7df6fd 100644 (file)
@@ -24,6 +24,13 @@ OPTIONS
 -r::
 --remove=::
         Remove specified file from the cache.
+-M::
+--missing=:: 
+       List missing build ids in the cache for the specified file.
+-u::
+--update::
+       Update specified file of the cache. It can be used to update kallsyms
+       kernel dso to vmlinux in order to support annotation.
 -v::
 --verbose::
        Be more verbose.
index 194f37d635dfa3e543f21a37807f6be61e9e91bc..5b3123d5721f94286a62979a3aabad8c6c7a0e7f 100644 (file)
@@ -22,10 +22,6 @@ specified perf.data files.
 
 OPTIONS
 -------
--M::
---displacement::
-        Show position displacement relative to baseline.
-
 -D::
 --dump-raw-trace::
         Dump raw trace in ASCII.
index 15217345c2fab7d13a451ff08473d5faf29d7171..1ceb3700ffbb4f6807d5a77fa4071fedb0aa60f6 100644 (file)
@@ -28,6 +28,10 @@ OPTIONS
 --verbose=::
        Show all fields.
 
+-g::
+--group::
+       Show event group information.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-list[1],
index f4d91bebd59d4adc70272a3a11e25f9c42b827e1..02284a0067f0a416c2db23203ecfcc76ae7bd808 100644 (file)
@@ -57,11 +57,44 @@ OPTIONS
 
 -s::
 --sort=::
-       Sort by key(s): pid, comm, dso, symbol, parent, srcline.
+       Sort histogram entries by given key(s) - multiple keys can be specified
+       in CSV format.  Following sort keys are available:
+       pid, comm, dso, symbol, parent, cpu, srcline.
+
+       Each key has following meaning:
+
+       - comm: command (name) of the task which can be read via /proc/<pid>/comm
+       - pid: command and tid of the task
+       - dso: name of library or module executed at the time of sample
+       - symbol: name of function executed at the time of sample
+       - parent: name of function matched to the parent regex filter. Unmatched
+       entries are displayed as "[other]".
+       - cpu: cpu number the task ran at the time of sample
+       - srcline: filename and line number executed at the time of sample.  The
+       DWARF debuggin info must be provided.
+
+       By default, comm, dso and symbol keys are used.
+       (i.e. --sort comm,dso,symbol)
+
+       If --branch-stack option is used, following sort keys are also
+       available:
+       dso_from, dso_to, symbol_from, symbol_to, mispredict.
+
+       - dso_from: name of library or module branched from
+       - dso_to: name of library or module branched to
+       - symbol_from: name of function branched from
+       - symbol_to: name of function branched to
+       - mispredict: "N" for predicted branch, "Y" for mispredicted branch
+
+       And default sort keys are changed to comm, dso_from, symbol_from, dso_to
+       and symbol_to, see '--branch-stack'.
 
 -p::
 --parent=<regex>::
-        regex filter to identify parent, see: '--sort parent'
+        A regex filter to identify parent. The parent is a caller of this
+       function and searched through the callchain, thus it requires callchain
+       information recorded. The pattern is in the exteneded regex format and
+       defaults to "\^sys_|^do_page_fault", see '--sort parent'.
 
 -x::
 --exclude-other::
@@ -74,7 +107,6 @@ OPTIONS
 
 -t::
 --field-separator=::
-
        Use a special separator character and don't pad with spaces, replacing
        all occurrences of this separator in symbol names (and other output)
        with a '.' character, that thus it's the only non valid separator.
@@ -171,6 +203,9 @@ OPTIONS
 --objdump=<path>::
         Path to objdump binary.
 
+--group::
+       Show event group information together.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-annotate[1]
index a4027f221a535457c672f8e6d99ccb4fe1db0925..9f1f054b8432c7aaed29e0f905f58ab25db2d2a9 100644 (file)
@@ -336,7 +336,6 @@ scripts listed by the 'perf script -l' command e.g.:
 ----
 root@tropicana:~# perf script -l
 List of available trace scripts:
-  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
   wakeup-latency                       system-wide min/max/avg wakeup latency
   rw-by-file <comm>                    r/w activity for a program, by file
   rw-by-pid                            system-wide r/w activity
@@ -402,7 +401,6 @@ should show a new entry for your script:
 ----
 root@tropicana:~# perf script -l
 List of available trace scripts:
-  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
   wakeup-latency                       system-wide min/max/avg wakeup latency
   rw-by-file <comm>                    r/w activity for a program, by file
   rw-by-pid                            system-wide r/w activity
index cf0c3107e06e4737fd4c2fda1f3f81a2a4a08e95..faf4f4feebccf239ef02d198900c8bc0be54afd2 100644 (file)
@@ -114,6 +114,17 @@ with it.  --append may be used here.  Examples:
 
 perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- make -s -j64 O=defconfig-build/ bzImage
 
+-I msecs::
+--interval-print msecs::
+       Print count deltas every N milliseconds (minimum: 100ms)
+       example: perf stat -I 1000 -e cycles -a sleep 5
+
+--aggr-socket::
+Aggregate counts per processor socket for system-wide mode measurements.  This
+is a useful mode to detect imbalance between sockets.  To enable this mode,
+use --aggr-socket in addition to -a. (system-wide).  The output includes the
+socket number and the number of online processors on that socket. This is
+useful to gauge the amount of aggregation.
 
 EXAMPLES
 --------
index b24ac40fcd58cad9391ddee7495370e3eb2f814a..d1d3e5121f89ca0389229d0e4b63fd7f126145db 100644 (file)
@@ -23,6 +23,10 @@ from 'perf test list'.
 
 OPTIONS
 -------
+-s::
+--skip::
+       Tests to skip (comma separater numeric list).
+
 -v::
 --verbose::
        Be more verbose.
index 5b80d84d6b4a3e7e430499d0381c11a8856f316d..a414bc95fd528f89678c9221960a7f37170787bf 100644 (file)
@@ -60,7 +60,7 @@ Default is to monitor all CPUS.
 
 -i::
 --inherit::
-       Child tasks inherit counters, only makes sens with -p option.
+       Child tasks do not inherit counters.
 
 -k <path>::
 --vmlinux=<path>::
index 80db3f4bcf7a7d07a8233b535f43a4862fd40b21..39d41068484f963efc242cb3fc75649875f874f3 100644 (file)
@@ -11,11 +11,21 @@ lib/rbtree.c
 include/linux/swab.h
 arch/*/include/asm/unistd*.h
 arch/*/include/asm/perf_regs.h
+arch/*/include/uapi/asm/unistd*.h
+arch/*/include/uapi/asm/perf_regs.h
 arch/*/lib/memcpy*.S
 arch/*/lib/memset*.S
 include/linux/poison.h
 include/linux/magic.h
 include/linux/hw_breakpoint.h
+include/linux/rbtree_augmented.h
+include/uapi/linux/perf_event.h
+include/uapi/linux/const.h
+include/uapi/linux/swab.h
+include/uapi/linux/hw_breakpoint.h
 arch/x86/include/asm/svm.h
 arch/x86/include/asm/vmx.h
 arch/x86/include/asm/kvm_host.h
+arch/x86/include/uapi/asm/svm.h
+arch/x86/include/uapi/asm/vmx.h
+arch/x86/include/uapi/asm/kvm.h
index 891bc77bdb2cbba9910813c6df8866b1351a7734..a2108ca1cc17ad02e331aa02adf1870cc56a07ba 100644 (file)
@@ -47,10 +47,11 @@ include config/utilities.mak
 # backtrace post unwind.
 #
 # Define NO_BACKTRACE if you do not want stack backtrace debug feature
+#
+# Define NO_LIBNUMA if you do not want numa perf benchmark
 
 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
        @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
--include $(OUTPUT)PERF-VERSION-FILE
 
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 
@@ -58,7 +59,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                 -e s/sh[234].*/sh/ )
+                                 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 NO_PERF_REGS := 1
 
 CC = $(CROSS_COMPILE)gcc
@@ -148,13 +149,25 @@ RM = rm -f
 MKDIR = mkdir
 FIND = find
 INSTALL = install
+FLEX = flex
+BISON= bison
 
 # sparse is architecture-neutral, which means that we need to tell it
 # explicitly what architecture to check for. Fix this up for yours..
 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)
 -include config/feature-tests.mak
 
+ifeq ($(call get-executable,$(FLEX)),)
+       dummy := $(error Error: $(FLEX) is missing on this system, please install it)
+endif
+
+ifeq ($(call get-executable,$(BISON)),)
+       dummy := $(error Error: $(BISON) is missing on this system, please install it)
+endif
+
 ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
        CFLAGS := $(CFLAGS) -fstack-protector-all
 endif
@@ -206,6 +219,8 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
        EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
        BASIC_CFLAGS += -I.
 endif
+endif # MAKECMDGOALS != tags
+endif # MAKECMDGOALS != clean
 
 # Guard against environment variables
 BUILTIN_OBJS =
@@ -230,11 +245,19 @@ endif
 LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
 TE_LIB := -L$(TE_PATH) -ltraceevent
 
+export LIBTRACEEVENT
+
+# python extension build directories
+PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
+PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
+PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
+export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
+
+python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
+
 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; \
@@ -269,20 +292,17 @@ endif
 
 export PERL_PATH
 
-FLEX = flex
-BISON= bison
-
 $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
        $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
 
 $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
-       $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c
+       $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
 
 $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
        $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
 
 $(OUTPUT)util/pmu-bison.c: util/pmu.y
-       $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
+       $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
 
 $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
 $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
@@ -378,8 +398,11 @@ LIB_H += util/rblist.h
 LIB_H += util/intlist.h
 LIB_H += util/perf_regs.h
 LIB_H += util/unwind.h
-LIB_H += ui/helpline.h
 LIB_H += util/vdso.h
+LIB_H += ui/helpline.h
+LIB_H += ui/progress.h
+LIB_H += ui/util.h
+LIB_H += ui/ui.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -453,6 +476,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
 LIB_OBJS += $(OUTPUT)ui/progress.o
+LIB_OBJS += $(OUTPUT)ui/util.o
 LIB_OBJS += $(OUTPUT)ui/hist.o
 LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
 
@@ -471,7 +495,8 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o
 LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
 LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
 LIB_OBJS += $(OUTPUT)tests/pmu.o
-LIB_OBJS += $(OUTPUT)tests/util.o
+LIB_OBJS += $(OUTPUT)tests/hists_link.o
+LIB_OBJS += $(OUTPUT)tests/python-use.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -510,14 +535,13 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
 #
 # Platform specific tweaks
 #
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)
 
 # We choose to avoid "if .. else if .. else .. endif endif"
 # because maintaining the nesting to match is a pain.  If
 # we had "elif" things would have been much nicer...
 
--include config.mak.autogen
--include config.mak
-
 ifdef NO_LIBELF
        NO_DWARF := 1
        NO_DEMANGLE := 1
@@ -557,6 +581,11 @@ else
 endif # SOURCE_LIBELF
 endif # NO_LIBELF
 
+# There's only x86 (both 32 and 64) support for CFI unwind so far
+ifneq ($(ARCH),x86)
+       NO_LIBUNWIND := 1
+endif
+
 ifndef NO_LIBUNWIND
 # for linking with debug library, run like:
 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
@@ -646,7 +675,6 @@ ifndef NO_NEWT
                LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
                LIB_OBJS += $(OUTPUT)ui/browsers/map.o
                LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
-               LIB_OBJS += $(OUTPUT)ui/util.o
                LIB_OBJS += $(OUTPUT)ui/tui/setup.o
                LIB_OBJS += $(OUTPUT)ui/tui/util.o
                LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
@@ -655,9 +683,6 @@ ifndef NO_NEWT
                LIB_H += ui/browsers/map.h
                LIB_H += ui/keysyms.h
                LIB_H += ui/libslang.h
-               LIB_H += ui/progress.h
-               LIB_H += ui/util.h
-               LIB_H += ui/ui.h
        endif
 endif
 
@@ -673,14 +698,12 @@ ifndef NO_GTK2
                BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
                EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
                LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
+               LIB_OBJS += $(OUTPUT)ui/gtk/hists.o
                LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
                LIB_OBJS += $(OUTPUT)ui/gtk/util.o
                LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
                LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
-               # Make sure that it'd be included only once.
-               ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
-                       LIB_OBJS += $(OUTPUT)ui/util.o
-               endif
+               LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
        endif
 endif
 
@@ -707,7 +730,7 @@ disable-python = $(eval $(disable-python_code))
 define disable-python_code
   BASIC_CFLAGS += -DNO_LIBPYTHON
   $(if $(1),$(warning No $(1) was found))
-  $(warning Python support won't be built)
+  $(warning Python support will not be built)
 endef
 
 override PYTHON := \
@@ -715,19 +738,10 @@ override PYTHON := \
 
 ifndef PYTHON
   $(call disable-python,python interpreter)
-  python-clean :=
 else
 
   PYTHON_WORD := $(call shell-wordify,$(PYTHON))
 
-  # python extension build directories
-  PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
-  PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
-  PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
-  export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
-
-  python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
-
   ifdef NO_LIBPYTHON
     $(call disable-python)
   else
@@ -839,10 +853,24 @@ ifndef NO_BACKTRACE
        endif
 endif
 
+ifndef NO_LIBNUMA
+       FLAGS_LIBNUMA = $(ALL_CFLAGS) $(ALL_LDFLAGS) -lnuma
+       ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y)
+               msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
+       else
+               BASIC_CFLAGS += -DLIBNUMA_SUPPORT
+               BUILTIN_OBJS += $(OUTPUT)bench/numa.o
+               EXTLIBS += -lnuma
+       endif
+endif
+
 ifdef ASCIIDOC8
        export ASCIIDOC8
 endif
 
+endif # MAKECMDGOALS != tags
+endif # MAKECMDGOALS != clean
+
 # Shell quote (do not use $(call) to accommodate ancient setups);
 
 ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -884,7 +912,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
        $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
 
 $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
+       $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
                '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
                $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
 
@@ -948,7 +976,13 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
 
 $(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
-               '-DBINDIR="$(bindir_SQ)"' \
+               '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
+               $<
+
+$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
+               -DPYTHONPATH='"$(OUTPUT)python"' \
+               -DPYTHON='"$(PYTHON_WORD)"' \
                $<
 
 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
@@ -1099,7 +1133,7 @@ perfexec_instdir = $(prefix)/$(perfexecdir)
 endif
 perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
 
-install: all try-install-man
+install-bin: all
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
        $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
@@ -1120,6 +1154,8 @@ install: all try-install-man
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
        $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
 
+install: install-bin try-install-man
+
 install-python_ext:
        $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
 
index 3e975cb6232eb97b2d14a9d4f069653727a6d649..aacef07ebf31525227b372e6c40e9a3039c5d580 100644 (file)
@@ -155,6 +155,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
                if (lookup_path(buf))
                        goto out;
                free(buf);
+               buf = NULL;
        }
 
        if (!strcmp(arch, "arm"))
index 8f89998eeaf4eeb3fd45388f6aacd34438e2f1f8..a5223e6a7b432a0b04faf5ba5dfc130cd9ed150e 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef BENCH_H
 #define BENCH_H
 
+extern int bench_numa(int argc, const char **argv, const char *prefix);
 extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
 extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
 extern int bench_mem_memcpy(int argc, const char **argv,
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
new file mode 100644 (file)
index 0000000..30d1c32
--- /dev/null
@@ -0,0 +1,1731 @@
+/*
+ * numa.c
+ *
+ * numa: Simulate NUMA-sensitive workload and measure their NUMA performance
+ */
+
+#include "../perf.h"
+#include "../builtin.h"
+#include "../util/util.h"
+#include "../util/parse-options.h"
+
+#include "bench.h"
+
+#include <errno.h>
+#include <sched.h>
+#include <stdio.h>
+#include <assert.h>
+#include <malloc.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+
+#include <numa.h>
+#include <numaif.h>
+
+/*
+ * Regular printout to the terminal, supressed if -q is specified:
+ */
+#define tprintf(x...) do { if (g && g->p.show_details >= 0) printf(x); } while (0)
+
+/*
+ * Debug printf:
+ */
+#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0)
+
+struct thread_data {
+       int                     curr_cpu;
+       cpu_set_t               bind_cpumask;
+       int                     bind_node;
+       u8                      *process_data;
+       int                     process_nr;
+       int                     thread_nr;
+       int                     task_nr;
+       unsigned int            loops_done;
+       u64                     val;
+       u64                     runtime_ns;
+       pthread_mutex_t         *process_lock;
+};
+
+/* Parameters set by options: */
+
+struct params {
+       /* Startup synchronization: */
+       bool                    serialize_startup;
+
+       /* Task hierarchy: */
+       int                     nr_proc;
+       int                     nr_threads;
+
+       /* Working set sizes: */
+       const char              *mb_global_str;
+       const char              *mb_proc_str;
+       const char              *mb_proc_locked_str;
+       const char              *mb_thread_str;
+
+       double                  mb_global;
+       double                  mb_proc;
+       double                  mb_proc_locked;
+       double                  mb_thread;
+
+       /* Access patterns to the working set: */
+       bool                    data_reads;
+       bool                    data_writes;
+       bool                    data_backwards;
+       bool                    data_zero_memset;
+       bool                    data_rand_walk;
+       u32                     nr_loops;
+       u32                     nr_secs;
+       u32                     sleep_usecs;
+
+       /* Working set initialization: */
+       bool                    init_zero;
+       bool                    init_random;
+       bool                    init_cpu0;
+
+       /* Misc options: */
+       int                     show_details;
+       int                     run_all;
+       int                     thp;
+
+       long                    bytes_global;
+       long                    bytes_process;
+       long                    bytes_process_locked;
+       long                    bytes_thread;
+
+       int                     nr_tasks;
+       bool                    show_quiet;
+
+       bool                    show_convergence;
+       bool                    measure_convergence;
+
+       int                     perturb_secs;
+       int                     nr_cpus;
+       int                     nr_nodes;
+
+       /* Affinity options -C and -N: */
+       char                    *cpu_list_str;
+       char                    *node_list_str;
+};
+
+
+/* Global, read-writable area, accessible to all processes and threads: */
+
+struct global_info {
+       u8                      *data;
+
+       pthread_mutex_t         startup_mutex;
+       int                     nr_tasks_started;
+
+       pthread_mutex_t         startup_done_mutex;
+
+       pthread_mutex_t         start_work_mutex;
+       int                     nr_tasks_working;
+
+       pthread_mutex_t         stop_work_mutex;
+       u64                     bytes_done;
+
+       struct thread_data      *threads;
+
+       /* Convergence latency measurement: */
+       bool                    all_converged;
+       bool                    stop_work;
+
+       int                     print_once;
+
+       struct params           p;
+};
+
+static struct global_info      *g = NULL;
+
+static int parse_cpus_opt(const struct option *opt, const char *arg, int unset);
+static int parse_nodes_opt(const struct option *opt, const char *arg, int unset);
+
+struct params p0;
+
+static const struct option options[] = {
+       OPT_INTEGER('p', "nr_proc"      , &p0.nr_proc,          "number of processes"),
+       OPT_INTEGER('t', "nr_threads"   , &p0.nr_threads,       "number of threads per process"),
+
+       OPT_STRING('G', "mb_global"     , &p0.mb_global_str,    "MB", "global  memory (MBs)"),
+       OPT_STRING('P', "mb_proc"       , &p0.mb_proc_str,      "MB", "process memory (MBs)"),
+       OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"),
+       OPT_STRING('T', "mb_thread"     , &p0.mb_thread_str,    "MB", "thread  memory (MBs)"),
+
+       OPT_UINTEGER('l', "nr_loops"    , &p0.nr_loops,         "max number of loops to run"),
+       OPT_UINTEGER('s', "nr_secs"     , &p0.nr_secs,          "max number of seconds to run"),
+       OPT_UINTEGER('u', "usleep"      , &p0.sleep_usecs,      "usecs to sleep per loop iteration"),
+
+       OPT_BOOLEAN('R', "data_reads"   , &p0.data_reads,       "access the data via writes (can be mixed with -W)"),
+       OPT_BOOLEAN('W', "data_writes"  , &p0.data_writes,      "access the data via writes (can be mixed with -R)"),
+       OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards,  "access the data backwards as well"),
+       OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"),
+       OPT_BOOLEAN('r', "data_rand_walk", &p0.data_rand_walk,  "access the data with random (32bit LFSR) walk"),
+
+
+       OPT_BOOLEAN('z', "init_zero"    , &p0.init_zero,        "bzero the initial allocations"),
+       OPT_BOOLEAN('I', "init_random"  , &p0.init_random,      "randomize the contents of the initial allocations"),
+       OPT_BOOLEAN('0', "init_cpu0"    , &p0.init_cpu0,        "do the initial allocations on CPU#0"),
+       OPT_INTEGER('x', "perturb_secs", &p0.perturb_secs,      "perturb thread 0/0 every X secs, to test convergence stability"),
+
+       OPT_INCR   ('d', "show_details" , &p0.show_details,     "Show details"),
+       OPT_INCR   ('a', "all"          , &p0.run_all,          "Run all tests in the suite"),
+       OPT_INTEGER('H', "thp"          , &p0.thp,              "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
+       OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
+       OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"),
+       OPT_BOOLEAN('q', "quiet"        , &p0.show_quiet,       "bzero the initial allocations"),
+       OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
+
+       /* Special option string parsing callbacks: */
+        OPT_CALLBACK('C', "cpus", NULL, "cpu[,cpu2,...cpuN]",
+                       "bind the first N tasks to these specific cpus (the rest is unbound)",
+                       parse_cpus_opt),
+        OPT_CALLBACK('M', "memnodes", NULL, "node[,node2,...nodeN]",
+                       "bind the first N tasks to these specific memory nodes (the rest is unbound)",
+                       parse_nodes_opt),
+       OPT_END()
+};
+
+static const char * const bench_numa_usage[] = {
+       "perf bench numa <options>",
+       NULL
+};
+
+static const char * const numa_usage[] = {
+       "perf bench numa mem [<options>]",
+       NULL
+};
+
+static cpu_set_t bind_to_cpu(int target_cpu)
+{
+       cpu_set_t orig_mask, mask;
+       int ret;
+
+       ret = sched_getaffinity(0, sizeof(orig_mask), &orig_mask);
+       BUG_ON(ret);
+
+       CPU_ZERO(&mask);
+
+       if (target_cpu == -1) {
+               int cpu;
+
+               for (cpu = 0; cpu < g->p.nr_cpus; cpu++)
+                       CPU_SET(cpu, &mask);
+       } else {
+               BUG_ON(target_cpu < 0 || target_cpu >= g->p.nr_cpus);
+               CPU_SET(target_cpu, &mask);
+       }
+
+       ret = sched_setaffinity(0, sizeof(mask), &mask);
+       BUG_ON(ret);
+
+       return orig_mask;
+}
+
+static cpu_set_t bind_to_node(int target_node)
+{
+       int cpus_per_node = g->p.nr_cpus/g->p.nr_nodes;
+       cpu_set_t orig_mask, mask;
+       int cpu;
+       int ret;
+
+       BUG_ON(cpus_per_node*g->p.nr_nodes != g->p.nr_cpus);
+       BUG_ON(!cpus_per_node);
+
+       ret = sched_getaffinity(0, sizeof(orig_mask), &orig_mask);
+       BUG_ON(ret);
+
+       CPU_ZERO(&mask);
+
+       if (target_node == -1) {
+               for (cpu = 0; cpu < g->p.nr_cpus; cpu++)
+                       CPU_SET(cpu, &mask);
+       } else {
+               int cpu_start = (target_node + 0) * cpus_per_node;
+               int cpu_stop  = (target_node + 1) * cpus_per_node;
+
+               BUG_ON(cpu_stop > g->p.nr_cpus);
+
+               for (cpu = cpu_start; cpu < cpu_stop; cpu++)
+                       CPU_SET(cpu, &mask);
+       }
+
+       ret = sched_setaffinity(0, sizeof(mask), &mask);
+       BUG_ON(ret);
+
+       return orig_mask;
+}
+
+static void bind_to_cpumask(cpu_set_t mask)
+{
+       int ret;
+
+       ret = sched_setaffinity(0, sizeof(mask), &mask);
+       BUG_ON(ret);
+}
+
+static void mempol_restore(void)
+{
+       int ret;
+
+       ret = set_mempolicy(MPOL_DEFAULT, NULL, g->p.nr_nodes-1);
+
+       BUG_ON(ret);
+}
+
+static void bind_to_memnode(int node)
+{
+       unsigned long nodemask;
+       int ret;
+
+       if (node == -1)
+               return;
+
+       BUG_ON(g->p.nr_nodes > (int)sizeof(nodemask));
+       nodemask = 1L << node;
+
+       ret = set_mempolicy(MPOL_BIND, &nodemask, sizeof(nodemask)*8);
+       dprintf("binding to node %d, mask: %016lx => %d\n", node, nodemask, ret);
+
+       BUG_ON(ret);
+}
+
+#define HPSIZE (2*1024*1024)
+
+#define set_taskname(fmt...)                           \
+do {                                                   \
+       char name[20];                                  \
+                                                       \
+       snprintf(name, 20, fmt);                        \
+       prctl(PR_SET_NAME, name);                       \
+} while (0)
+
+static u8 *alloc_data(ssize_t bytes0, int map_flags,
+                     int init_zero, int init_cpu0, int thp, int init_random)
+{
+       cpu_set_t orig_mask;
+       ssize_t bytes;
+       u8 *buf;
+       int ret;
+
+       if (!bytes0)
+               return NULL;
+
+       /* Allocate and initialize all memory on CPU#0: */
+       if (init_cpu0) {
+               orig_mask = bind_to_node(0);
+               bind_to_memnode(0);
+       }
+
+       bytes = bytes0 + HPSIZE;
+
+       buf = (void *)mmap(0, bytes, PROT_READ|PROT_WRITE, MAP_ANON|map_flags, -1, 0);
+       BUG_ON(buf == (void *)-1);
+
+       if (map_flags == MAP_PRIVATE) {
+               if (thp > 0) {
+                       ret = madvise(buf, bytes, MADV_HUGEPAGE);
+                       if (ret && !g->print_once) {
+                               g->print_once = 1;
+                               printf("WARNING: Could not enable THP - do: 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled'\n");
+                       }
+               }
+               if (thp < 0) {
+                       ret = madvise(buf, bytes, MADV_NOHUGEPAGE);
+                       if (ret && !g->print_once) {
+                               g->print_once = 1;
+                               printf("WARNING: Could not disable THP: run a CONFIG_TRANSPARENT_HUGEPAGE kernel?\n");
+                       }
+               }
+       }
+
+       if (init_zero) {
+               bzero(buf, bytes);
+       } else {
+               /* Initialize random contents, different in each word: */
+               if (init_random) {
+                       u64 *wbuf = (void *)buf;
+                       long off = rand();
+                       long i;
+
+                       for (i = 0; i < bytes/8; i++)
+                               wbuf[i] = i + off;
+               }
+       }
+
+       /* Align to 2MB boundary: */
+       buf = (void *)(((unsigned long)buf + HPSIZE-1) & ~(HPSIZE-1));
+
+       /* Restore affinity: */
+       if (init_cpu0) {
+               bind_to_cpumask(orig_mask);
+               mempol_restore();
+       }
+
+       return buf;
+}
+
+static void free_data(void *data, ssize_t bytes)
+{
+       int ret;
+
+       if (!data)
+               return;
+
+       ret = munmap(data, bytes);
+       BUG_ON(ret);
+}
+
+/*
+ * Create a shared memory buffer that can be shared between processes, zeroed:
+ */
+static void * zalloc_shared_data(ssize_t bytes)
+{
+       return alloc_data(bytes, MAP_SHARED, 1, g->p.init_cpu0,  g->p.thp, g->p.init_random);
+}
+
+/*
+ * Create a shared memory buffer that can be shared between processes:
+ */
+static void * setup_shared_data(ssize_t bytes)
+{
+       return alloc_data(bytes, MAP_SHARED, 0, g->p.init_cpu0,  g->p.thp, g->p.init_random);
+}
+
+/*
+ * Allocate process-local memory - this will either be shared between
+ * threads of this process, or only be accessed by this thread:
+ */
+static void * setup_private_data(ssize_t bytes)
+{
+       return alloc_data(bytes, MAP_PRIVATE, 0, g->p.init_cpu0,  g->p.thp, g->p.init_random);
+}
+
+/*
+ * Return a process-shared (global) mutex:
+ */
+static void init_global_mutex(pthread_mutex_t *mutex)
+{
+       pthread_mutexattr_t attr;
+
+       pthread_mutexattr_init(&attr);
+       pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+       pthread_mutex_init(mutex, &attr);
+}
+
+static int parse_cpu_list(const char *arg)
+{
+       p0.cpu_list_str = strdup(arg);
+
+       dprintf("got CPU list: {%s}\n", p0.cpu_list_str);
+
+       return 0;
+}
+
+static void parse_setup_cpu_list(void)
+{
+       struct thread_data *td;
+       char *str0, *str;
+       int t;
+
+       if (!g->p.cpu_list_str)
+               return;
+
+       dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
+
+       str0 = str = strdup(g->p.cpu_list_str);
+       t = 0;
+
+       BUG_ON(!str);
+
+       tprintf("# binding tasks to CPUs:\n");
+       tprintf("#  ");
+
+       while (true) {
+               int bind_cpu, bind_cpu_0, bind_cpu_1;
+               char *tok, *tok_end, *tok_step, *tok_len, *tok_mul;
+               int bind_len;
+               int step;
+               int mul;
+
+               tok = strsep(&str, ",");
+               if (!tok)
+                       break;
+
+               tok_end = strstr(tok, "-");
+
+               dprintf("\ntoken: {%s}, end: {%s}\n", tok, tok_end);
+               if (!tok_end) {
+                       /* Single CPU specified: */
+                       bind_cpu_0 = bind_cpu_1 = atol(tok);
+               } else {
+                       /* CPU range specified (for example: "5-11"): */
+                       bind_cpu_0 = atol(tok);
+                       bind_cpu_1 = atol(tok_end + 1);
+               }
+
+               step = 1;
+               tok_step = strstr(tok, "#");
+               if (tok_step) {
+                       step = atol(tok_step + 1);
+                       BUG_ON(step <= 0 || step >= g->p.nr_cpus);
+               }
+
+               /*
+                * Mask length.
+                * Eg: "--cpus 8_4-16#4" means: '--cpus 8_4,12_4,16_4',
+                * where the _4 means the next 4 CPUs are allowed.
+                */
+               bind_len = 1;
+               tok_len = strstr(tok, "_");
+               if (tok_len) {
+                       bind_len = atol(tok_len + 1);
+                       BUG_ON(bind_len <= 0 || bind_len > g->p.nr_cpus);
+               }
+
+               /* Multiplicator shortcut, "0x8" is a shortcut for: "0,0,0,0,0,0,0,0" */
+               mul = 1;
+               tok_mul = strstr(tok, "x");
+               if (tok_mul) {
+                       mul = atol(tok_mul + 1);
+                       BUG_ON(mul <= 0);
+               }
+
+               dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul);
+
+               BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus);
+               BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus);
+               BUG_ON(bind_cpu_0 > bind_cpu_1);
+
+               for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) {
+                       int i;
+
+                       for (i = 0; i < mul; i++) {
+                               int cpu;
+
+                               if (t >= g->p.nr_tasks) {
+                                       printf("\n# NOTE: ignoring bind CPUs starting at CPU#%d\n #", bind_cpu);
+                                       goto out;
+                               }
+                               td = g->threads + t;
+
+                               if (t)
+                                       tprintf(",");
+                               if (bind_len > 1) {
+                                       tprintf("%2d/%d", bind_cpu, bind_len);
+                               } else {
+                                       tprintf("%2d", bind_cpu);
+                               }
+
+                               CPU_ZERO(&td->bind_cpumask);
+                               for (cpu = bind_cpu; cpu < bind_cpu+bind_len; cpu++) {
+                                       BUG_ON(cpu < 0 || cpu >= g->p.nr_cpus);
+                                       CPU_SET(cpu, &td->bind_cpumask);
+                               }
+                               t++;
+                       }
+               }
+       }
+out:
+
+       tprintf("\n");
+
+       if (t < g->p.nr_tasks)
+               printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
+
+       free(str0);
+}
+
+static int parse_cpus_opt(const struct option *opt __maybe_unused,
+                         const char *arg, int unset __maybe_unused)
+{
+       if (!arg)
+               return -1;
+
+       return parse_cpu_list(arg);
+}
+
+static int parse_node_list(const char *arg)
+{
+       p0.node_list_str = strdup(arg);
+
+       dprintf("got NODE list: {%s}\n", p0.node_list_str);
+
+       return 0;
+}
+
+static void parse_setup_node_list(void)
+{
+       struct thread_data *td;
+       char *str0, *str;
+       int t;
+
+       if (!g->p.node_list_str)
+               return;
+
+       dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
+
+       str0 = str = strdup(g->p.node_list_str);
+       t = 0;
+
+       BUG_ON(!str);
+
+       tprintf("# binding tasks to NODEs:\n");
+       tprintf("# ");
+
+       while (true) {
+               int bind_node, bind_node_0, bind_node_1;
+               char *tok, *tok_end, *tok_step, *tok_mul;
+               int step;
+               int mul;
+
+               tok = strsep(&str, ",");
+               if (!tok)
+                       break;
+
+               tok_end = strstr(tok, "-");
+
+               dprintf("\ntoken: {%s}, end: {%s}\n", tok, tok_end);
+               if (!tok_end) {
+                       /* Single NODE specified: */
+                       bind_node_0 = bind_node_1 = atol(tok);
+               } else {
+                       /* NODE range specified (for example: "5-11"): */
+                       bind_node_0 = atol(tok);
+                       bind_node_1 = atol(tok_end + 1);
+               }
+
+               step = 1;
+               tok_step = strstr(tok, "#");
+               if (tok_step) {
+                       step = atol(tok_step + 1);
+                       BUG_ON(step <= 0 || step >= g->p.nr_nodes);
+               }
+
+               /* Multiplicator shortcut, "0x8" is a shortcut for: "0,0,0,0,0,0,0,0" */
+               mul = 1;
+               tok_mul = strstr(tok, "x");
+               if (tok_mul) {
+                       mul = atol(tok_mul + 1);
+                       BUG_ON(mul <= 0);
+               }
+
+               dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step);
+
+               BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes);
+               BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes);
+               BUG_ON(bind_node_0 > bind_node_1);
+
+               for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) {
+                       int i;
+
+                       for (i = 0; i < mul; i++) {
+                               if (t >= g->p.nr_tasks) {
+                                       printf("\n# NOTE: ignoring bind NODEs starting at NODE#%d\n", bind_node);
+                                       goto out;
+                               }
+                               td = g->threads + t;
+
+                               if (!t)
+                                       tprintf(" %2d", bind_node);
+                               else
+                                       tprintf(",%2d", bind_node);
+
+                               td->bind_node = bind_node;
+                               t++;
+                       }
+               }
+       }
+out:
+
+       tprintf("\n");
+
+       if (t < g->p.nr_tasks)
+               printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
+
+       free(str0);
+}
+
+static int parse_nodes_opt(const struct option *opt __maybe_unused,
+                         const char *arg, int unset __maybe_unused)
+{
+       if (!arg)
+               return -1;
+
+       return parse_node_list(arg);
+
+       return 0;
+}
+
+#define BIT(x) (1ul << x)
+
+static inline uint32_t lfsr_32(uint32_t lfsr)
+{
+       const uint32_t taps = BIT(1) | BIT(5) | BIT(6) | BIT(31);
+       return (lfsr>>1) ^ ((0x0u - (lfsr & 0x1u)) & taps);
+}
+
+/*
+ * Make sure there's real data dependency to RAM (when read
+ * accesses are enabled), so the compiler, the CPU and the
+ * kernel (KSM, zero page, etc.) cannot optimize away RAM
+ * accesses:
+ */
+static inline u64 access_data(u64 *data __attribute__((unused)), u64 val)
+{
+       if (g->p.data_reads)
+               val += *data;
+       if (g->p.data_writes)
+               *data = val + 1;
+       return val;
+}
+
+/*
+ * The worker process does two types of work, a forwards going
+ * loop and a backwards going loop.
+ *
+ * We do this so that on multiprocessor systems we do not create
+ * a 'train' of processing, with highly synchronized processes,
+ * skewing the whole benchmark.
+ */
+static u64 do_work(u8 *__data, long bytes, int nr, int nr_max, int loop, u64 val)
+{
+       long words = bytes/sizeof(u64);
+       u64 *data = (void *)__data;
+       long chunk_0, chunk_1;
+       u64 *d0, *d, *d1;
+       long off;
+       long i;
+
+       BUG_ON(!data && words);
+       BUG_ON(data && !words);
+
+       if (!data)
+               return val;
+
+       /* Very simple memset() work variant: */
+       if (g->p.data_zero_memset && !g->p.data_rand_walk) {
+               bzero(data, bytes);
+               return val;
+       }
+
+       /* Spread out by PID/TID nr and by loop nr: */
+       chunk_0 = words/nr_max;
+       chunk_1 = words/g->p.nr_loops;
+       off = nr*chunk_0 + loop*chunk_1;
+
+       while (off >= words)
+               off -= words;
+
+       if (g->p.data_rand_walk) {
+               u32 lfsr = nr + loop + val;
+               int j;
+
+               for (i = 0; i < words/1024; i++) {
+                       long start, end;
+
+                       lfsr = lfsr_32(lfsr);
+
+                       start = lfsr % words;
+                       end = min(start + 1024, words-1);
+
+                       if (g->p.data_zero_memset) {
+                               bzero(data + start, (end-start) * sizeof(u64));
+                       } else {
+                               for (j = start; j < end; j++)
+                                       val = access_data(data + j, val);
+                       }
+               }
+       } else if (!g->p.data_backwards || (nr + loop) & 1) {
+
+               d0 = data + off;
+               d  = data + off + 1;
+               d1 = data + words;
+
+               /* Process data forwards: */
+               for (;;) {
+                       if (unlikely(d >= d1))
+                               d = data;
+                       if (unlikely(d == d0))
+                               break;
+
+                       val = access_data(d, val);
+
+                       d++;
+               }
+       } else {
+               /* Process data backwards: */
+
+               d0 = data + off;
+               d  = data + off - 1;
+               d1 = data + words;
+
+               /* Process data forwards: */
+               for (;;) {
+                       if (unlikely(d < data))
+                               d = data + words-1;
+                       if (unlikely(d == d0))
+                               break;
+
+                       val = access_data(d, val);
+
+                       d--;
+               }
+       }
+
+       return val;
+}
+
+static void update_curr_cpu(int task_nr, unsigned long bytes_worked)
+{
+       unsigned int cpu;
+
+       cpu = sched_getcpu();
+
+       g->threads[task_nr].curr_cpu = cpu;
+       prctl(0, bytes_worked);
+}
+
+#define MAX_NR_NODES   64
+
+/*
+ * Count the number of nodes a process's threads
+ * are spread out on.
+ *
+ * A count of 1 means that the process is compressed
+ * to a single node. A count of g->p.nr_nodes means it's
+ * spread out on the whole system.
+ */
+static int count_process_nodes(int process_nr)
+{
+       char node_present[MAX_NR_NODES] = { 0, };
+       int nodes;
+       int n, t;
+
+       for (t = 0; t < g->p.nr_threads; t++) {
+               struct thread_data *td;
+               int task_nr;
+               int node;
+
+               task_nr = process_nr*g->p.nr_threads + t;
+               td = g->threads + task_nr;
+
+               node = numa_node_of_cpu(td->curr_cpu);
+               node_present[node] = 1;
+       }
+
+       nodes = 0;
+
+       for (n = 0; n < MAX_NR_NODES; n++)
+               nodes += node_present[n];
+
+       return nodes;
+}
+
+/*
+ * Count the number of distinct process-threads a node contains.
+ *
+ * A count of 1 means that the node contains only a single
+ * process. If all nodes on the system contain at most one
+ * process then we are well-converged.
+ */
+static int count_node_processes(int node)
+{
+       int processes = 0;
+       int t, p;
+
+       for (p = 0; p < g->p.nr_proc; p++) {
+               for (t = 0; t < g->p.nr_threads; t++) {
+                       struct thread_data *td;
+                       int task_nr;
+                       int n;
+
+                       task_nr = p*g->p.nr_threads + t;
+                       td = g->threads + task_nr;
+
+                       n = numa_node_of_cpu(td->curr_cpu);
+                       if (n == node) {
+                               processes++;
+                               break;
+                       }
+               }
+       }
+
+       return processes;
+}
+
+static void calc_convergence_compression(int *strong)
+{
+       unsigned int nodes_min, nodes_max;
+       int p;
+
+       nodes_min = -1;
+       nodes_max =  0;
+
+       for (p = 0; p < g->p.nr_proc; p++) {
+               unsigned int nodes = count_process_nodes(p);
+
+               nodes_min = min(nodes, nodes_min);
+               nodes_max = max(nodes, nodes_max);
+       }
+
+       /* Strong convergence: all threads compress on a single node: */
+       if (nodes_min == 1 && nodes_max == 1) {
+               *strong = 1;
+       } else {
+               *strong = 0;
+               tprintf(" {%d-%d}", nodes_min, nodes_max);
+       }
+}
+
+static void calc_convergence(double runtime_ns_max, double *convergence)
+{
+       unsigned int loops_done_min, loops_done_max;
+       int process_groups;
+       int nodes[MAX_NR_NODES];
+       int distance;
+       int nr_min;
+       int nr_max;
+       int strong;
+       int sum;
+       int nr;
+       int node;
+       int cpu;
+       int t;
+
+       if (!g->p.show_convergence && !g->p.measure_convergence)
+               return;
+
+       for (node = 0; node < g->p.nr_nodes; node++)
+               nodes[node] = 0;
+
+       loops_done_min = -1;
+       loops_done_max = 0;
+
+       for (t = 0; t < g->p.nr_tasks; t++) {
+               struct thread_data *td = g->threads + t;
+               unsigned int loops_done;
+
+               cpu = td->curr_cpu;
+
+               /* Not all threads have written it yet: */
+               if (cpu < 0)
+                       continue;
+
+               node = numa_node_of_cpu(cpu);
+
+               nodes[node]++;
+
+               loops_done = td->loops_done;
+               loops_done_min = min(loops_done, loops_done_min);
+               loops_done_max = max(loops_done, loops_done_max);
+       }
+
+       nr_max = 0;
+       nr_min = g->p.nr_tasks;
+       sum = 0;
+
+       for (node = 0; node < g->p.nr_nodes; node++) {
+               nr = nodes[node];
+               nr_min = min(nr, nr_min);
+               nr_max = max(nr, nr_max);
+               sum += nr;
+       }
+       BUG_ON(nr_min > nr_max);
+
+       BUG_ON(sum > g->p.nr_tasks);
+
+       if (0 && (sum < g->p.nr_tasks))
+               return;
+
+       /*
+        * Count the number of distinct process groups present
+        * on nodes - when we are converged this will decrease
+        * to g->p.nr_proc:
+        */
+       process_groups = 0;
+
+       for (node = 0; node < g->p.nr_nodes; node++) {
+               int processes = count_node_processes(node);
+
+               nr = nodes[node];
+               tprintf(" %2d/%-2d", nr, processes);
+
+               process_groups += processes;
+       }
+
+       distance = nr_max - nr_min;
+
+       tprintf(" [%2d/%-2d]", distance, process_groups);
+
+       tprintf(" l:%3d-%-3d (%3d)",
+               loops_done_min, loops_done_max, loops_done_max-loops_done_min);
+
+       if (loops_done_min && loops_done_max) {
+               double skew = 1.0 - (double)loops_done_min/loops_done_max;
+
+               tprintf(" [%4.1f%%]", skew * 100.0);
+       }
+
+       calc_convergence_compression(&strong);
+
+       if (strong && process_groups == g->p.nr_proc) {
+               if (!*convergence) {
+                       *convergence = runtime_ns_max;
+                       tprintf(" (%6.1fs converged)\n", *convergence/1e9);
+                       if (g->p.measure_convergence) {
+                               g->all_converged = true;
+                               g->stop_work = true;
+                       }
+               }
+       } else {
+               if (*convergence) {
+                       tprintf(" (%6.1fs de-converged)", runtime_ns_max/1e9);
+                       *convergence = 0;
+               }
+               tprintf("\n");
+       }
+}
+
+static void show_summary(double runtime_ns_max, int l, double *convergence)
+{
+       tprintf("\r #  %5.1f%%  [%.1f mins]",
+               (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max/1e9 / 60.0);
+
+       calc_convergence(runtime_ns_max, convergence);
+
+       if (g->p.show_details >= 0)
+               fflush(stdout);
+}
+
+static void *worker_thread(void *__tdata)
+{
+       struct thread_data *td = __tdata;
+       struct timeval start0, start, stop, diff;
+       int process_nr = td->process_nr;
+       int thread_nr = td->thread_nr;
+       unsigned long last_perturbance;
+       int task_nr = td->task_nr;
+       int details = g->p.show_details;
+       int first_task, last_task;
+       double convergence = 0;
+       u64 val = td->val;
+       double runtime_ns_max;
+       u8 *global_data;
+       u8 *process_data;
+       u8 *thread_data;
+       u64 bytes_done;
+       long work_done;
+       u32 l;
+
+       bind_to_cpumask(td->bind_cpumask);
+       bind_to_memnode(td->bind_node);
+
+       set_taskname("thread %d/%d", process_nr, thread_nr);
+
+       global_data = g->data;
+       process_data = td->process_data;
+       thread_data = setup_private_data(g->p.bytes_thread);
+
+       bytes_done = 0;
+
+       last_task = 0;
+       if (process_nr == g->p.nr_proc-1 && thread_nr == g->p.nr_threads-1)
+               last_task = 1;
+
+       first_task = 0;
+       if (process_nr == 0 && thread_nr == 0)
+               first_task = 1;
+
+       if (details >= 2) {
+               printf("#  thread %2d / %2d global mem: %p, process mem: %p, thread mem: %p\n",
+                       process_nr, thread_nr, global_data, process_data, thread_data);
+       }
+
+       if (g->p.serialize_startup) {
+               pthread_mutex_lock(&g->startup_mutex);
+               g->nr_tasks_started++;
+               pthread_mutex_unlock(&g->startup_mutex);
+
+               /* Here we will wait for the main process to start us all at once: */
+               pthread_mutex_lock(&g->start_work_mutex);
+               g->nr_tasks_working++;
+
+               /* Last one wake the main process: */
+               if (g->nr_tasks_working == g->p.nr_tasks)
+                       pthread_mutex_unlock(&g->startup_done_mutex);
+
+               pthread_mutex_unlock(&g->start_work_mutex);
+       }
+
+       gettimeofday(&start0, NULL);
+
+       start = stop = start0;
+       last_perturbance = start.tv_sec;
+
+       for (l = 0; l < g->p.nr_loops; l++) {
+               start = stop;
+
+               if (g->stop_work)
+                       break;
+
+               val += do_work(global_data,  g->p.bytes_global,  process_nr, g->p.nr_proc,      l, val);
+               val += do_work(process_data, g->p.bytes_process, thread_nr,  g->p.nr_threads,   l, val);
+               val += do_work(thread_data,  g->p.bytes_thread,  0,          1,         l, val);
+
+               if (g->p.sleep_usecs) {
+                       pthread_mutex_lock(td->process_lock);
+                       usleep(g->p.sleep_usecs);
+                       pthread_mutex_unlock(td->process_lock);
+               }
+               /*
+                * Amount of work to be done under a process-global lock:
+                */
+               if (g->p.bytes_process_locked) {
+                       pthread_mutex_lock(td->process_lock);
+                       val += do_work(process_data, g->p.bytes_process_locked, thread_nr,  g->p.nr_threads,    l, val);
+                       pthread_mutex_unlock(td->process_lock);
+               }
+
+               work_done = g->p.bytes_global + g->p.bytes_process +
+                           g->p.bytes_process_locked + g->p.bytes_thread;
+
+               update_curr_cpu(task_nr, work_done);
+               bytes_done += work_done;
+
+               if (details < 0 && !g->p.perturb_secs && !g->p.measure_convergence && !g->p.nr_secs)
+                       continue;
+
+               td->loops_done = l;
+
+               gettimeofday(&stop, NULL);
+
+               /* Check whether our max runtime timed out: */
+               if (g->p.nr_secs) {
+                       timersub(&stop, &start0, &diff);
+                       if (diff.tv_sec >= g->p.nr_secs) {
+                               g->stop_work = true;
+                               break;
+                       }
+               }
+
+               /* Update the summary at most once per second: */
+               if (start.tv_sec == stop.tv_sec)
+                       continue;
+
+               /*
+                * Perturb the first task's equilibrium every g->p.perturb_secs seconds,
+                * by migrating to CPU#0:
+                */
+               if (first_task && g->p.perturb_secs && (int)(stop.tv_sec - last_perturbance) >= g->p.perturb_secs) {
+                       cpu_set_t orig_mask;
+                       int target_cpu;
+                       int this_cpu;
+
+                       last_perturbance = stop.tv_sec;
+
+                       /*
+                        * Depending on where we are running, move into
+                        * the other half of the system, to create some
+                        * real disturbance:
+                        */
+                       this_cpu = g->threads[task_nr].curr_cpu;
+                       if (this_cpu < g->p.nr_cpus/2)
+                               target_cpu = g->p.nr_cpus-1;
+                       else
+                               target_cpu = 0;
+
+                       orig_mask = bind_to_cpu(target_cpu);
+
+                       /* Here we are running on the target CPU already */
+                       if (details >= 1)
+                               printf(" (injecting perturbalance, moved to CPU#%d)\n", target_cpu);
+
+                       bind_to_cpumask(orig_mask);
+               }
+
+               if (details >= 3) {
+                       timersub(&stop, &start, &diff);
+                       runtime_ns_max = diff.tv_sec * 1000000000;
+                       runtime_ns_max += diff.tv_usec * 1000;
+
+                       if (details >= 0) {
+                               printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016lx]\n",
+                                       process_nr, thread_nr, runtime_ns_max / bytes_done, val);
+                       }
+                       fflush(stdout);
+               }
+               if (!last_task)
+                       continue;
+
+               timersub(&stop, &start0, &diff);
+               runtime_ns_max = diff.tv_sec * 1000000000ULL;
+               runtime_ns_max += diff.tv_usec * 1000ULL;
+
+               show_summary(runtime_ns_max, l, &convergence);
+       }
+
+       gettimeofday(&stop, NULL);
+       timersub(&stop, &start0, &diff);
+       td->runtime_ns = diff.tv_sec * 1000000000ULL;
+       td->runtime_ns += diff.tv_usec * 1000ULL;
+
+       free_data(thread_data, g->p.bytes_thread);
+
+       pthread_mutex_lock(&g->stop_work_mutex);
+       g->bytes_done += bytes_done;
+       pthread_mutex_unlock(&g->stop_work_mutex);
+
+       return NULL;
+}
+
+/*
+ * A worker process starts a couple of threads:
+ */
+static void worker_process(int process_nr)
+{
+       pthread_mutex_t process_lock;
+       struct thread_data *td;
+       pthread_t *pthreads;
+       u8 *process_data;
+       int task_nr;
+       int ret;
+       int t;
+
+       pthread_mutex_init(&process_lock, NULL);
+       set_taskname("process %d", process_nr);
+
+       /*
+        * Pick up the memory policy and the CPU binding of our first thread,
+        * so that we initialize memory accordingly:
+        */
+       task_nr = process_nr*g->p.nr_threads;
+       td = g->threads + task_nr;
+
+       bind_to_memnode(td->bind_node);
+       bind_to_cpumask(td->bind_cpumask);
+
+       pthreads = zalloc(g->p.nr_threads * sizeof(pthread_t));
+       process_data = setup_private_data(g->p.bytes_process);
+
+       if (g->p.show_details >= 3) {
+               printf(" # process %2d global mem: %p, process mem: %p\n",
+                       process_nr, g->data, process_data);
+       }
+
+       for (t = 0; t < g->p.nr_threads; t++) {
+               task_nr = process_nr*g->p.nr_threads + t;
+               td = g->threads + task_nr;
+
+               td->process_data = process_data;
+               td->process_nr   = process_nr;
+               td->thread_nr    = t;
+               td->task_nr      = task_nr;
+               td->val          = rand();
+               td->curr_cpu     = -1;
+               td->process_lock = &process_lock;
+
+               ret = pthread_create(pthreads + t, NULL, worker_thread, td);
+               BUG_ON(ret);
+       }
+
+       for (t = 0; t < g->p.nr_threads; t++) {
+                ret = pthread_join(pthreads[t], NULL);
+               BUG_ON(ret);
+       }
+
+       free_data(process_data, g->p.bytes_process);
+       free(pthreads);
+}
+
+static void print_summary(void)
+{
+       if (g->p.show_details < 0)
+               return;
+
+       printf("\n ###\n");
+       printf(" # %d %s will execute (on %d nodes, %d CPUs):\n",
+               g->p.nr_tasks, g->p.nr_tasks == 1 ? "task" : "tasks", g->p.nr_nodes, g->p.nr_cpus);
+       printf(" #      %5dx %5ldMB global  shared mem operations\n",
+                       g->p.nr_loops, g->p.bytes_global/1024/1024);
+       printf(" #      %5dx %5ldMB process shared mem operations\n",
+                       g->p.nr_loops, g->p.bytes_process/1024/1024);
+       printf(" #      %5dx %5ldMB thread  local  mem operations\n",
+                       g->p.nr_loops, g->p.bytes_thread/1024/1024);
+
+       printf(" ###\n");
+
+       printf("\n ###\n"); fflush(stdout);
+}
+
+static void init_thread_data(void)
+{
+       ssize_t size = sizeof(*g->threads)*g->p.nr_tasks;
+       int t;
+
+       g->threads = zalloc_shared_data(size);
+
+       for (t = 0; t < g->p.nr_tasks; t++) {
+               struct thread_data *td = g->threads + t;
+               int cpu;
+
+               /* Allow all nodes by default: */
+               td->bind_node = -1;
+
+               /* Allow all CPUs by default: */
+               CPU_ZERO(&td->bind_cpumask);
+               for (cpu = 0; cpu < g->p.nr_cpus; cpu++)
+                       CPU_SET(cpu, &td->bind_cpumask);
+       }
+}
+
+static void deinit_thread_data(void)
+{
+       ssize_t size = sizeof(*g->threads)*g->p.nr_tasks;
+
+       free_data(g->threads, size);
+}
+
+static int init(void)
+{
+       g = (void *)alloc_data(sizeof(*g), MAP_SHARED, 1, 0, 0 /* THP */, 0);
+
+       /* Copy over options: */
+       g->p = p0;
+
+       g->p.nr_cpus = numa_num_configured_cpus();
+
+       g->p.nr_nodes = numa_max_node() + 1;
+
+       /* char array in count_process_nodes(): */
+       BUG_ON(g->p.nr_nodes > MAX_NR_NODES || g->p.nr_nodes < 0);
+
+       if (g->p.show_quiet && !g->p.show_details)
+               g->p.show_details = -1;
+
+       /* Some memory should be specified: */
+       if (!g->p.mb_global_str && !g->p.mb_proc_str && !g->p.mb_thread_str)
+               return -1;
+
+       if (g->p.mb_global_str) {
+               g->p.mb_global = atof(g->p.mb_global_str);
+               BUG_ON(g->p.mb_global < 0);
+       }
+
+       if (g->p.mb_proc_str) {
+               g->p.mb_proc = atof(g->p.mb_proc_str);
+               BUG_ON(g->p.mb_proc < 0);
+       }
+
+       if (g->p.mb_proc_locked_str) {
+               g->p.mb_proc_locked = atof(g->p.mb_proc_locked_str);
+               BUG_ON(g->p.mb_proc_locked < 0);
+               BUG_ON(g->p.mb_proc_locked > g->p.mb_proc);
+       }
+
+       if (g->p.mb_thread_str) {
+               g->p.mb_thread = atof(g->p.mb_thread_str);
+               BUG_ON(g->p.mb_thread < 0);
+       }
+
+       BUG_ON(g->p.nr_threads <= 0);
+       BUG_ON(g->p.nr_proc <= 0);
+
+       g->p.nr_tasks = g->p.nr_proc*g->p.nr_threads;
+
+       g->p.bytes_global               = g->p.mb_global        *1024L*1024L;
+       g->p.bytes_process              = g->p.mb_proc          *1024L*1024L;
+       g->p.bytes_process_locked       = g->p.mb_proc_locked   *1024L*1024L;
+       g->p.bytes_thread               = g->p.mb_thread        *1024L*1024L;
+
+       g->data = setup_shared_data(g->p.bytes_global);
+
+       /* Startup serialization: */
+       init_global_mutex(&g->start_work_mutex);
+       init_global_mutex(&g->startup_mutex);
+       init_global_mutex(&g->startup_done_mutex);
+       init_global_mutex(&g->stop_work_mutex);
+
+       init_thread_data();
+
+       tprintf("#\n");
+       parse_setup_cpu_list();
+       parse_setup_node_list();
+       tprintf("#\n");
+
+       print_summary();
+
+       return 0;
+}
+
+static void deinit(void)
+{
+       free_data(g->data, g->p.bytes_global);
+       g->data = NULL;
+
+       deinit_thread_data();
+
+       free_data(g, sizeof(*g));
+       g = NULL;
+}
+
+/*
+ * Print a short or long result, depending on the verbosity setting:
+ */
+static void print_res(const char *name, double val,
+                     const char *txt_unit, const char *txt_short, const char *txt_long)
+{
+       if (!name)
+               name = "main,";
+
+       if (g->p.show_quiet)
+               printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short);
+       else
+               printf(" %14.3f %s\n", val, txt_long);
+}
+
+static int __bench_numa(const char *name)
+{
+       struct timeval start, stop, diff;
+       u64 runtime_ns_min, runtime_ns_sum;
+       pid_t *pids, pid, wpid;
+       double delta_runtime;
+       double runtime_avg;
+       double runtime_sec_max;
+       double runtime_sec_min;
+       int wait_stat;
+       double bytes;
+       int i, t;
+
+       if (init())
+               return -1;
+
+       pids = zalloc(g->p.nr_proc * sizeof(*pids));
+       pid = -1;
+
+       /* All threads try to acquire it, this way we can wait for them to start up: */
+       pthread_mutex_lock(&g->start_work_mutex);
+
+       if (g->p.serialize_startup) {
+               tprintf(" #\n");
+               tprintf(" # Startup synchronization: ..."); fflush(stdout);
+       }
+
+       gettimeofday(&start, NULL);
+
+       for (i = 0; i < g->p.nr_proc; i++) {
+               pid = fork();
+               dprintf(" # process %2d: PID %d\n", i, pid);
+
+               BUG_ON(pid < 0);
+               if (!pid) {
+                       /* Child process: */
+                       worker_process(i);
+
+                       exit(0);
+               }
+               pids[i] = pid;
+
+       }
+       /* Wait for all the threads to start up: */
+       while (g->nr_tasks_started != g->p.nr_tasks)
+               usleep(1000);
+
+       BUG_ON(g->nr_tasks_started != g->p.nr_tasks);
+
+       if (g->p.serialize_startup) {
+               double startup_sec;
+
+               pthread_mutex_lock(&g->startup_done_mutex);
+
+               /* This will start all threads: */
+               pthread_mutex_unlock(&g->start_work_mutex);
+
+               /* This mutex is locked - the last started thread will wake us: */
+               pthread_mutex_lock(&g->startup_done_mutex);
+
+               gettimeofday(&stop, NULL);
+
+               timersub(&stop, &start, &diff);
+
+               startup_sec = diff.tv_sec * 1000000000.0;
+               startup_sec += diff.tv_usec * 1000.0;
+               startup_sec /= 1e9;
+
+               tprintf(" threads initialized in %.6f seconds.\n", startup_sec);
+               tprintf(" #\n");
+
+               start = stop;
+               pthread_mutex_unlock(&g->startup_done_mutex);
+       } else {
+               gettimeofday(&start, NULL);
+       }
+
+       /* Parent process: */
+
+
+       for (i = 0; i < g->p.nr_proc; i++) {
+               wpid = waitpid(pids[i], &wait_stat, 0);
+               BUG_ON(wpid < 0);
+               BUG_ON(!WIFEXITED(wait_stat));
+
+       }
+
+       runtime_ns_sum = 0;
+       runtime_ns_min = -1LL;
+
+       for (t = 0; t < g->p.nr_tasks; t++) {
+               u64 thread_runtime_ns = g->threads[t].runtime_ns;
+
+               runtime_ns_sum += thread_runtime_ns;
+               runtime_ns_min = min(thread_runtime_ns, runtime_ns_min);
+       }
+
+       gettimeofday(&stop, NULL);
+       timersub(&stop, &start, &diff);
+
+       BUG_ON(bench_format != BENCH_FORMAT_DEFAULT);
+
+       tprintf("\n ###\n");
+       tprintf("\n");
+
+       runtime_sec_max = diff.tv_sec * 1000000000.0;
+       runtime_sec_max += diff.tv_usec * 1000.0;
+       runtime_sec_max /= 1e9;
+
+       runtime_sec_min = runtime_ns_min/1e9;
+
+       bytes = g->bytes_done;
+       runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / 1e9;
+
+       if (g->p.measure_convergence) {
+               print_res(name, runtime_sec_max,
+                       "secs,", "NUMA-convergence-latency", "secs latency to NUMA-converge");
+       }
+
+       print_res(name, runtime_sec_max,
+               "secs,", "runtime-max/thread",  "secs slowest (max) thread-runtime");
+
+       print_res(name, runtime_sec_min,
+               "secs,", "runtime-min/thread",  "secs fastest (min) thread-runtime");
+
+       print_res(name, runtime_avg,
+               "secs,", "runtime-avg/thread",  "secs average thread-runtime");
+
+       delta_runtime = (runtime_sec_max - runtime_sec_min)/2.0;
+       print_res(name, delta_runtime / runtime_sec_max * 100.0,
+               "%,", "spread-runtime/thread",  "% difference between max/avg runtime");
+
+       print_res(name, bytes / g->p.nr_tasks / 1e9,
+               "GB,", "data/thread",           "GB data processed, per thread");
+
+       print_res(name, bytes / 1e9,
+               "GB,", "data-total",            "GB data processed, total");
+
+       print_res(name, runtime_sec_max * 1e9 / (bytes / g->p.nr_tasks),
+               "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime");
+
+       print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max,
+               "GB/sec,", "thread-speed",      "GB/sec/thread speed");
+
+       print_res(name, bytes / runtime_sec_max / 1e9,
+               "GB/sec,", "total-speed",       "GB/sec total speed");
+
+       free(pids);
+
+       deinit();
+
+       return 0;
+}
+
+#define MAX_ARGS 50
+
+static int command_size(const char **argv)
+{
+       int size = 0;
+
+       while (*argv) {
+               size++;
+               argv++;
+       }
+
+       BUG_ON(size >= MAX_ARGS);
+
+       return size;
+}
+
+static void init_params(struct params *p, const char *name, int argc, const char **argv)
+{
+       int i;
+
+       printf("\n # Running %s \"perf bench numa", name);
+
+       for (i = 0; i < argc; i++)
+               printf(" %s", argv[i]);
+
+       printf("\"\n");
+
+       memset(p, 0, sizeof(*p));
+
+       /* Initialize nonzero defaults: */
+
+       p->serialize_startup            = 1;
+       p->data_reads                   = true;
+       p->data_writes                  = true;
+       p->data_backwards               = true;
+       p->data_rand_walk               = true;
+       p->nr_loops                     = -1;
+       p->init_random                  = true;
+}
+
+static int run_bench_numa(const char *name, const char **argv)
+{
+       int argc = command_size(argv);
+
+       init_params(&p0, name, argc, argv);
+       argc = parse_options(argc, argv, options, bench_numa_usage, 0);
+       if (argc)
+               goto err;
+
+       if (__bench_numa(name))
+               goto err;
+
+       return 0;
+
+err:
+       usage_with_options(numa_usage, options);
+       return -1;
+}
+
+#define OPT_BW_RAM             "-s",  "20", "-zZq",    "--thp", " 1", "--no-data_rand_walk"
+#define OPT_BW_RAM_NOTHP       OPT_BW_RAM,             "--thp", "-1"
+
+#define OPT_CONV               "-s", "100", "-zZ0qcm", "--thp", " 1"
+#define OPT_CONV_NOTHP         OPT_CONV,               "--thp", "-1"
+
+#define OPT_BW                 "-s",  "20", "-zZ0q",   "--thp", " 1"
+#define OPT_BW_NOTHP           OPT_BW,                 "--thp", "-1"
+
+/*
+ * The built-in test-suite executed by "perf bench numa -a".
+ *
+ * (A minimum of 4 nodes and 16 GB of RAM is recommended.)
+ */
+static const char *tests[][MAX_ARGS] = {
+   /* Basic single-stream NUMA bandwidth measurements: */
+   { "RAM-bw-local,",    "mem",  "-p",  "1",  "-t",  "1", "-P", "1024",
+                         "-C" ,   "0", "-M",   "0", OPT_BW_RAM },
+   { "RAM-bw-local-NOTHP,",
+                         "mem",  "-p",  "1",  "-t",  "1", "-P", "1024",
+                         "-C" ,   "0", "-M",   "0", OPT_BW_RAM_NOTHP },
+   { "RAM-bw-remote,",   "mem",  "-p",  "1",  "-t",  "1", "-P", "1024",
+                         "-C" ,   "0", "-M",   "1", OPT_BW_RAM },
+
+   /* 2-stream NUMA bandwidth measurements: */
+   { "RAM-bw-local-2x,",  "mem",  "-p",  "2",  "-t",  "1", "-P", "1024",
+                          "-C", "0,2", "-M", "0x2", OPT_BW_RAM },
+   { "RAM-bw-remote-2x,", "mem",  "-p",  "2",  "-t",  "1", "-P", "1024",
+                          "-C", "0,2", "-M", "1x2", OPT_BW_RAM },
+
+   /* Cross-stream NUMA bandwidth measurement: */
+   { "RAM-bw-cross,",     "mem",  "-p",  "2",  "-t",  "1", "-P", "1024",
+                          "-C", "0,8", "-M", "1,0", OPT_BW_RAM },
+
+   /* Convergence latency measurements: */
+   { " 1x3-convergence,", "mem",  "-p",  "1", "-t",  "3", "-P",  "512", OPT_CONV },
+   { " 1x4-convergence,", "mem",  "-p",  "1", "-t",  "4", "-P",  "512", OPT_CONV },
+   { " 1x6-convergence,", "mem",  "-p",  "1", "-t",  "6", "-P", "1020", OPT_CONV },
+   { " 2x3-convergence,", "mem",  "-p",  "3", "-t",  "3", "-P", "1020", OPT_CONV },
+   { " 3x3-convergence,", "mem",  "-p",  "3", "-t",  "3", "-P", "1020", OPT_CONV },
+   { " 4x4-convergence,", "mem",  "-p",  "4", "-t",  "4", "-P",  "512", OPT_CONV },
+   { " 4x4-convergence-NOTHP,",
+                         "mem",  "-p",  "4", "-t",  "4", "-P",  "512", OPT_CONV_NOTHP },
+   { " 4x6-convergence,", "mem",  "-p",  "4", "-t",  "6", "-P", "1020", OPT_CONV },
+   { " 4x8-convergence,", "mem",  "-p",  "4", "-t",  "8", "-P",  "512", OPT_CONV },
+   { " 8x4-convergence,", "mem",  "-p",  "8", "-t",  "4", "-P",  "512", OPT_CONV },
+   { " 8x4-convergence-NOTHP,",
+                         "mem",  "-p",  "8", "-t",  "4", "-P",  "512", OPT_CONV_NOTHP },
+   { " 3x1-convergence,", "mem",  "-p",  "3", "-t",  "1", "-P",  "512", OPT_CONV },
+   { " 4x1-convergence,", "mem",  "-p",  "4", "-t",  "1", "-P",  "512", OPT_CONV },
+   { " 8x1-convergence,", "mem",  "-p",  "8", "-t",  "1", "-P",  "512", OPT_CONV },
+   { "16x1-convergence,", "mem",  "-p", "16", "-t",  "1", "-P",  "256", OPT_CONV },
+   { "32x1-convergence,", "mem",  "-p", "32", "-t",  "1", "-P",  "128", OPT_CONV },
+
+   /* Various NUMA process/thread layout bandwidth measurements: */
+   { " 2x1-bw-process,",  "mem",  "-p",  "2", "-t",  "1", "-P", "1024", OPT_BW },
+   { " 3x1-bw-process,",  "mem",  "-p",  "3", "-t",  "1", "-P", "1024", OPT_BW },
+   { " 4x1-bw-process,",  "mem",  "-p",  "4", "-t",  "1", "-P", "1024", OPT_BW },
+   { " 8x1-bw-process,",  "mem",  "-p",  "8", "-t",  "1", "-P", " 512", OPT_BW },
+   { " 8x1-bw-process-NOTHP,",
+                         "mem",  "-p",  "8", "-t",  "1", "-P", " 512", OPT_BW_NOTHP },
+   { "16x1-bw-process,",  "mem",  "-p", "16", "-t",  "1", "-P",  "256", OPT_BW },
+
+   { " 4x1-bw-thread,",          "mem",  "-p",  "1", "-t",  "4", "-T",  "256", OPT_BW },
+   { " 8x1-bw-thread,",          "mem",  "-p",  "1", "-t",  "8", "-T",  "256", OPT_BW },
+   { "16x1-bw-thread,",   "mem",  "-p",  "1", "-t", "16", "-T",  "128", OPT_BW },
+   { "32x1-bw-thread,",   "mem",  "-p",  "1", "-t", "32", "-T",   "64", OPT_BW },
+
+   { " 2x3-bw-thread,",          "mem",  "-p",  "2", "-t",  "3", "-P",  "512", OPT_BW },
+   { " 4x4-bw-thread,",          "mem",  "-p",  "4", "-t",  "4", "-P",  "512", OPT_BW },
+   { " 4x6-bw-thread,",          "mem",  "-p",  "4", "-t",  "6", "-P",  "512", OPT_BW },
+   { " 4x8-bw-thread,",          "mem",  "-p",  "4", "-t",  "8", "-P",  "512", OPT_BW },
+   { " 4x8-bw-thread-NOTHP,",
+                         "mem",  "-p",  "4", "-t",  "8", "-P",  "512", OPT_BW_NOTHP },
+   { " 3x3-bw-thread,",          "mem",  "-p",  "3", "-t",  "3", "-P",  "512", OPT_BW },
+   { " 5x5-bw-thread,",          "mem",  "-p",  "5", "-t",  "5", "-P",  "512", OPT_BW },
+
+   { "2x16-bw-thread,",   "mem",  "-p",  "2", "-t", "16", "-P",  "512", OPT_BW },
+   { "1x32-bw-thread,",   "mem",  "-p",  "1", "-t", "32", "-P", "2048", OPT_BW },
+
+   { "numa02-bw,",       "mem",  "-p",  "1", "-t", "32", "-T",   "32", OPT_BW },
+   { "numa02-bw-NOTHP,",  "mem",  "-p",  "1", "-t", "32", "-T",   "32", OPT_BW_NOTHP },
+   { "numa01-bw-thread,", "mem",  "-p",  "2", "-t", "16", "-T",  "192", OPT_BW },
+   { "numa01-bw-thread-NOTHP,",
+                         "mem",  "-p",  "2", "-t", "16", "-T",  "192", OPT_BW_NOTHP },
+};
+
+static int bench_all(void)
+{
+       int nr = ARRAY_SIZE(tests);
+       int ret;
+       int i;
+
+       ret = system("echo ' #'; echo ' # Running test on: '$(uname -a); echo ' #'");
+       BUG_ON(ret < 0);
+
+       for (i = 0; i < nr; i++) {
+               if (run_bench_numa(tests[i][0], tests[i] + 1))
+                       return -1;
+       }
+
+       printf("\n");
+
+       return 0;
+}
+
+int bench_numa(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+       init_params(&p0, "main,", argc, argv);
+       argc = parse_options(argc, argv, options, bench_numa_usage, 0);
+       if (argc)
+               goto err;
+
+       if (p0.run_all)
+               return bench_all();
+
+       if (__bench_numa(NULL))
+               goto err;
+
+       return 0;
+
+err:
+       usage_with_options(numa_usage, options);
+       return -1;
+}
index dc870cf31b79beefa01c777680efb761c0ed3377..2e6961ea3184f510e4f51143168bc1ea8eb607ae 100644 (file)
 
 struct perf_annotate {
        struct perf_tool tool;
-       bool       force, use_tui, use_stdio;
+       bool       force, use_tui, use_stdio, use_gtk;
        bool       full_paths;
        bool       print_line;
+       bool       skip_missing;
        const char *sym_hist_filter;
        const char *cpu_list;
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -138,9 +139,22 @@ find_next:
                        continue;
                }
 
-               if (use_browser > 0) {
+               if (use_browser == 2) {
+                       int ret;
+
+                       ret = hist_entry__gtk_annotate(he, evidx, NULL);
+                       if (!ret || !ann->skip_missing)
+                               return;
+
+                       /* skip missing symbols */
+                       nd = rb_next(nd);
+               } else if (use_browser == 1) {
                        key = hist_entry__tui_annotate(he, evidx, NULL);
                        switch (key) {
+                       case -1:
+                               if (!ann->skip_missing)
+                                       return;
+                               /* fall through */
                        case K_RIGHT:
                                next = rb_next(nd);
                                break;
@@ -224,6 +238,10 @@ static int __cmd_annotate(struct perf_annotate *ann)
                ui__error("The %s file has no samples!\n", session->filename);
                goto out_delete;
        }
+
+       if (use_browser == 2)
+               perf_gtk__show_annotations();
+
 out_delete:
        /*
         * Speed up the exit process, for large files this can
@@ -270,6 +288,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
+       OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
        OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
        OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -280,6 +299,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                    "print matching source lines (may be slow)"),
        OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
                    "Don't shorten the displayed pathnames"),
+       OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
+                   "Skip symbols that cannot be annotated"),
        OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                   "Look for files with symbols relative to this directory"),
@@ -300,6 +321,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                use_browser = 0;
        else if (annotate.use_tui)
                use_browser = 1;
+       else if (annotate.use_gtk)
+               use_browser = 2;
 
        setup_browser(true);
 
@@ -309,7 +332,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
        if (symbol__init() < 0)
                return -1;
 
-       setup_sorting(annotate_usage, options);
+       if (setup_sorting() < 0)
+               usage_with_options(annotate_usage, options);
 
        if (argc) {
                /*
index cae9a5fd2ecfe97489a079146746727719eeb372..77298bf892b85c68d3c662cfe62e050518630a49 100644 (file)
@@ -35,6 +35,18 @@ struct bench_suite {
 /* sentinel: easy for help */
 #define suite_all { "all", "Test all benchmark suites", NULL }
 
+#ifdef LIBNUMA_SUPPORT
+static struct bench_suite numa_suites[] = {
+       { "mem",
+         "Benchmark for NUMA workloads",
+         bench_numa },
+       suite_all,
+       { NULL,
+         NULL,
+         NULL                  }
+};
+#endif
+
 static struct bench_suite sched_suites[] = {
        { "messaging",
          "Benchmark for scheduler and IPC mechanisms",
@@ -68,6 +80,11 @@ struct bench_subsys {
 };
 
 static struct bench_subsys subsystems[] = {
+#ifdef LIBNUMA_SUPPORT
+       { "numa",
+         "NUMA scheduling and MM behavior",
+         numa_suites },
+#endif
        { "sched",
          "scheduler and IPC mechanism",
          sched_suites },
@@ -159,6 +176,7 @@ static void all_suite(struct bench_subsys *subsys)    /* FROM HERE */
                printf("# Running %s/%s benchmark...\n",
                       subsys->name,
                       suites[i].name);
+               fflush(stdout);
 
                argv[1] = suites[i].name;
                suites[i].fn(1, argv, NULL);
@@ -225,6 +243,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
                                printf("# Running %s/%s benchmark...\n",
                                       subsystems[i].name,
                                       subsystems[i].suites[j].name);
+                       fflush(stdout);
                        status = subsystems[i].suites[j].fn(argc - 1,
                                                            argv + 1, prefix);
                        goto end;
index fae8b250b2ca711a8581fd70ab2142a1ddd5e9e5..c96c8fa3824353f1c5401cd2a6bacb9701a2762e 100644 (file)
@@ -14,6 +14,7 @@
 #include "util/parse-options.h"
 #include "util/strlist.h"
 #include "util/build-id.h"
+#include "util/session.h"
 #include "util/symbol.h"
 
 static int build_id_cache__add_file(const char *filename, const char *debugdir)
@@ -58,19 +59,89 @@ static int build_id_cache__remove_file(const char *filename,
        return err;
 }
 
+static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
+{
+       char filename[PATH_MAX];
+       u8 build_id[BUILD_ID_SIZE];
+
+       if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
+           filename__read_build_id(filename, build_id,
+                                   sizeof(build_id)) != sizeof(build_id)) {
+               if (errno == ENOENT)
+                       return false;
+
+               pr_warning("Problems with %s file, consider removing it from the cache\n", 
+                          filename);
+       } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
+               pr_warning("Problems with %s file, consider removing it from the cache\n", 
+                          filename);
+       }
+
+       return true;
+}
+
+static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
+{
+       struct perf_session *session = perf_session__new(filename, O_RDONLY,
+                                                        force, false, NULL);
+       if (session == NULL)
+               return -1;
+
+       perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
+       perf_session__delete(session);
+
+       return 0;
+}
+
+static int build_id_cache__update_file(const char *filename,
+                                      const char *debugdir)
+{
+       u8 build_id[BUILD_ID_SIZE];
+       char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
+       int err;
+
+       if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
+               pr_debug("Couldn't read a build-id in %s\n", filename);
+               return -1;
+       }
+
+       build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
+       err = build_id_cache__remove_s(sbuild_id, debugdir);
+       if (!err) {
+               err = build_id_cache__add_s(sbuild_id, debugdir, filename,
+                                           false, false);
+       }
+       if (verbose)
+               pr_info("Updating %s %s: %s\n", sbuild_id, filename,
+                       err ? "FAIL" : "Ok");
+
+       return err;
+}
+
 int cmd_buildid_cache(int argc, const char **argv,
                      const char *prefix __maybe_unused)
 {
        struct strlist *list;
        struct str_node *pos;
+       int ret = 0;
+       bool force = false;
        char debugdir[PATH_MAX];
        char const *add_name_list_str = NULL,
-                  *remove_name_list_str = NULL;
+                  *remove_name_list_str = NULL,
+                  *missing_filename = NULL,
+                  *update_name_list_str = NULL;
+
        const struct option buildid_cache_options[] = {
        OPT_STRING('a', "add", &add_name_list_str,
                   "file list", "file(s) to add"),
        OPT_STRING('r', "remove", &remove_name_list_str, "file list",
                    "file(s) to remove"),
+       OPT_STRING('M', "missing", &missing_filename, "file",
+                  "to find missing build ids in the cache"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+       OPT_STRING('u', "update", &update_name_list_str, "file list",
+                   "file(s) to update"),
        OPT_INCR('v', "verbose", &verbose, "be more verbose"),
        OPT_END()
        };
@@ -125,5 +196,26 @@ int cmd_buildid_cache(int argc, const char **argv,
                }
        }
 
-       return 0;
+       if (missing_filename)
+               ret = build_id_cache__fprintf_missing(missing_filename, force, stdout);
+
+       if (update_name_list_str) {
+               list = strlist__new(true, update_name_list_str);
+               if (list) {
+                       strlist__for_each(pos, list)
+                               if (build_id_cache__update_file(pos->s, debugdir)) {
+                                       if (errno == ENOENT) {
+                                               pr_debug("%s wasn't in the cache\n",
+                                                        pos->s);
+                                               continue;
+                                       }
+                                       pr_warning("Couldn't update %s: %s\n",
+                                                  pos->s, strerror(errno));
+                               }
+
+                       strlist__delete(list);
+               }
+       }
+
+       return ret;
 }
index a82d99fec83e2b2f9b1e9ea1d941847baa5243fc..e74366a13218dbc5da8ef576b298d8bcc21c4ed6 100644 (file)
@@ -44,23 +44,26 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
        return fprintf(fp, "%s\n", sbuild_id);
 }
 
+static bool dso__skip_buildid(struct dso *dso, int with_hits)
+{
+       return with_hits && !dso->hit;
+}
+
 static int perf_session__list_build_ids(bool force, bool with_hits)
 {
        struct perf_session *session;
 
        symbol__elf_init();
-
-       session = perf_session__new(input_name, O_RDONLY, force, false,
-                                   &build_id__mark_dso_hit_ops);
-       if (session == NULL)
-               return -1;
-
        /*
         * See if this is an ELF file first:
         */
-       if (filename__fprintf_build_id(session->filename, stdout))
+       if (filename__fprintf_build_id(input_name, stdout))
                goto out;
 
+       session = perf_session__new(input_name, O_RDONLY, force, false,
+                                   &build_id__mark_dso_hit_ops);
+       if (session == NULL)
+               return -1;
        /*
         * in pipe-mode, the only way to get the buildids is to parse
         * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
@@ -68,9 +71,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
        if (with_hits || session->fd_pipe)
                perf_session__process_events(session, &build_id__mark_dso_hit_ops);
 
-       perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
-out:
+       perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
        perf_session__delete(session);
+out:
        return 0;
 }
 
index 93b852f8a5d5936c902a720ed74cde4904bfa781..d207a97a2db1e96887418f354961d947bfecb7c2 100644 (file)
@@ -23,7 +23,6 @@ static char const *input_old = "perf.data.old",
                  *input_new = "perf.data";
 static char      diff__default_sort_order[] = "dso,symbol";
 static bool  force;
-static bool show_displacement;
 static bool show_period;
 static bool show_formula;
 static bool show_baseline_only;
@@ -146,58 +145,47 @@ static int setup_compute(const struct option *opt, const char *str,
        return -EINVAL;
 }
 
-static double get_period_percent(struct hist_entry *he, u64 period)
+double perf_diff__period_percent(struct hist_entry *he, u64 period)
 {
        u64 total = he->hists->stats.total_period;
        return (period * 100.0) / total;
 }
 
-double perf_diff__compute_delta(struct hist_entry *he)
+double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
-       double new_percent = get_period_percent(he, he->stat.period);
-       double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
+       double new_percent = perf_diff__period_percent(he, he->stat.period);
+       double old_percent = perf_diff__period_percent(pair, pair->stat.period);
 
        he->diff.period_ratio_delta = new_percent - old_percent;
        he->diff.computed = true;
        return he->diff.period_ratio_delta;
 }
 
-double perf_diff__compute_ratio(struct hist_entry *he)
+double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
        double new_period = he->stat.period;
-       double old_period = pair ? pair->stat.period : 0;
+       double old_period = pair->stat.period;
 
        he->diff.computed = true;
-       he->diff.period_ratio = pair ? (new_period / old_period) : 0;
+       he->diff.period_ratio = new_period / old_period;
        return he->diff.period_ratio;
 }
 
-s64 perf_diff__compute_wdiff(struct hist_entry *he)
+s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
        u64 new_period = he->stat.period;
-       u64 old_period = pair ? pair->stat.period : 0;
+       u64 old_period = pair->stat.period;
 
        he->diff.computed = true;
-
-       if (!pair)
-               he->diff.wdiff = 0;
-       else
-               he->diff.wdiff = new_period * compute_wdiff_w2 -
-                                old_period * compute_wdiff_w1;
+       he->diff.wdiff = new_period * compute_wdiff_w2 -
+                        old_period * compute_wdiff_w1;
 
        return he->diff.wdiff;
 }
 
-static int formula_delta(struct hist_entry *he, char *buf, size_t size)
+static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
+                        char *buf, size_t size)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
-
-       if (!pair)
-               return -1;
-
        return scnprintf(buf, size,
                         "(%" PRIu64 " * 100 / %" PRIu64 ") - "
                         "(%" PRIu64 " * 100 / %" PRIu64 ")",
@@ -205,41 +193,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size)
                          pair->stat.period, pair->hists->stats.total_period);
 }
 
-static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
+static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
+                        char *buf, size_t size)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
        double new_period = he->stat.period;
-       double old_period = pair ? pair->stat.period : 0;
-
-       if (!pair)
-               return -1;
+       double old_period = pair->stat.period;
 
        return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
 }
 
-static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
+static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
+                        char *buf, size_t size)
 {
-       struct hist_entry *pair = hist_entry__next_pair(he);
        u64 new_period = he->stat.period;
-       u64 old_period = pair ? pair->stat.period : 0;
-
-       if (!pair)
-               return -1;
+       u64 old_period = pair->stat.period;
 
        return scnprintf(buf, size,
                  "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
                  new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
 }
 
-int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
+int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
+                      char *buf, size_t size)
 {
        switch (compute) {
        case COMPUTE_DELTA:
-               return formula_delta(he, buf, size);
+               return formula_delta(he, pair, buf, size);
        case COMPUTE_RATIO:
-               return formula_ratio(he, buf, size);
+               return formula_ratio(he, pair, buf, size);
        case COMPUTE_WEIGHTED_DIFF:
-               return formula_wdiff(he, buf, size);
+               return formula_wdiff(he, pair, buf, size);
        default:
                BUG_ON(1);
        }
@@ -292,48 +275,6 @@ static struct perf_tool tool = {
        .ordering_requires_timestamps = true,
 };
 
-static void insert_hist_entry_by_name(struct rb_root *root,
-                                     struct hist_entry *he)
-{
-       struct rb_node **p = &root->rb_node;
-       struct rb_node *parent = NULL;
-       struct hist_entry *iter;
-
-       while (*p != NULL) {
-               parent = *p;
-               iter = rb_entry(parent, struct hist_entry, rb_node);
-               if (hist_entry__cmp(he, iter) < 0)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
-
-       rb_link_node(&he->rb_node, parent, p);
-       rb_insert_color(&he->rb_node, root);
-}
-
-static void hists__name_resort(struct hists *self, bool sort)
-{
-       unsigned long position = 1;
-       struct rb_root tmp = RB_ROOT;
-       struct rb_node *next = rb_first(&self->entries);
-
-       while (next != NULL) {
-               struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
-
-               next = rb_next(&n->rb_node);
-               n->position = position++;
-
-               if (sort) {
-                       rb_erase(&n->rb_node, &self->entries);
-                       insert_hist_entry_by_name(&tmp, n);
-               }
-       }
-
-       if (sort)
-               self->entries = tmp;
-}
-
 static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
                                      struct perf_evlist *evlist)
 {
@@ -346,34 +287,34 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
        return NULL;
 }
 
-static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
+static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
        list_for_each_entry(evsel, &evlist->entries, node) {
                struct hists *hists = &evsel->hists;
 
-               hists__output_resort(hists);
-
-               /*
-                * The hists__name_resort only sets possition
-                * if name is false.
-                */
-               if (name || ((!name) && show_displacement))
-                       hists__name_resort(hists, name);
+               hists__collapse_resort(hists);
        }
 }
 
 static void hists__baseline_only(struct hists *hists)
 {
-       struct rb_node *next = rb_first(&hists->entries);
+       struct rb_root *root;
+       struct rb_node *next;
 
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       next = rb_first(root);
        while (next != NULL) {
-               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
 
-               next = rb_next(&he->rb_node);
+               next = rb_next(&he->rb_node_in);
                if (!hist_entry__next_pair(he)) {
-                       rb_erase(&he->rb_node, &hists->entries);
+                       rb_erase(&he->rb_node_in, root);
                        hist_entry__free(he);
                }
        }
@@ -385,18 +326,21 @@ static void hists__precompute(struct hists *hists)
 
        while (next != NULL) {
                struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+               struct hist_entry *pair = hist_entry__next_pair(he);
 
                next = rb_next(&he->rb_node);
+               if (!pair)
+                       continue;
 
                switch (compute) {
                case COMPUTE_DELTA:
-                       perf_diff__compute_delta(he);
+                       perf_diff__compute_delta(he, pair);
                        break;
                case COMPUTE_RATIO:
-                       perf_diff__compute_ratio(he);
+                       perf_diff__compute_ratio(he, pair);
                        break;
                case COMPUTE_WEIGHTED_DIFF:
-                       perf_diff__compute_wdiff(he);
+                       perf_diff__compute_wdiff(he, pair);
                        break;
                default:
                        BUG_ON(1);
@@ -470,19 +414,30 @@ static void insert_hist_entry_by_compute(struct rb_root *root,
 
 static void hists__compute_resort(struct hists *hists)
 {
-       struct rb_root tmp = RB_ROOT;
-       struct rb_node *next = rb_first(&hists->entries);
+       struct rb_root *root;
+       struct rb_node *next;
+
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       hists->entries = RB_ROOT;
+       next = rb_first(root);
+
+       hists->nr_entries = 0;
+       hists->stats.total_period = 0;
+       hists__reset_col_len(hists);
 
        while (next != NULL) {
-               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+               struct hist_entry *he;
 
-               next = rb_next(&he->rb_node);
+               he = rb_entry(next, struct hist_entry, rb_node_in);
+               next = rb_next(&he->rb_node_in);
 
-               rb_erase(&he->rb_node, &hists->entries);
-               insert_hist_entry_by_compute(&tmp, he, compute);
+               insert_hist_entry_by_compute(&hists->entries, he, compute);
+               hists__inc_nr_entries(hists, he);
        }
-
-       hists->entries = tmp;
 }
 
 static void hists__process(struct hists *old, struct hists *new)
@@ -497,6 +452,8 @@ static void hists__process(struct hists *old, struct hists *new)
        if (sort_compute) {
                hists__precompute(new);
                hists__compute_resort(new);
+       } else {
+               hists__output_resort(new);
        }
 
        hists__fprintf(new, true, 0, 0, stdout);
@@ -528,8 +485,8 @@ static int __cmd_diff(void)
        evlist_old = older->evlist;
        evlist_new = newer->evlist;
 
-       perf_evlist__resort_hists(evlist_old, true);
-       perf_evlist__resort_hists(evlist_new, false);
+       perf_evlist__collapse_resort(evlist_old);
+       perf_evlist__collapse_resort(evlist_new);
 
        list_for_each_entry(evsel, &evlist_new->entries, node) {
                struct perf_evsel *evsel_old;
@@ -562,8 +519,6 @@ static const char * const diff_usage[] = {
 static const struct option options[] = {
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show symbol address, etc)"),
-       OPT_BOOLEAN('M', "displacement", &show_displacement,
-                   "Show position displacement relative to baseline"),
        OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
                    "Show only items with match in baseline"),
        OPT_CALLBACK('c', "compute", &compute,
@@ -597,40 +552,32 @@ static const struct option options[] = {
 
 static void ui_init(void)
 {
-       perf_hpp__init();
-
-       /* No overhead column. */
-       perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
-
        /*
-        * Display baseline/delta/ratio/displacement/
+        * Display baseline/delta/ratio
         * formula/periods columns.
         */
-       perf_hpp__column_enable(PERF_HPP__BASELINE, true);
+       perf_hpp__column_enable(PERF_HPP__BASELINE);
 
        switch (compute) {
        case COMPUTE_DELTA:
-               perf_hpp__column_enable(PERF_HPP__DELTA, true);
+               perf_hpp__column_enable(PERF_HPP__DELTA);
                break;
        case COMPUTE_RATIO:
-               perf_hpp__column_enable(PERF_HPP__RATIO, true);
+               perf_hpp__column_enable(PERF_HPP__RATIO);
                break;
        case COMPUTE_WEIGHTED_DIFF:
-               perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+               perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
                break;
        default:
                BUG_ON(1);
        };
 
-       if (show_displacement)
-               perf_hpp__column_enable(PERF_HPP__DISPL, true);
-
        if (show_formula)
-               perf_hpp__column_enable(PERF_HPP__FORMULA, true);
+               perf_hpp__column_enable(PERF_HPP__FORMULA);
 
        if (show_period) {
-               perf_hpp__column_enable(PERF_HPP__PERIOD, true);
-               perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
+               perf_hpp__column_enable(PERF_HPP__PERIOD);
+               perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
        }
 }
 
@@ -658,7 +605,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 
        ui_init();
 
-       setup_sorting(diff_usage, options);
+       if (setup_sorting() < 0)
+               usage_with_options(diff_usage, options);
+
        setup_pager();
 
        sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", NULL);
index c20f1dcfb7e226f3348727c9957d3260554a032d..05bd9dfe875cb95aeb6d2008b3319c2e8ca8f5eb 100644 (file)
 #include "util/parse-options.h"
 #include "util/session.h"
 
-struct perf_attr_details {
-       bool freq;
-       bool verbose;
-};
-
-static int comma_printf(bool *first, const char *fmt, ...)
-{
-       va_list args;
-       int ret = 0;
-
-       if (!*first) {
-               ret += printf(",");
-       } else {
-               ret += printf(":");
-               *first = false;
-       }
-
-       va_start(args, fmt);
-       ret += vprintf(fmt, args);
-       va_end(args);
-       return ret;
-}
-
-static int __if_print(bool *first, const char *field, u64 value)
-{
-       if (value == 0)
-               return 0;
-
-       return comma_printf(first, " %s: %" PRIu64, field, value);
-}
-
-#define if_print(field) __if_print(&first, #field, pos->attr.field)
-
 static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
 {
        struct perf_session *session;
@@ -57,52 +24,8 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
        if (session == NULL)
                return -ENOMEM;
 
-       list_for_each_entry(pos, &session->evlist->entries, node) {
-               bool first = true;
-
-               printf("%s", perf_evsel__name(pos));
-
-               if (details->verbose || details->freq) {
-                       comma_printf(&first, " sample_freq=%" PRIu64,
-                                    (u64)pos->attr.sample_freq);
-               }
-
-               if (details->verbose) {
-                       if_print(type);
-                       if_print(config);
-                       if_print(config1);
-                       if_print(config2);
-                       if_print(size);
-                       if_print(sample_type);
-                       if_print(read_format);
-                       if_print(disabled);
-                       if_print(inherit);
-                       if_print(pinned);
-                       if_print(exclusive);
-                       if_print(exclude_user);
-                       if_print(exclude_kernel);
-                       if_print(exclude_hv);
-                       if_print(exclude_idle);
-                       if_print(mmap);
-                       if_print(comm);
-                       if_print(freq);
-                       if_print(inherit_stat);
-                       if_print(enable_on_exec);
-                       if_print(task);
-                       if_print(watermark);
-                       if_print(precise_ip);
-                       if_print(mmap_data);
-                       if_print(sample_id_all);
-                       if_print(exclude_host);
-                       if_print(exclude_guest);
-                       if_print(__reserved_1);
-                       if_print(wakeup_events);
-                       if_print(bp_type);
-                       if_print(branch_sample_type);
-               }
-
-               putchar('\n');
-       }
+       list_for_each_entry(pos, &session->evlist->entries, node)
+               perf_evsel__fprintf(pos, details, stdout);
 
        perf_session__delete(session);
        return 0;
@@ -116,6 +39,8 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
        OPT_BOOLEAN('v', "verbose", &details.verbose,
                    "Show all event attr details"),
+       OPT_BOOLEAN('g', "group", &details.event_group,
+                   "Show event group information"),
        OPT_END()
        };
        const char * const evlist_usage[] = {
@@ -127,5 +52,10 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
        if (argc)
                usage_with_options(evlist_usage, options);
 
+       if (details.event_group && (details.verbose || details.freq)) {
+               pr_err("--group option is not compatible with other options\n");
+               usage_with_options(evlist_usage, options);
+       }
+
        return __cmd_evlist(input_name, &details);
 }
index 0b4b796167beca45dc12736527fa7bcfe2560d9e..46878daca5cc723b3200763e023744e87c7dc2fd 100644 (file)
@@ -17,6 +17,7 @@
 #include "util/debug.h"
 
 #include <linux/rbtree.h>
+#include <linux/string.h>
 
 struct alloc_stat;
 typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
@@ -340,7 +341,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
                           int n_lines, int is_caller)
 {
        struct rb_node *next;
-       struct machine *machine;
+       struct machine *machine = &session->machines.host;
 
        printf("%.102s\n", graph_dotted_line);
        printf(" %-34s |",  is_caller ? "Callsite": "Alloc Ptr");
@@ -349,11 +350,6 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
 
        next = rb_first(root);
 
-       machine = perf_session__find_host_machine(session);
-       if (!machine) {
-               pr_err("__print_result: couldn't find kernel information\n");
-               return;
-       }
        while (next && n_lines--) {
                struct alloc_stat *data = rb_entry(next, struct alloc_stat,
                                                   node);
@@ -614,8 +610,7 @@ static struct sort_dimension *avail_sorts[] = {
        &pingpong_sort_dimension,
 };
 
-#define NUM_AVAIL_SORTS        \
-       (int)(sizeof(avail_sorts) / sizeof(struct sort_dimension *))
+#define NUM_AVAIL_SORTS        ((int)ARRAY_SIZE(avail_sorts))
 
 static int sort_dimension__add(const char *tok, struct list_head *list)
 {
@@ -624,12 +619,11 @@ static int sort_dimension__add(const char *tok, struct list_head *list)
 
        for (i = 0; i < NUM_AVAIL_SORTS; i++) {
                if (!strcmp(avail_sorts[i]->name, tok)) {
-                       sort = malloc(sizeof(*sort));
+                       sort = memdup(avail_sorts[i], sizeof(*avail_sorts[i]));
                        if (!sort) {
-                               pr_err("%s: malloc failed\n", __func__);
+                               pr_err("%s: memdup failed\n", __func__);
                                return -1;
                        }
-                       memcpy(sort, avail_sorts[i], sizeof(*sort));
                        list_add_tail(&sort->list, list);
                        return 0;
                }
index ca3f80ebc100ce271007940cf32a4f16856f1628..37a769d7f9fead5a666e3124acf94a5570e505fd 100644 (file)
@@ -973,8 +973,7 @@ __cmd_buildid_list(const char *file_name, int argc, const char **argv)
 
 int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       const char *file_name;
-
+       const char *file_name = NULL;
        const struct option kvm_options[] = {
                OPT_STRING('i', "input", &file_name, "file",
                           "Input file name"),
index f3151d3c70ce15c6b93e57a8c3ebe0f70425f0a8..774c90713a53fe8a27f0561a8476d5c23748edab 100644 (file)
@@ -224,130 +224,28 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
 
 static int perf_record__open(struct perf_record *rec)
 {
+       char msg[512];
        struct perf_evsel *pos;
        struct perf_evlist *evlist = rec->evlist;
        struct perf_session *session = rec->session;
        struct perf_record_opts *opts = &rec->opts;
        int rc = 0;
 
-       /*
-        * Set the evsel leader links before we configure attributes,
-        * since some might depend on this info.
-        */
-       if (opts->group)
-               perf_evlist__set_leader(evlist);
-
-       perf_evlist__config_attrs(evlist, opts);
+       perf_evlist__config(evlist, opts);
 
        list_for_each_entry(pos, &evlist->entries, node) {
-               struct perf_event_attr *attr = &pos->attr;
-               /*
-                * Check if parse_single_tracepoint_event has already asked for
-                * PERF_SAMPLE_TIME.
-                *
-                * XXX this is kludgy but short term fix for problems introduced by
-                * eac23d1c that broke 'perf script' by having different sample_types
-                * when using multiple tracepoint events when we use a perf binary
-                * that tries to use sample_id_all on an older kernel.
-                *
-                * We need to move counter creation to perf_session, support
-                * different sample_types, etc.
-                */
-               bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
-
-fallback_missing_features:
-               if (opts->exclude_guest_missing)
-                       attr->exclude_guest = attr->exclude_host = 0;
-retry_sample_id:
-               attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
 try_again:
                if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
-                       int err = errno;
-
-                       if (err == EPERM || err == EACCES) {
-                               ui__error_paranoid();
-                               rc = -err;
-                               goto out;
-                       } else if (err ==  ENODEV && opts->target.cpu_list) {
-                               pr_err("No such device - did you specify"
-                                      " an out-of-range profile CPU?\n");
-                               rc = -err;
-                               goto out;
-                       } else if (err == EINVAL) {
-                               if (!opts->exclude_guest_missing &&
-                                   (attr->exclude_guest || attr->exclude_host)) {
-                                       pr_debug("Old kernel, cannot exclude "
-                                                "guest or host samples.\n");
-                                       opts->exclude_guest_missing = true;
-                                       goto fallback_missing_features;
-                               } else if (!opts->sample_id_all_missing) {
-                                       /*
-                                        * Old kernel, no attr->sample_id_type_all field
-                                        */
-                                       opts->sample_id_all_missing = true;
-                                       if (!opts->sample_time && !opts->raw_samples && !time_needed)
-                                               attr->sample_type &= ~PERF_SAMPLE_TIME;
-
-                                       goto retry_sample_id;
-                               }
-                       }
-
-                       /*
-                        * If it's cycles then fall back to hrtimer
-                        * based cpu-clock-tick sw counter, which
-                        * is always available even if no PMU support.
-                        *
-                        * PPC returns ENXIO until 2.6.37 (behavior changed
-                        * with commit b0a873e).
-                        */
-                       if ((err == ENOENT || err == ENXIO)
-                                       && attr->type == PERF_TYPE_HARDWARE
-                                       && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
-
+                       if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
                                if (verbose)
-                                       ui__warning("The cycles event is not supported, "
-                                                   "trying to fall back to cpu-clock-ticks\n");
-                               attr->type = PERF_TYPE_SOFTWARE;
-                               attr->config = PERF_COUNT_SW_CPU_CLOCK;
-                               if (pos->name) {
-                                       free(pos->name);
-                                       pos->name = NULL;
-                               }
+                                       ui__warning("%s\n", msg);
                                goto try_again;
                        }
 
-                       if (err == ENOENT) {
-                               ui__error("The %s event is not supported.\n",
-                                         perf_evsel__name(pos));
-                               rc = -err;
-                               goto out;
-                       } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
-                               ui__error("\'precise\' request may not be supported. "
-                                         "Try removing 'p' modifier\n");
-                               rc = -err;
-                               goto out;
-                       }
-
-                       printf("\n");
-                       error("sys_perf_event_open() syscall returned with %d "
-                             "(%s) for event %s. /bin/dmesg may provide "
-                             "additional information.\n",
-                             err, strerror(err), perf_evsel__name(pos));
-
-#if defined(__i386__) || defined(__x86_64__)
-                       if (attr->type == PERF_TYPE_HARDWARE &&
-                           err == EOPNOTSUPP) {
-                               pr_err("No hardware sampling interrupt available."
-                                      " No APIC? If so then you can boot the kernel"
-                                      " with the \"lapic\" boot parameter to"
-                                      " force-enable it.\n");
-                               rc = -err;
-                               goto out;
-                       }
-#endif
-
-                       pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
-                       rc = -err;
+                       rc = -errno;
+                       perf_evsel__open_strerror(pos, &opts->target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
                        goto out;
                }
        }
@@ -430,10 +328,6 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
        int err;
        struct perf_tool *tool = data;
-
-       if (machine__is_host(machine))
-               return;
-
        /*
         *As for guest kernel when processing subcommand record&report,
         *we arrange module mmap prior to guest kernel mmap and trigger
@@ -592,6 +486,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                goto out_delete_session;
        }
 
+       if (!evsel_list->nr_groups)
+               perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
+
        /*
         * perf_session__delete(session) will be called at perf_record__exit()
         */
@@ -618,12 +515,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 
        rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
 
-       machine = perf_session__find_host_machine(session);
-       if (!machine) {
-               pr_err("Couldn't find native kernel information.\n");
-               err = -1;
-               goto out_delete_session;
-       }
+       machine = &session->machines.host;
 
        if (opts->pipe_output) {
                err = perf_event__synthesize_attrs(tool, session,
@@ -676,9 +568,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
                       "Check /proc/modules permission or run as root.\n");
 
-       if (perf_guest)
-               perf_session__process_machines(session, tool,
-                                              perf_event__synthesize_guest_os);
+       if (perf_guest) {
+               machines__process_guests(&session->machines,
+                                        perf_event__synthesize_guest_os, tool);
+       }
 
        if (!opts->target.system_wide)
                err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
@@ -875,11 +768,10 @@ static int get_stack_size(char *str, unsigned long *_size)
 }
 #endif /* LIBUNWIND_SUPPORT */
 
-static int
-parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
-                   int unset)
+int record_parse_callchain_opt(const struct option *opt,
+                              const char *arg, int unset)
 {
-       struct perf_record *rec = (struct perf_record *)opt->value;
+       struct perf_record_opts *opts = opt->value;
        char *tok, *name, *saveptr = NULL;
        char *buf;
        int ret = -1;
@@ -905,7 +797,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
                /* Framepointer style */
                if (!strncmp(name, "fp", sizeof("fp"))) {
                        if (!strtok_r(NULL, ",", &saveptr)) {
-                               rec->opts.call_graph = CALLCHAIN_FP;
+                               opts->call_graph = CALLCHAIN_FP;
                                ret = 0;
                        } else
                                pr_err("callchain: No more arguments "
@@ -918,20 +810,20 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
                        const unsigned long default_stack_dump_size = 8192;
 
                        ret = 0;
-                       rec->opts.call_graph = CALLCHAIN_DWARF;
-                       rec->opts.stack_dump_size = default_stack_dump_size;
+                       opts->call_graph = CALLCHAIN_DWARF;
+                       opts->stack_dump_size = default_stack_dump_size;
 
                        tok = strtok_r(NULL, ",", &saveptr);
                        if (tok) {
                                unsigned long size = 0;
 
                                ret = get_stack_size(tok, &size);
-                               rec->opts.stack_dump_size = size;
+                               opts->stack_dump_size = size;
                        }
 
                        if (!ret)
                                pr_debug("callchain: stack dump size %d\n",
-                                        rec->opts.stack_dump_size);
+                                        opts->stack_dump_size);
 #endif /* LIBUNWIND_SUPPORT */
                } else {
                        pr_err("callchain: Unknown -g option "
@@ -944,7 +836,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
        free(buf);
 
        if (!ret)
-               pr_debug("callchain: type %d\n", rec->opts.call_graph);
+               pr_debug("callchain: type %d\n", opts->call_graph);
 
        return ret;
 }
@@ -982,9 +874,9 @@ static struct perf_record record = {
 #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
 
 #ifdef LIBUNWIND_SUPPORT
-static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
 #else
-static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
+const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
 #endif
 
 /*
@@ -1028,9 +920,9 @@ const struct option record_options[] = {
                     "number of mmap data pages"),
        OPT_BOOLEAN(0, "group", &record.opts.group,
                    "put the counters into a counter group"),
-       OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
-                            callchain_help, &parse_callchain_opt,
-                            "fp"),
+       OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
+                            "mode[,dump_size]", record_callchain_help,
+                            &record_parse_callchain_opt, "fp"),
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
        OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
index fc251005dd3d9ce954f4e382517f305b7dc3070d..96b5a7fee4bbe45a0f2558fb243e706ad65b8567 100644 (file)
@@ -8,6 +8,7 @@
 #include "builtin.h"
 
 #include "util/util.h"
+#include "util/cache.h"
 
 #include "util/annotate.h"
 #include "util/color.h"
@@ -54,6 +55,16 @@ struct perf_report {
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
+static int perf_report_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "report.group")) {
+               symbol_conf.event_group = perf_config_bool(var, value);
+               return 0;
+       }
+
+       return perf_default_config(var, value, cb);
+}
+
 static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
                                        struct addr_location *al,
                                        struct perf_sample *sample,
@@ -299,6 +310,21 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
        char unit;
        unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
        u64 nr_events = self->stats.total_period;
+       struct perf_evsel *evsel = hists_to_evsel(self);
+       char buf[512];
+       size_t size = sizeof(buf);
+
+       if (symbol_conf.event_group && evsel->nr_members > 1) {
+               struct perf_evsel *pos;
+
+               perf_evsel__group_desc(evsel, buf, size);
+               evname = buf;
+
+               for_each_group_member(pos, evsel) {
+                       nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+                       nr_events += pos->hists.stats.total_period;
+               }
+       }
 
        nr_samples = convert_unit(nr_samples, &unit);
        ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
@@ -319,6 +345,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                struct hists *hists = &pos->hists;
                const char *evname = perf_evsel__name(pos);
 
+               if (symbol_conf.event_group &&
+                   !perf_evsel__is_group_leader(pos))
+                       continue;
+
                hists__fprintf_nr_sample_events(hists, evname, stdout);
                hists__fprintf(hists, true, 0, 0, stdout);
                fprintf(stdout, "\n\n");
@@ -372,7 +402,7 @@ static int __cmd_report(struct perf_report *rep)
        if (ret)
                goto out_delete;
 
-       kernel_map = session->host_machine.vmlinux_maps[MAP__FUNCTION];
+       kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
        kernel_kmap = map__kmap(kernel_map);
        if (kernel_map == NULL ||
            (kernel_map->dso->hit &&
@@ -416,8 +446,16 @@ static int __cmd_report(struct perf_report *rep)
                        hists->symbol_filter_str = rep->symbol_filter_str;
 
                hists__collapse_resort(hists);
-               hists__output_resort(hists);
                nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
+
+               /* Non-group events are considered as leader */
+               if (symbol_conf.event_group &&
+                   !perf_evsel__is_group_leader(pos)) {
+                       struct hists *leader_hists = &pos->leader->hists;
+
+                       hists__match(leader_hists, hists);
+                       hists__link(leader_hists, hists);
+               }
        }
 
        if (nr_samples == 0) {
@@ -425,11 +463,22 @@ static int __cmd_report(struct perf_report *rep)
                goto out_delete;
        }
 
+       list_for_each_entry(pos, &session->evlist->entries, node)
+               hists__output_resort(&pos->hists);
+
        if (use_browser > 0) {
                if (use_browser == 1) {
-                       perf_evlist__tui_browse_hists(session->evlist, help,
-                                                     NULL,
-                                                     &session->header.env);
+                       ret = perf_evlist__tui_browse_hists(session->evlist,
+                                                       help,
+                                                       NULL,
+                                                       &session->header.env);
+                       /*
+                        * Usually "ret" is the last pressed key, and we only
+                        * care if the key notifies us to switch data file.
+                        */
+                       if (ret != K_SWITCH_INPUT_DATA)
+                               ret = 0;
+
                } else if (use_browser == 2) {
                        perf_evlist__gtk_browse_hists(session->evlist, help,
                                                      NULL);
@@ -595,8 +644,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN(0, "stdio", &report.use_stdio,
                    "Use the stdio interface"),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
-                  "sort by key(s): pid, comm, dso, symbol, parent, dso_to,"
-                  " dso_from, symbol_to, symbol_from, mispredict"),
+                  "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
+                  " dso_to, dso_from, symbol_to, symbol_from, mispredict"),
        OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
                    "Show sample percentage for different cpu modes"),
        OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -638,6 +687,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                   "Specify disassembler style (e.g. -M intel for intel syntax)"),
        OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
                    "Show a column with the sum of periods"),
+       OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
+                   "Show event group information together"),
        OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
                    "use branch records for histogram filling", parse_branch_mode),
        OPT_STRING(0, "objdump", &objdump_path, "path",
@@ -645,6 +696,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_END()
        };
 
+       perf_config(perf_report_config, NULL);
+
        argc = parse_options(argc, argv, options, report_usage, 0);
 
        if (report.use_stdio)
@@ -663,6 +716,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                else
                        input_name = "perf.data";
        }
+
+       if (strcmp(input_name, "-") != 0)
+               setup_browser(true);
+       else {
+               use_browser = 0;
+               perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+               perf_hpp__init();
+       }
+
+repeat:
        session = perf_session__new(input_name, O_RDONLY,
                                    report.force, false, &report.tool);
        if (session == NULL)
@@ -688,14 +751,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 
        }
 
-       if (strcmp(input_name, "-") != 0)
-               setup_browser(true);
-       else {
-               use_browser = 0;
-               perf_hpp__init();
-       }
-
-       setup_sorting(report_usage, options);
+       if (setup_sorting() < 0)
+               usage_with_options(report_usage, options);
 
        /*
         * Only in the newt browser we are doing integrated annotation,
@@ -763,6 +820,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
        ret = __cmd_report(&report);
+       if (ret == K_SWITCH_INPUT_DATA) {
+               perf_session__delete(session);
+               goto repeat;
+       } else
+               ret = 0;
+
 error:
        perf_session__delete(session);
        return ret;
index cc28b85dabd5a6d6c5cd70d92c726f1fe7fb33f6..138229439a93f3c8527f3da1cd319779fe287fe7 100644 (file)
@@ -1475,9 +1475,9 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
                        goto out_delete;
                }
 
-               sched->nr_events      = session->hists.stats.nr_events[0];
-               sched->nr_lost_events = session->hists.stats.total_lost;
-               sched->nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
+               sched->nr_events      = session->stats.nr_events[0];
+               sched->nr_lost_events = session->stats.total_lost;
+               sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST];
        }
 
        if (destroy)
index b363e7b292b26fa2ff41bd5a86977ec8a7f8e3c4..92d4658f56fb55a93415dbccb441c552724b0402 100644 (file)
@@ -692,7 +692,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
                            const char *arg, int unset __maybe_unused)
 {
        char *tok;
-       int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
+       int i, imax = ARRAY_SIZE(all_output_options);
        int j;
        int rc = 0;
        char *str = strdup(arg);
@@ -909,18 +909,6 @@ static const char *ends_with(const char *str, const char *suffix)
        return NULL;
 }
 
-static char *ltrim(char *str)
-{
-       int len = strlen(str);
-
-       while (len && isspace(*str)) {
-               len--;
-               str++;
-       }
-
-       return str;
-}
-
 static int read_script_info(struct script_desc *desc, const char *filename)
 {
        char line[BUFSIZ], *p;
@@ -1487,7 +1475,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        return -1;
        }
 
-       perf_session__fprintf_info(session, stdout, show_full_info);
+       if (!script_name && !generate_script_lang)
+               perf_session__fprintf_info(session, stdout, show_full_info);
 
        if (!no_callchain)
                symbol_conf.use_callchain = true;
index c247faca7127c19e2ab7eae99be56310a35c7bb1..99848761f573883e320f2db06071c5c16984b123 100644 (file)
 #define CNTR_NOT_SUPPORTED     "<not supported>"
 #define CNTR_NOT_COUNTED       "<not counted>"
 
+static void print_stat(int argc, const char **argv);
+static void print_counter_aggr(struct perf_evsel *counter, char *prefix);
+static void print_counter(struct perf_evsel *counter, char *prefix);
+static void print_aggr_socket(char *prefix);
+
 static struct perf_evlist      *evsel_list;
 
 static struct perf_target      target = {
@@ -75,6 +80,7 @@ static int                    run_count                       =  1;
 static bool                    no_inherit                      = false;
 static bool                    scale                           =  true;
 static bool                    no_aggr                         = false;
+static bool                    aggr_socket                     = false;
 static pid_t                   child_pid                       = -1;
 static bool                    null_run                        =  false;
 static int                     detailed_run                    =  0;
@@ -87,6 +93,9 @@ static FILE                   *output                         = NULL;
 static const char              *pre_cmd                        = NULL;
 static const char              *post_cmd                       = NULL;
 static bool                    sync_run                        = false;
+static unsigned int            interval                        = 0;
+static struct timespec         ref_time;
+static struct cpu_map          *sock_map;
 
 static volatile int done = 0;
 
@@ -94,6 +103,28 @@ struct perf_stat {
        struct stats      res_stats[3];
 };
 
+static inline void diff_timespec(struct timespec *r, struct timespec *a,
+                                struct timespec *b)
+{
+       r->tv_sec = a->tv_sec - b->tv_sec;
+       if (a->tv_nsec < b->tv_nsec) {
+               r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec;
+               r->tv_sec--;
+       } else {
+               r->tv_nsec = a->tv_nsec - b->tv_nsec ;
+       }
+}
+
+static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+{
+       return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
+}
+
+static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
+{
+       return perf_evsel__cpus(evsel)->nr;
+}
+
 static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 {
        evsel->priv = zalloc(sizeof(struct perf_stat));
@@ -106,14 +137,27 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
        evsel->priv = NULL;
 }
 
-static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
 {
-       return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
+       void *addr;
+       size_t sz;
+
+       sz = sizeof(*evsel->counts) +
+            (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values));
+
+       addr = zalloc(sz);
+       if (!addr)
+               return -ENOMEM;
+
+       evsel->prev_raw_counts =  addr;
+
+       return 0;
 }
 
-static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
+static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 {
-       return perf_evsel__cpus(evsel)->nr;
+       free(evsel->prev_raw_counts);
+       evsel->prev_raw_counts = NULL;
 }
 
 static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
@@ -132,8 +176,6 @@ static struct stats walltime_nsecs_stats;
 static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
        struct perf_event_attr *attr = &evsel->attr;
-       bool exclude_guest_missing = false;
-       int ret;
 
        if (scale)
                attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -141,38 +183,16 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 
        attr->inherit = !no_inherit;
 
-retry:
-       if (exclude_guest_missing)
-               evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
-
-       if (perf_target__has_cpu(&target)) {
-               ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
-               if (ret)
-                       goto check_ret;
-               return 0;
-       }
+       if (perf_target__has_cpu(&target))
+               return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
 
        if (!perf_target__has_task(&target) &&
-           !perf_evsel__is_group_member(evsel)) {
+           perf_evsel__is_group_leader(evsel)) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
-       if (!ret)
-               return 0;
-       /* fall through */
-check_ret:
-       if (ret && errno == EINVAL) {
-               if (!exclude_guest_missing &&
-                   (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
-                       pr_debug("Old kernel, cannot exclude "
-                                "guest or host samples.\n");
-                       exclude_guest_missing = true;
-                       goto retry;
-               }
-       }
-       return ret;
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads);
 }
 
 /*
@@ -269,15 +289,79 @@ static int read_counter(struct perf_evsel *counter)
        return 0;
 }
 
+static void print_interval(void)
+{
+       static int num_print_interval;
+       struct perf_evsel *counter;
+       struct perf_stat *ps;
+       struct timespec ts, rs;
+       char prefix[64];
+
+       if (no_aggr) {
+               list_for_each_entry(counter, &evsel_list->entries, node) {
+                       ps = counter->priv;
+                       memset(ps->res_stats, 0, sizeof(ps->res_stats));
+                       read_counter(counter);
+               }
+       } else {
+               list_for_each_entry(counter, &evsel_list->entries, node) {
+                       ps = counter->priv;
+                       memset(ps->res_stats, 0, sizeof(ps->res_stats));
+                       read_counter_aggr(counter);
+               }
+       }
+       clock_gettime(CLOCK_MONOTONIC, &ts);
+       diff_timespec(&rs, &ts, &ref_time);
+       sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep);
+
+       if (num_print_interval == 0 && !csv_output) {
+               if (aggr_socket)
+                       fprintf(output, "#           time socket cpus             counts events\n");
+               else if (no_aggr)
+                       fprintf(output, "#           time CPU                 counts events\n");
+               else
+                       fprintf(output, "#           time             counts events\n");
+       }
+
+       if (++num_print_interval == 25)
+               num_print_interval = 0;
+
+       if (aggr_socket)
+               print_aggr_socket(prefix);
+       else if (no_aggr) {
+               list_for_each_entry(counter, &evsel_list->entries, node)
+                       print_counter(counter, prefix);
+       } else {
+               list_for_each_entry(counter, &evsel_list->entries, node)
+                       print_counter_aggr(counter, prefix);
+       }
+}
+
 static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 {
+       char msg[512];
        unsigned long long t0, t1;
        struct perf_evsel *counter;
+       struct timespec ts;
        int status = 0;
        int child_ready_pipe[2], go_pipe[2];
        const bool forks = (argc > 0);
        char buf;
 
+       if (interval) {
+               ts.tv_sec  = interval / 1000;
+               ts.tv_nsec = (interval % 1000) * 1000000;
+       } else {
+               ts.tv_sec  = 1;
+               ts.tv_nsec = 0;
+       }
+
+       if (aggr_socket
+           && cpu_map__build_socket_map(evsel_list->cpus, &sock_map)) {
+               perror("cannot build socket map");
+               return -1;
+       }
+
        if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
                perror("failed to create pipes");
                return -1;
@@ -348,20 +432,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
                                continue;
                        }
 
-                       if (errno == EPERM || errno == EACCES) {
-                               error("You may not have permission to collect %sstats.\n"
-                                     "\t Consider tweaking"
-                                     " /proc/sys/kernel/perf_event_paranoid or running as root.",
-                                     target.system_wide ? "system-wide " : "");
-                       } else {
-                               error("open_counter returned with %d (%s). "
-                                     "/bin/dmesg may provide additional information.\n",
-                                      errno, strerror(errno));
-                       }
+                       perf_evsel__open_strerror(counter, &target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
+
                        if (child_pid != -1)
                                kill(child_pid, SIGTERM);
 
-                       pr_err("Not all events could be opened.\n");
                        return -1;
                }
                counter->supported = true;
@@ -377,14 +454,25 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
         * Enable counters and exec the command:
         */
        t0 = rdclock();
+       clock_gettime(CLOCK_MONOTONIC, &ref_time);
 
        if (forks) {
                close(go_pipe[1]);
+               if (interval) {
+                       while (!waitpid(child_pid, &status, WNOHANG)) {
+                               nanosleep(&ts, NULL);
+                               print_interval();
+                       }
+               }
                wait(&status);
                if (WIFSIGNALED(status))
                        psignal(WTERMSIG(status), argv[0]);
        } else {
-               while(!done) sleep(1);
+               while (!done) {
+                       nanosleep(&ts, NULL);
+                       if (interval)
+                               print_interval();
+               }
        }
 
        t1 = rdclock();
@@ -454,13 +542,21 @@ static void print_noise(struct perf_evsel *evsel, double avg)
        print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
 }
 
-static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
+static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double msecs = avg / 1e6;
        char cpustr[16] = { '\0', };
        const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s";
 
-       if (no_aggr)
+       if (aggr_socket)
+               sprintf(cpustr, "S%*d%s%*d%s",
+                       csv_output ? 0 : -5,
+                       cpu,
+                       csv_sep,
+                       csv_output ? 0 : 4,
+                       nr,
+                       csv_sep);
+       else if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
                        csv_output ? 0 : -4,
                        perf_evsel__cpus(evsel)->map[cpu], csv_sep);
@@ -470,7 +566,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-       if (csv_output)
+       if (csv_output || interval)
                return;
 
        if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
@@ -659,7 +755,7 @@ static void print_ll_cache_misses(int cpu,
        fprintf(output, " of all LL-cache hits   ");
 }
 
-static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
+static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double total, ratio = 0.0;
        char cpustr[16] = { '\0', };
@@ -672,7 +768,15 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        else
                fmt = "%s%18.0f%s%-25s";
 
-       if (no_aggr)
+       if (aggr_socket)
+               sprintf(cpustr, "S%*d%s%*d%s",
+                       csv_output ? 0 : -5,
+                       cpu,
+                       csv_sep,
+                       csv_output ? 0 : 4,
+                       nr,
+                       csv_sep);
+       else if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
                        csv_output ? 0 : -4,
                        perf_evsel__cpus(evsel)->map[cpu], csv_sep);
@@ -684,12 +788,11 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-       if (csv_output)
+       if (csv_output || interval)
                return;
 
        if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
                total = avg_stats(&runtime_cycles_stats[cpu]);
-
                if (total)
                        ratio = avg / total;
 
@@ -779,16 +882,83 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        }
 }
 
+static void print_aggr_socket(char *prefix)
+{
+       struct perf_evsel *counter;
+       u64 ena, run, val;
+       int cpu, s, s2, sock, nr;
+
+       if (!sock_map)
+               return;
+
+       for (s = 0; s < sock_map->nr; s++) {
+               sock = cpu_map__socket(sock_map, s);
+               list_for_each_entry(counter, &evsel_list->entries, node) {
+                       val = ena = run = 0;
+                       nr = 0;
+                       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+                               s2 = cpu_map__get_socket(evsel_list->cpus, cpu);
+                               if (s2 != sock)
+                                       continue;
+                               val += counter->counts->cpu[cpu].val;
+                               ena += counter->counts->cpu[cpu].ena;
+                               run += counter->counts->cpu[cpu].run;
+                               nr++;
+                       }
+                       if (prefix)
+                               fprintf(output, "%s", prefix);
+
+                       if (run == 0 || ena == 0) {
+                               fprintf(output, "S%*d%s%*d%s%*s%s%*s",
+                                       csv_output ? 0 : -5,
+                                       s,
+                                       csv_sep,
+                                       csv_output ? 0 : 4,
+                                       nr,
+                                       csv_sep,
+                                       csv_output ? 0 : 18,
+                                       counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
+                                       csv_sep,
+                                       csv_output ? 0 : -24,
+                                       perf_evsel__name(counter));
+                               if (counter->cgrp)
+                                       fprintf(output, "%s%s",
+                                               csv_sep, counter->cgrp->name);
+
+                               fputc('\n', output);
+                               continue;
+                       }
+
+                       if (nsec_counter(counter))
+                               nsec_printout(sock, nr, counter, val);
+                       else
+                               abs_printout(sock, nr, counter, val);
+
+                       if (!csv_output) {
+                               print_noise(counter, 1.0);
+
+                               if (run != ena)
+                                       fprintf(output, "  (%.2f%%)",
+                                               100.0 * run / ena);
+                       }
+                       fputc('\n', output);
+               }
+       }
+}
+
 /*
  * Print out the results of a single counter:
  * aggregated counts in system-wide mode
  */
-static void print_counter_aggr(struct perf_evsel *counter)
+static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 {
        struct perf_stat *ps = counter->priv;
        double avg = avg_stats(&ps->res_stats[0]);
        int scaled = counter->counts->scaled;
 
+       if (prefix)
+               fprintf(output, "%s", prefix);
+
        if (scaled == -1) {
                fprintf(output, "%*s%s%*s",
                        csv_output ? 0 : 18,
@@ -805,9 +975,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
        }
 
        if (nsec_counter(counter))
-               nsec_printout(-1, counter, avg);
+               nsec_printout(-1, 0, counter, avg);
        else
-               abs_printout(-1, counter, avg);
+               abs_printout(-1, 0, counter, avg);
 
        print_noise(counter, avg);
 
@@ -831,7 +1001,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
  * Print out the results of a single counter:
  * does not use aggregated count in system-wide
  */
-static void print_counter(struct perf_evsel *counter)
+static void print_counter(struct perf_evsel *counter, char *prefix)
 {
        u64 ena, run, val;
        int cpu;
@@ -840,6 +1010,10 @@ static void print_counter(struct perf_evsel *counter)
                val = counter->counts->cpu[cpu].val;
                ena = counter->counts->cpu[cpu].ena;
                run = counter->counts->cpu[cpu].run;
+
+               if (prefix)
+                       fprintf(output, "%s", prefix);
+
                if (run == 0 || ena == 0) {
                        fprintf(output, "CPU%*d%s%*s%s%*s",
                                csv_output ? 0 : -4,
@@ -859,9 +1033,9 @@ static void print_counter(struct perf_evsel *counter)
                }
 
                if (nsec_counter(counter))
-                       nsec_printout(cpu, counter, val);
+                       nsec_printout(cpu, 0, counter, val);
                else
-                       abs_printout(cpu, counter, val);
+                       abs_printout(cpu, 0, counter, val);
 
                if (!csv_output) {
                        print_noise(counter, 1.0);
@@ -899,12 +1073,14 @@ static void print_stat(int argc, const char **argv)
                fprintf(output, ":\n\n");
        }
 
-       if (no_aggr) {
+       if (aggr_socket)
+               print_aggr_socket(NULL);
+       else if (no_aggr) {
                list_for_each_entry(counter, &evsel_list->entries, node)
-                       print_counter(counter);
+                       print_counter(counter, NULL);
        } else {
                list_for_each_entry(counter, &evsel_list->entries, node)
-                       print_counter_aggr(counter);
+                       print_counter_aggr(counter, NULL);
        }
 
        if (!csv_output) {
@@ -925,7 +1101,7 @@ static volatile int signr = -1;
 
 static void skip_signal(int signo)
 {
-       if(child_pid == -1)
+       if ((child_pid == -1) || interval)
                done = 1;
 
        signr = signo;
@@ -1145,6 +1321,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                        "command to run prior to the measured command"),
        OPT_STRING(0, "post", &post_cmd, "command",
                        "command to run after to the measured command"),
+       OPT_UINTEGER('I', "interval-print", &interval,
+                   "print counts at regular interval in ms (>= 100)"),
+       OPT_BOOLEAN(0, "aggr-socket", &aggr_socket, "aggregate counts per processor socket"),
        OPT_END()
        };
        const char * const stat_usage[] = {
@@ -1231,6 +1410,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                usage_with_options(stat_usage, options);
        }
 
+       if (aggr_socket) {
+               if (!perf_target__has_cpu(&target)) {
+                       fprintf(stderr, "--aggr-socket only available in system-wide mode (-a)\n");
+                       usage_with_options(stat_usage, options);
+               }
+               no_aggr = true;
+       }
+
        if (add_default_attributes())
                goto out;
 
@@ -1245,12 +1432,23 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                usage_with_options(stat_usage, options);
                return -1;
        }
+       if (interval && interval < 100) {
+               pr_err("print interval must be >= 100ms\n");
+               usage_with_options(stat_usage, options);
+               return -1;
+       }
 
        list_for_each_entry(pos, &evsel_list->entries, node) {
                if (perf_evsel__alloc_stat_priv(pos) < 0 ||
                    perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
                        goto out_free_fd;
        }
+       if (interval) {
+               list_for_each_entry(pos, &evsel_list->entries, node) {
+                       if (perf_evsel__alloc_prev_raw_counts(pos) < 0)
+                               goto out_free_fd;
+               }
+       }
 
        /*
         * We dont want to block the signals - that would cause
@@ -1260,6 +1458,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
         */
        atexit(sig_atexit);
        signal(SIGINT,  skip_signal);
+       signal(SIGCHLD, skip_signal);
        signal(SIGALRM, skip_signal);
        signal(SIGABRT, skip_signal);
 
@@ -1272,11 +1471,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                status = run_perf_stat(argc, argv);
        }
 
-       if (status != -1)
+       if (status != -1 && !interval)
                print_stat(argc, argv);
 out_free_fd:
-       list_for_each_entry(pos, &evsel_list->entries, node)
+       list_for_each_entry(pos, &evsel_list->entries, node) {
                perf_evsel__free_stat_priv(pos);
+               perf_evsel__free_counts(pos);
+               perf_evsel__free_prev_raw_counts(pos);
+       }
        perf_evlist__delete_maps(evsel_list);
 out:
        perf_evlist__delete(evsel_list);
index c9ff3950cd4be55a487ff6cbda76b4f55c47ad5d..72f6eb7b4173c86f84fcf3b001f6eb9ae1bdd8b4 100644 (file)
 #include <linux/unistd.h>
 #include <linux/types.h>
 
-void get_term_dimensions(struct winsize *ws)
-{
-       char *s = getenv("LINES");
-
-       if (s != NULL) {
-               ws->ws_row = atoi(s);
-               s = getenv("COLUMNS");
-               if (s != NULL) {
-                       ws->ws_col = atoi(s);
-                       if (ws->ws_row && ws->ws_col)
-                               return;
-               }
-       }
-#ifdef TIOCGWINSZ
-       if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
-           ws->ws_row && ws->ws_col)
-               return;
-#endif
-       ws->ws_row = 25;
-       ws->ws_col = 80;
-}
+static volatile int done;
 
 static void perf_top__update_print_entries(struct perf_top *top)
 {
@@ -453,8 +433,10 @@ static int perf_top__key_mapped(struct perf_top *top, int c)
        return 0;
 }
 
-static void perf_top__handle_keypress(struct perf_top *top, int c)
+static bool perf_top__handle_keypress(struct perf_top *top, int c)
 {
+       bool ret = true;
+
        if (!perf_top__key_mapped(top, c)) {
                struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
                struct termios tc, save;
@@ -475,7 +457,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
 
                tcsetattr(0, TCSAFLUSH, &save);
                if (!perf_top__key_mapped(top, c))
-                       return;
+                       return ret;
        }
 
        switch (c) {
@@ -537,7 +519,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                        printf("exiting.\n");
                        if (top->dump_symtab)
                                perf_session__fprintf_dsos(top->session, stderr);
-                       exit(0);
+                       ret = false;
+                       break;
                case 's':
                        perf_top__prompt_symbol(top, "Enter details symbol");
                        break;
@@ -560,6 +543,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                default:
                        break;
        }
+
+       return ret;
 }
 
 static void perf_top__sort_new_samples(void *arg)
@@ -596,13 +581,12 @@ static void *display_thread_tui(void *arg)
         * via --uid.
         */
        list_for_each_entry(pos, &top->evlist->entries, node)
-               pos->hists.uid_filter_str = top->target.uid_str;
+               pos->hists.uid_filter_str = top->record_opts.target.uid_str;
 
        perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
                                      &top->session->header.env);
 
-       exit_browser(0);
-       exit(0);
+       done = 1;
        return NULL;
 }
 
@@ -626,7 +610,7 @@ repeat:
        /* trash return*/
        getc(stdin);
 
-       while (1) {
+       while (!done) {
                perf_top__print_sym_table(top);
                /*
                 * Either timeout expired or we got an EINTR due to SIGWINCH,
@@ -640,15 +624,14 @@ repeat:
                                continue;
                        /* Fall trhu */
                default:
-                       goto process_hotkey;
+                       c = getc(stdin);
+                       tcsetattr(0, TCSAFLUSH, &save);
+
+                       if (perf_top__handle_keypress(top, c))
+                               goto repeat;
+                       done = 1;
                }
        }
-process_hotkey:
-       c = getc(stdin);
-       tcsetattr(0, TCSAFLUSH, &save);
-
-       perf_top__handle_keypress(top, c);
-       goto repeat;
 
        return NULL;
 }
@@ -716,7 +699,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
                static struct intlist *seen;
 
                if (!seen)
-                       seen = intlist__new();
+                       seen = intlist__new(NULL);
 
                if (!intlist__has_entry(seen, event->ip.pid)) {
                        pr_err("Can't find guest [%d]'s kernel information\n",
@@ -727,8 +710,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
        }
 
        if (!machine) {
-               pr_err("%u unprocessable samples recorded.",
-                      top->session->hists.stats.nr_unprocessable_samples++);
+               pr_err("%u unprocessable samples recorded.\r",
+                      top->session->stats.nr_unprocessable_samples++);
                return;
        }
 
@@ -847,13 +830,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
                        ++top->us_samples;
                        if (top->hide_user_symbols)
                                continue;
-                       machine = perf_session__find_host_machine(session);
+                       machine = &session->machines.host;
                        break;
                case PERF_RECORD_MISC_KERNEL:
                        ++top->kernel_samples;
                        if (top->hide_kernel_symbols)
                                continue;
-                       machine = perf_session__find_host_machine(session);
+                       machine = &session->machines.host;
                        break;
                case PERF_RECORD_MISC_GUEST_KERNEL:
                        ++top->guest_kernel_samples;
@@ -878,7 +861,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
                        hists__inc_nr_events(&evsel->hists, event->header.type);
                        machine__process_event(machine, event);
                } else
-                       ++session->hists.stats.nr_unknown_events;
+                       ++session->stats.nr_unknown_events;
        }
 }
 
@@ -890,123 +873,42 @@ static void perf_top__mmap_read(struct perf_top *top)
                perf_top__mmap_read_idx(top, i);
 }
 
-static void perf_top__start_counters(struct perf_top *top)
+static int perf_top__start_counters(struct perf_top *top)
 {
+       char msg[512];
        struct perf_evsel *counter;
        struct perf_evlist *evlist = top->evlist;
+       struct perf_record_opts *opts = &top->record_opts;
 
-       if (top->group)
-               perf_evlist__set_leader(evlist);
+       perf_evlist__config(evlist, opts);
 
        list_for_each_entry(counter, &evlist->entries, node) {
-               struct perf_event_attr *attr = &counter->attr;
-
-               attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
-
-               if (top->freq) {
-                       attr->sample_type |= PERF_SAMPLE_PERIOD;
-                       attr->freq        = 1;
-                       attr->sample_freq = top->freq;
-               }
-
-               if (evlist->nr_entries > 1) {
-                       attr->sample_type |= PERF_SAMPLE_ID;
-                       attr->read_format |= PERF_FORMAT_ID;
-               }
-
-               if (perf_target__has_cpu(&top->target))
-                       attr->sample_type |= PERF_SAMPLE_CPU;
-
-               if (symbol_conf.use_callchain)
-                       attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
-
-               attr->mmap = 1;
-               attr->comm = 1;
-               attr->inherit = top->inherit;
-fallback_missing_features:
-               if (top->exclude_guest_missing)
-                       attr->exclude_guest = attr->exclude_host = 0;
-retry_sample_id:
-               attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
 try_again:
                if (perf_evsel__open(counter, top->evlist->cpus,
                                     top->evlist->threads) < 0) {
-                       int err = errno;
-
-                       if (err == EPERM || err == EACCES) {
-                               ui__error_paranoid();
-                               goto out_err;
-                       } else if (err == EINVAL) {
-                               if (!top->exclude_guest_missing &&
-                                   (attr->exclude_guest || attr->exclude_host)) {
-                                       pr_debug("Old kernel, cannot exclude "
-                                                "guest or host samples.\n");
-                                       top->exclude_guest_missing = true;
-                                       goto fallback_missing_features;
-                               } else if (!top->sample_id_all_missing) {
-                                       /*
-                                        * Old kernel, no attr->sample_id_type_all field
-                                        */
-                                       top->sample_id_all_missing = true;
-                                       goto retry_sample_id;
-                               }
-                       }
-                       /*
-                        * If it's cycles then fall back to hrtimer
-                        * based cpu-clock-tick sw counter, which
-                        * is always available even if no PMU support:
-                        */
-                       if ((err == ENOENT || err == ENXIO) &&
-                           (attr->type == PERF_TYPE_HARDWARE) &&
-                           (attr->config == PERF_COUNT_HW_CPU_CYCLES)) {
-
+                       if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
                                if (verbose)
-                                       ui__warning("Cycles event not supported,\n"
-                                                   "trying to fall back to cpu-clock-ticks\n");
-
-                               attr->type = PERF_TYPE_SOFTWARE;
-                               attr->config = PERF_COUNT_SW_CPU_CLOCK;
-                               if (counter->name) {
-                                       free(counter->name);
-                                       counter->name = NULL;
-                               }
+                                       ui__warning("%s\n", msg);
                                goto try_again;
                        }
 
-                       if (err == ENOENT) {
-                               ui__error("The %s event is not supported.\n",
-                                         perf_evsel__name(counter));
-                               goto out_err;
-                       } else if (err == EMFILE) {
-                               ui__error("Too many events are opened.\n"
-                                           "Try again after reducing the number of events\n");
-                               goto out_err;
-                       } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
-                               ui__error("\'precise\' request may not be supported. "
-                                         "Try removing 'p' modifier\n");
-                               goto out_err;
-                       }
-
-                       ui__error("The sys_perf_event_open() syscall "
-                                   "returned with %d (%s).  /bin/dmesg "
-                                   "may provide additional information.\n"
-                                   "No CONFIG_PERF_EVENTS=y kernel support "
-                                   "configured?\n", err, strerror(err));
+                       perf_evsel__open_strerror(counter, &opts->target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
                        goto out_err;
                }
        }
 
-       if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
+       if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
                ui__error("Failed to mmap with %d (%s)\n",
                            errno, strerror(errno));
                goto out_err;
        }
 
-       return;
+       return 0;
 
 out_err:
-       exit_browser(0);
-       exit(0);
+       return -1;
 }
 
 static int perf_top__setup_sample_type(struct perf_top *top)
@@ -1016,7 +918,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
                        ui__error("Selected -g but \"sym\" not present in --sort/-s.");
                        return -EINVAL;
                }
-       } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
+       } else if (callchain_param.mode != CHAIN_NONE) {
                if (callchain_register_param(&callchain_param) < 0) {
                        ui__error("Can't register callchain params.\n");
                        return -EINVAL;
@@ -1028,6 +930,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
 
 static int __cmd_top(struct perf_top *top)
 {
+       struct perf_record_opts *opts = &top->record_opts;
        pthread_t thread;
        int ret;
        /*
@@ -1042,26 +945,42 @@ static int __cmd_top(struct perf_top *top)
        if (ret)
                goto out_delete;
 
-       if (perf_target__has_task(&top->target))
+       if (perf_target__has_task(&opts->target))
                perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
                                                  perf_event__process,
-                                                 &top->session->host_machine);
+                                                 &top->session->machines.host);
        else
                perf_event__synthesize_threads(&top->tool, perf_event__process,
-                                              &top->session->host_machine);
-       perf_top__start_counters(top);
+                                              &top->session->machines.host);
+
+       ret = perf_top__start_counters(top);
+       if (ret)
+               goto out_delete;
+
        top->session->evlist = top->evlist;
        perf_session__set_id_hdr_size(top->session);
 
+       /*
+        * When perf is starting the traced process, all the events (apart from
+        * group members) have enable_on_exec=1 set, so don't spoil it by
+        * prematurely enabling them.
+        *
+        * XXX 'top' still doesn't start workloads like record, trace, but should,
+        * so leave the check here.
+        */
+        if (!perf_target__none(&opts->target))
+                perf_evlist__enable(top->evlist);
+
        /* Wait for a minimal set of events before starting the snapshot */
        poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
 
        perf_top__mmap_read(top);
 
+       ret = -1;
        if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
                                                            display_thread), top)) {
                ui__error("Could not create display thread.\n");
-               exit(-1);
+               goto out_delete;
        }
 
        if (top->realtime_prio) {
@@ -1070,11 +989,11 @@ static int __cmd_top(struct perf_top *top)
                param.sched_priority = top->realtime_prio;
                if (sched_setscheduler(0, SCHED_FIFO, &param)) {
                        ui__error("Could not set realtime priority.\n");
-                       exit(-1);
+                       goto out_delete;
                }
        }
 
-       while (1) {
+       while (!done) {
                u64 hits = top->samples;
 
                perf_top__mmap_read(top);
@@ -1083,126 +1002,67 @@ static int __cmd_top(struct perf_top *top)
                        ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
        }
 
+       ret = 0;
 out_delete:
        perf_session__delete(top->session);
        top->session = NULL;
 
-       return 0;
+       return ret;
 }
 
 static int
 parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
-       struct perf_top *top = (struct perf_top *)opt->value;
-       char *tok, *tok2;
-       char *endptr;
-
        /*
         * --no-call-graph
         */
-       if (unset) {
-               top->dont_use_callchains = true;
+       if (unset)
                return 0;
-       }
 
        symbol_conf.use_callchain = true;
 
-       if (!arg)
-               return 0;
-
-       tok = strtok((char *)arg, ",");
-       if (!tok)
-               return -1;
-
-       /* get the output mode */
-       if (!strncmp(tok, "graph", strlen(arg)))
-               callchain_param.mode = CHAIN_GRAPH_ABS;
-
-       else if (!strncmp(tok, "flat", strlen(arg)))
-               callchain_param.mode = CHAIN_FLAT;
-
-       else if (!strncmp(tok, "fractal", strlen(arg)))
-               callchain_param.mode = CHAIN_GRAPH_REL;
-
-       else if (!strncmp(tok, "none", strlen(arg))) {
-               callchain_param.mode = CHAIN_NONE;
-               symbol_conf.use_callchain = false;
-
-               return 0;
-       } else
-               return -1;
-
-       /* get the min percentage */
-       tok = strtok(NULL, ",");
-       if (!tok)
-               goto setup;
-
-       callchain_param.min_percent = strtod(tok, &endptr);
-       if (tok == endptr)
-               return -1;
-
-       /* get the print limit */
-       tok2 = strtok(NULL, ",");
-       if (!tok2)
-               goto setup;
-
-       if (tok2[0] != 'c') {
-               callchain_param.print_limit = strtod(tok2, &endptr);
-               tok2 = strtok(NULL, ",");
-               if (!tok2)
-                       goto setup;
-       }
-
-       /* get the call chain order */
-       if (!strcmp(tok2, "caller"))
-               callchain_param.order = ORDER_CALLER;
-       else if (!strcmp(tok2, "callee"))
-               callchain_param.order = ORDER_CALLEE;
-       else
-               return -1;
-setup:
-       if (callchain_register_param(&callchain_param) < 0) {
-               fprintf(stderr, "Can't register callchain params\n");
-               return -1;
-       }
-       return 0;
+       return record_parse_callchain_opt(opt, arg, unset);
 }
 
 int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       struct perf_evsel *pos;
        int status;
        char errbuf[BUFSIZ];
        struct perf_top top = {
                .count_filter        = 5,
                .delay_secs          = 2,
-               .freq                = 4000, /* 4 KHz */
-               .mmap_pages          = 128,
-               .sym_pcnt_filter     = 5,
-               .target              = {
-                       .uses_mmap   = true,
+               .record_opts = {
+                       .mmap_pages     = UINT_MAX,
+                       .user_freq      = UINT_MAX,
+                       .user_interval  = ULLONG_MAX,
+                       .freq           = 4000, /* 4 KHz */
+                       .target              = {
+                               .uses_mmap   = true,
+                       },
                },
+               .sym_pcnt_filter     = 5,
        };
-       char callchain_default_opt[] = "fractal,0.5,callee";
+       struct perf_record_opts *opts = &top.record_opts;
+       struct perf_target *target = &opts->target;
        const struct option options[] = {
        OPT_CALLBACK('e', "event", &top.evlist, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
-       OPT_INTEGER('c', "count", &top.default_interval,
-                   "event period to sample"),
-       OPT_STRING('p', "pid", &top.target.pid, "pid",
+       OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
+       OPT_STRING('p', "pid", &target->pid, "pid",
                    "profile events on existing process id"),
-       OPT_STRING('t', "tid", &top.target.tid, "tid",
+       OPT_STRING('t', "tid", &target->tid, "tid",
                    "profile events on existing thread id"),
-       OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide,
+       OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
                            "system-wide collection from all CPUs"),
-       OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu",
+       OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
                    "list of cpus to monitor"),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
        OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
                    "hide kernel symbols"),
-       OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"),
+       OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages,
+                    "number of mmap data pages"),
        OPT_INTEGER('r', "realtime", &top.realtime_prio,
                    "collect data with this RT SCHED_FIFO priority"),
        OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1211,16 +1071,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                            "dump the symbol table used for profiling"),
        OPT_INTEGER('f', "count-filter", &top.count_filter,
                    "only display functions with more events than this"),
-       OPT_BOOLEAN('g', "group", &top.group,
+       OPT_BOOLEAN('g', "group", &opts->group,
                            "put the counters into a counter group"),
-       OPT_BOOLEAN('i', "inherit", &top.inherit,
-                   "child tasks inherit counters"),
+       OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
+                   "child tasks do not inherit counters"),
        OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
                    "symbol to annotate"),
-       OPT_BOOLEAN('z', "zero", &top.zero,
-                   "zero history across updates"),
-       OPT_INTEGER('F', "freq", &top.freq,
-                   "profile at this frequency"),
+       OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
+       OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"),
        OPT_INTEGER('E', "entries", &top.print_entries,
                    "display this many functions"),
        OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1233,10 +1091,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                   "sort by key(s): pid, comm, dso, symbol, parent"),
        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
                    "Show a column with the number of samples"),
-       OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order",
-                    "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. "
-                    "Default: fractal,0.5,callee", &parse_callchain_opt,
-                    callchain_default_opt),
+       OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
+                            "mode[,dump_size]", record_callchain_help,
+                            &parse_callchain_opt, "fp"),
        OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
                    "Show a column with the sum of periods"),
        OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1251,7 +1108,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                    "Display raw encoding of assembly instructions (default)"),
        OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
                   "Specify disassembler style (e.g. -M intel for intel syntax)"),
-       OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
+       OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
        OPT_END()
        };
        const char * const top_usage[] = {
@@ -1272,7 +1129,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        if (sort_order == default_sort_order)
                sort_order = "dso,symbol";
 
-       setup_sorting(top_usage, options);
+       if (setup_sorting() < 0)
+               usage_with_options(top_usage, options);
 
        if (top.use_stdio)
                use_browser = 0;
@@ -1281,33 +1139,33 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 
        setup_browser(false);
 
-       status = perf_target__validate(&top.target);
+       status = perf_target__validate(target);
        if (status) {
-               perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+               perf_target__strerror(target, status, errbuf, BUFSIZ);
                ui__warning("%s", errbuf);
        }
 
-       status = perf_target__parse_uid(&top.target);
+       status = perf_target__parse_uid(target);
        if (status) {
                int saved_errno = errno;
 
-               perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+               perf_target__strerror(target, status, errbuf, BUFSIZ);
                ui__error("%s", errbuf);
 
                status = -saved_errno;
                goto out_delete_evlist;
        }
 
-       if (perf_target__none(&top.target))
-               top.target.system_wide = true;
+       if (perf_target__none(target))
+               target->system_wide = true;
 
-       if (perf_evlist__create_maps(top.evlist, &top.target) < 0)
+       if (perf_evlist__create_maps(top.evlist, target) < 0)
                usage_with_options(top_usage, options);
 
        if (!top.evlist->nr_entries &&
            perf_evlist__add_default(top.evlist) < 0) {
                ui__error("Not enough memory for event selector list\n");
-               return -ENOMEM;
+               goto out_delete_maps;
        }
 
        symbol_conf.nr_events = top.evlist->nr_entries;
@@ -1315,24 +1173,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        if (top.delay_secs < 1)
                top.delay_secs = 1;
 
+       if (opts->user_interval != ULLONG_MAX)
+               opts->default_interval = opts->user_interval;
+       if (opts->user_freq != UINT_MAX)
+               opts->freq = opts->user_freq;
+
        /*
         * User specified count overrides default frequency.
         */
-       if (top.default_interval)
-               top.freq = 0;
-       else if (top.freq) {
-               top.default_interval = top.freq;
+       if (opts->default_interval)
+               opts->freq = 0;
+       else if (opts->freq) {
+               opts->default_interval = opts->freq;
        } else {
                ui__error("frequency and count are zero, aborting\n");
-               exit(EXIT_FAILURE);
-       }
-
-       list_for_each_entry(pos, &top.evlist->entries, node) {
-               /*
-                * Fill in the ones not specifically initialized via -c:
-                */
-               if (!pos->attr.sample_period)
-                       pos->attr.sample_period = top.default_interval;
+               status = -EINVAL;
+               goto out_delete_maps;
        }
 
        top.sym_evsel = perf_evlist__first(top.evlist);
@@ -1365,6 +1221,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 
        status = __cmd_top(&top);
 
+out_delete_maps:
+       perf_evlist__delete_maps(top.evlist);
 out_delete_evlist:
        perf_evlist__delete(top.evlist);
 
index 7932ffa298894a00694b82c6f26c058acd3760f9..d222d7fc7e960c7b541d507d524b66790a7d93b0 100644 (file)
@@ -455,7 +455,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
                goto out_delete_evlist;
        }
 
-       perf_evlist__config_attrs(evlist, &trace->opts);
+       perf_evlist__config(evlist, &trace->opts);
 
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
index f5ac77485a4f6124c3216c93556fb26c33ae79c9..b4eabb44e381c8d74f95362fb6ece61bdc32bf50 100644 (file)
@@ -225,3 +225,14 @@ int main(void)
        return on_exit(NULL, NULL);
 }
 endef
+
+define SOURCE_LIBNUMA
+#include <numa.h>
+#include <numaif.h>
+
+int main(void)
+{
+       numa_available();
+       return 0;
+}
+endef
\ No newline at end of file
index e5413125e6bbaef823b773b7a5b712d30c89a0b1..8ef3bd30a5492afa002c928b4483e03ac16db790 100644 (file)
@@ -13,7 +13,7 @@ newline := $(newline)
 # what should replace a newline when escaping
 # newlines; the default is a bizarre string.
 #
-nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n)
+nl-escape = $(if $(1),$(1),m822df3020w6a44id34bt574ctac44eb9f4n)
 
 # escape-nl
 #
@@ -173,9 +173,9 @@ _ge-abspath = $(if $(is-executable),$(1))
 # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
 #
 define get-executable-or-default
-$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
+$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1)))
 endef
-_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2)))
+_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
 _gea_warn = $(warning The path '$(1)' is not executable.)
 _gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
 
index 0f661fbce6a8c3d318f20b255a407ed41d54fead..095b88207cd3e8f952b1b9676a0abf57f91dde50 100644 (file)
@@ -328,14 +328,23 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
        if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
                return 0;
 
+       status = 1;
        /* Check for ENOSPC and EIO errors.. */
-       if (fflush(stdout))
-               die("write failure on standard output: %s", strerror(errno));
-       if (ferror(stdout))
-               die("unknown write failure on standard output");
-       if (fclose(stdout))
-               die("close failed on standard output: %s", strerror(errno));
-       return 0;
+       if (fflush(stdout)) {
+               fprintf(stderr, "write failure on standard output: %s", strerror(errno));
+               goto out;
+       }
+       if (ferror(stdout)) {
+               fprintf(stderr, "unknown write failure on standard output");
+               goto out;
+       }
+       if (fclose(stdout)) {
+               fprintf(stderr, "close failed on standard output: %s", strerror(errno));
+               goto out;
+       }
+       status = 0;
+out:
+       return status;
 }
 
 static void handle_internal_command(int argc, const char **argv)
@@ -467,7 +476,8 @@ int main(int argc, const char **argv)
                cmd += 5;
                argv[0] = cmd;
                handle_internal_command(argc, argv);
-               die("cannot handle %s internally", cmd);
+               fprintf(stderr, "cannot handle %s internally", cmd);
+               goto out;
        }
 
        /* Look for flags.. */
@@ -485,7 +495,7 @@ int main(int argc, const char **argv)
                printf("\n usage: %s\n\n", perf_usage_string);
                list_common_cmds_help();
                printf("\n %s\n\n", perf_more_info_string);
-               exit(1);
+               goto out;
        }
        cmd = argv[0];
 
@@ -517,7 +527,7 @@ int main(int argc, const char **argv)
                        fprintf(stderr, "Expansion of alias '%s' failed; "
                                "'%s' is not a perf-command\n",
                                cmd, argv[0]);
-                       exit(1);
+                       goto out;
                }
                if (!done_help) {
                        cmd = argv[0] = help_unknown_cmd(cmd);
@@ -528,6 +538,6 @@ int main(int argc, const char **argv)
 
        fprintf(stderr, "Failed to run command '%s': %s\n",
                cmd, strerror(errno));
-
+out:
        return 1;
 }
index 2c340e7da458e4fa53b2c08914f1acd976fa90c5..c2206c87fc9fefaca6c6a75d35e7210fdd4eb707 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef _PERF_PERF_H
 #define _PERF_PERF_H
 
-struct winsize;
-
-void get_term_dimensions(struct winsize *ws);
-
 #include <asm/unistd.h>
 
 #if defined(__i386__)
@@ -107,32 +103,6 @@ void get_term_dimensions(struct winsize *ws);
 #include "util/types.h"
 #include <stdbool.h>
 
-struct perf_mmap {
-       void                    *base;
-       int                     mask;
-       unsigned int            prev;
-};
-
-static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
-{
-       struct perf_event_mmap_page *pc = mm->base;
-       int head = pc->data_head;
-       rmb();
-       return head;
-}
-
-static inline void perf_mmap__write_tail(struct perf_mmap *md,
-                                        unsigned long tail)
-{
-       struct perf_event_mmap_page *pc = md->base;
-
-       /*
-        * ensure all reads are done before we write the tail out.
-        */
-       /* mb(); */
-       pc->data_tail = tail;
-}
-
 /*
  * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all
  * counters in the current task.
@@ -237,8 +207,6 @@ struct perf_record_opts {
        bool         raw_samples;
        bool         sample_address;
        bool         sample_time;
-       bool         sample_id_all_missing;
-       bool         exclude_guest_missing;
        bool         period;
        unsigned int freq;
        unsigned int mmap_pages;
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
deleted file mode 100644 (file)
index 8edda90..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
deleted file mode 100644 (file)
index 6d91411..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: workqueue stats (ins/exe/create/destroy)
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
index 4bb3ecd33472498b186afe3b809d9431737e4c03..8b20787021c1d211fc709b21ac6b77deaf3a288b 100644 (file)
@@ -17,6 +17,7 @@ use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
 use lib "./Perf-Trace-Util/lib";
 use Perf::Trace::Core;
 use Perf::Trace::Util;
+use POSIX qw/SIGALRM SA_RESTART/;
 
 my $default_interval = 3;
 my $nlines = 20;
@@ -90,7 +91,10 @@ sub syscalls::sys_enter_write
 
 sub trace_begin
 {
-    $SIG{ALRM} = \&set_print_pending;
+    my $sa = POSIX::SigAction->new(\&set_print_pending);
+    $sa->flags(SA_RESTART);
+    $sa->safe(1);
+    POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n";
     alarm 1;
 }
 
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
deleted file mode 100644 (file)
index a8eaff5..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/perl -w
-# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-
-# Displays workqueue stats
-#
-# Usage:
-#
-#   perf record -c 1 -f -a -R -e workqueue:workqueue_creation -e
-#     workqueue:workqueue_destruction -e workqueue:workqueue_execution
-#     -e workqueue:workqueue_insertion
-#
-#   perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl
-
-use 5.010000;
-use strict;
-use warnings;
-
-use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
-use lib "./Perf-Trace-Util/lib";
-use Perf::Trace::Core;
-use Perf::Trace::Util;
-
-my @cpus;
-
-sub workqueue::workqueue_destruction
-{
-    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
-       $common_pid, $common_comm,
-       $thread_comm, $thread_pid) = @_;
-
-    $cpus[$common_cpu]{$thread_pid}{destroyed}++;
-    $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
-}
-
-sub workqueue::workqueue_creation
-{
-    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
-       $common_pid, $common_comm,
-       $thread_comm, $thread_pid, $cpu) = @_;
-
-    $cpus[$common_cpu]{$thread_pid}{created}++;
-    $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
-}
-
-sub workqueue::workqueue_execution
-{
-    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
-       $common_pid, $common_comm,
-       $thread_comm, $thread_pid, $func) = @_;
-
-    $cpus[$common_cpu]{$thread_pid}{executed}++;
-    $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
-}
-
-sub workqueue::workqueue_insertion
-{
-    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
-       $common_pid, $common_comm,
-       $thread_comm, $thread_pid, $func) = @_;
-
-    $cpus[$common_cpu]{$thread_pid}{inserted}++;
-    $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm;
-}
-
-sub trace_end
-{
-    print "workqueue work stats:\n\n";
-    my $cpu = 0;
-    printf("%3s %6s %6s\t%-20s\n", "cpu", "ins", "exec", "name");
-    printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----");
-    foreach my $pidhash (@cpus) {
-       while ((my $pid, my $wqhash) = each %$pidhash) {
-           my $ins = $$wqhash{'inserted'} || 0;
-           my $exe = $$wqhash{'executed'} || 0;
-           my $comm = $$wqhash{'comm'} || "";
-           if ($ins || $exe) {
-               printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm);
-           }
-       }
-       $cpu++;
-    }
-
-    $cpu = 0;
-    print "\nworkqueue lifecycle stats:\n\n";
-    printf("%3s %6s %6s\t%-20s\n", "cpu", "created", "destroyed", "name");
-    printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----");
-    foreach my $pidhash (@cpus) {
-       while ((my $pid, my $wqhash) = each %$pidhash) {
-           my $created = $$wqhash{'created'} || 0;
-           my $destroyed = $$wqhash{'destroyed'} || 0;
-           my $comm = $$wqhash{'comm'} || "";
-           if ($created || $destroyed) {
-               printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed,
-                      $comm);
-           }
-       }
-       $cpu++;
-    }
-
-    print_unhandled();
-}
-
-my %unhandled;
-
-sub print_unhandled
-{
-    if ((scalar keys %unhandled) == 0) {
-       return;
-    }
-
-    print "\nunhandled events:\n\n";
-
-    printf("%-40s  %10s\n", "event", "count");
-    printf("%-40s  %10s\n", "----------------------------------------",
-          "-----------");
-
-    foreach my $event_name (keys %unhandled) {
-       printf("%-40s  %10d\n", $event_name, $unhandled{$event_name});
-    }
-}
-
-sub trace_unhandled
-{
-    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
-       $common_pid, $common_comm) = @_;
-
-    $unhandled{$event_name}++;
-}
index 25638a986257a58ef664f5d68b39833987988406..bdcceb886f77fc5f8ae91e3d79b2da4ccd11d09c 100644 (file)
  * permissions. All the event text files are stored there.
  */
 
+/*
+ * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
+ * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
+ */
+#define __SANE_USERSPACE_TYPES__
 #include <stdlib.h>
 #include <stdio.h>
 #include <inttypes.h>
@@ -33,8 +38,6 @@
 
 extern int verbose;
 
-bool test_attr__enabled;
-
 static char *dir;
 
 void test_attr__init(void)
@@ -146,7 +149,7 @@ static int run_dir(const char *d, const char *perf)
 {
        char cmd[3*PATH_MAX];
 
-       snprintf(cmd, 3*PATH_MAX, "python %s/attr.py -d %s/attr/ -p %s %s",
+       snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %s",
                 d, d, perf, verbose ? "-v" : "");
 
        return system(cmd);
index e702b82dcb86e91a528b287d250c8cf8d4ba0667..2f629ca485bc32f6c04c773f6ad36623d7ee171e 100644 (file)
@@ -68,7 +68,7 @@ class Event(dict):
             self[key] = val
 
     def __init__(self, name, data, base):
-        log.info("    Event %s" % name);
+        log.debug("    Event %s" % name);
         self.name  = name;
         self.group = ''
         self.add(base)
@@ -97,6 +97,14 @@ class Event(dict):
                 return False
         return True
 
+    def diff(self, other):
+        for t in Event.terms:
+            if not self.has_key(t) or not other.has_key(t):
+                continue
+            if not self.compare_data(self[t], other[t]):
+               log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
+                
+
 # Test file description needs to have following sections:
 # [config]
 #   - just single instance in file
@@ -113,7 +121,7 @@ class Test(object):
         parser = ConfigParser.SafeConfigParser()
         parser.read(path)
 
-        log.warning("running '%s'" % path)
+        log.debug("running '%s'" % path)
 
         self.path     = path
         self.test_dir = options.test_dir
@@ -128,7 +136,7 @@ class Test(object):
 
         self.expect   = {}
         self.result   = {}
-        log.info("  loading expected events");
+        log.debug("  loading expected events");
         self.load_events(path, self.expect)
 
     def is_event(self, name):
@@ -164,7 +172,7 @@ class Test(object):
               self.perf, self.command, tempdir, self.args)
         ret = os.WEXITSTATUS(os.system(cmd))
 
-        log.info("  running '%s' ret %d " % (cmd, ret))
+        log.warning("  running '%s' ret %d " % (cmd, ret))
 
         if ret != int(self.ret):
             raise Unsup(self)
@@ -172,7 +180,7 @@ class Test(object):
     def compare(self, expect, result):
         match = {}
 
-        log.info("  compare");
+        log.debug("  compare");
 
         # For each expected event find all matching
         # events in result. Fail if there's not any.
@@ -187,10 +195,11 @@ class Test(object):
                 else:
                     log.debug("    ->FAIL");
 
-            log.info("    match: [%s] matches %s" % (exp_name, str(exp_list)))
+            log.debug("    match: [%s] matches %s" % (exp_name, str(exp_list)))
 
             # we did not any matching event - fail
             if (not exp_list):
+               exp_event.diff(res_event)
                 raise Fail(self, 'match failure');
 
             match[exp_name] = exp_list
@@ -208,10 +217,10 @@ class Test(object):
                 if res_group not in match[group]:
                     raise Fail(self, 'group failure')
 
-                log.info("    group: [%s] matches group leader %s" %
+                log.debug("    group: [%s] matches group leader %s" %
                          (exp_name, str(match[group])))
 
-        log.info("  matched")
+        log.debug("  matched")
 
     def resolve_groups(self, events):
         for name, event in events.items():
@@ -233,7 +242,7 @@ class Test(object):
             self.run_cmd(tempdir);
 
             # load events expectation for the test
-            log.info("  loading result events");
+            log.debug("  loading result events");
             for f in glob.glob(tempdir + '/event*'):
                 self.load_events(f, self.result);
 
index f1485d8e6a0b473550473784f9a8de435e544d57..5bc3880f7be5096d7366355763df58a0d4f2016d 100644 (file)
@@ -7,7 +7,7 @@ size=96
 config=0
 sample_period=4000
 sample_type=263
-read_format=7
+read_format=0
 disabled=1
 inherit=1
 pinned=0
index a6599e9a19d302134359941e92e579c465e80989..57739cacdb2aa10841b16ca1386fe6f8b0ab9db5 100644 (file)
@@ -6,12 +6,14 @@ args    = --group -e cycles,instructions kill >/dev/null 2>&1
 fd=1
 group_fd=-1
 sample_type=327
+read_format=4
 
 [event-2:base-record]
 fd=2
 group_fd=1
 config=1
 sample_type=327
+read_format=4
 mmap=0
 comm=0
 enable_on_exec=0
index 5a8359da38af9ed26f4c51ca84026bce2b3f2454..c5548d054aff5ba9ded3225494d9954f22c1e7b2 100644 (file)
@@ -1,11 +1,12 @@
 [config]
 command = record
-args    = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
+args    = -e '{cycles,instructions}' kill >/dev/null 2>&1
 
 [event-1:base-record]
 fd=1
 group_fd=-1
 sample_type=327
+read_format=4
 
 [event-2:base-record]
 fd=2
@@ -13,6 +14,7 @@ group_fd=1
 type=0
 config=1
 sample_type=327
+read_format=4
 mmap=0
 comm=0
 enable_on_exec=0
index 186f675354945cac0e870502e450cec1e9a38a63..acb98e0e39f2957426a74c0e0a8858d2ead85331 100644 (file)
@@ -4,6 +4,7 @@
  * Builtin regression testing command: ever growing number of sanity tests
  */
 #include "builtin.h"
+#include "intlist.h"
 #include "tests.h"
 #include "debug.h"
 #include "color.h"
@@ -68,6 +69,14 @@ static struct test {
                .desc = "struct perf_event_attr setup",
                .func = test__attr,
        },
+       {
+               .desc = "Test matching and linking mutliple hists",
+               .func = test__hists_link,
+       },
+       {
+               .desc = "Try 'use perf' in python, checking link problems",
+               .func = test__python_use,
+       },
        {
                .func = NULL,
        },
@@ -97,7 +106,7 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
        return false;
 }
 
-static int __cmd_test(int argc, const char *argv[])
+static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
 {
        int i = 0;
        int width = 0;
@@ -118,13 +127,28 @@ static int __cmd_test(int argc, const char *argv[])
                        continue;
 
                pr_info("%2d: %-*s:", i, width, tests[curr].desc);
+
+               if (intlist__find(skiplist, i)) {
+                       color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
+                       continue;
+               }
+
                pr_debug("\n--- start ---\n");
                err = tests[curr].func();
                pr_debug("---- end ----\n%s:", tests[curr].desc);
-               if (err)
-                       color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
-               else
+
+               switch (err) {
+               case TEST_OK:
                        pr_info(" Ok\n");
+                       break;
+               case TEST_SKIP:
+                       color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
+                       break;
+               case TEST_FAIL:
+               default:
+                       color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
+                       break;
+               }
        }
 
        return 0;
@@ -152,11 +176,14 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
        "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
        NULL,
        };
+       const char *skip = NULL;
        const struct option test_options[] = {
+       OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show symbol address, etc)"),
        OPT_END()
        };
+       struct intlist *skiplist = NULL;
 
        argc = parse_options(argc, argv, test_options, test_usage, 0);
        if (argc >= 1 && !strcmp(argv[0], "list"))
@@ -169,5 +196,8 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
        if (symbol__init() < 0)
                return -1;
 
-       return __cmd_test(argc, argv);
+       if (skip != NULL)
+               skiplist = intlist__new(skip);
+
+       return __cmd_test(argc, argv, skiplist);
 }
index e61fc828a158ac771b6e09897f78fc8593b3392c..0fd99a9adb916293d91cd80797355b92940906d8 100644 (file)
@@ -22,7 +22,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)
                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
                                __perf_evsel__hw_cache_type_op_res_name(type, op, i,
                                                                        name, sizeof(name));
-                               err = parse_events(evlist, name, 0);
+                               err = parse_events(evlist, name);
                                if (err)
                                        ret = err;
                        }
@@ -70,7 +70,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
                 return -ENOMEM;
 
        for (i = 0; i < nr_names; ++i) {
-               err = parse_events(evlist, names[i], 0);
+               err = parse_events(evlist, names[i]);
                if (err) {
                        pr_debug("failed to parse event '%s', err %d\n",
                                 names[i], err);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
new file mode 100644 (file)
index 0000000..1be64a6
--- /dev/null
@@ -0,0 +1,500 @@
+#include "perf.h"
+#include "tests.h"
+#include "debug.h"
+#include "symbol.h"
+#include "sort.h"
+#include "evsel.h"
+#include "evlist.h"
+#include "machine.h"
+#include "thread.h"
+#include "parse-events.h"
+
+static struct {
+       u32 pid;
+       const char *comm;
+} fake_threads[] = {
+       { 100, "perf" },
+       { 200, "perf" },
+       { 300, "bash" },
+};
+
+static struct {
+       u32 pid;
+       u64 start;
+       const char *filename;
+} fake_mmap_info[] = {
+       { 100, 0x40000, "perf" },
+       { 100, 0x50000, "libc" },
+       { 100, 0xf0000, "[kernel]" },
+       { 200, 0x40000, "perf" },
+       { 200, 0x50000, "libc" },
+       { 200, 0xf0000, "[kernel]" },
+       { 300, 0x40000, "bash" },
+       { 300, 0x50000, "libc" },
+       { 300, 0xf0000, "[kernel]" },
+};
+
+struct fake_sym {
+       u64 start;
+       u64 length;
+       const char *name;
+};
+
+static struct fake_sym perf_syms[] = {
+       { 700, 100, "main" },
+       { 800, 100, "run_command" },
+       { 900, 100, "cmd_record" },
+};
+
+static struct fake_sym bash_syms[] = {
+       { 700, 100, "main" },
+       { 800, 100, "xmalloc" },
+       { 900, 100, "xfree" },
+};
+
+static struct fake_sym libc_syms[] = {
+       { 700, 100, "malloc" },
+       { 800, 100, "free" },
+       { 900, 100, "realloc" },
+};
+
+static struct fake_sym kernel_syms[] = {
+       { 700, 100, "schedule" },
+       { 800, 100, "page_fault" },
+       { 900, 100, "sys_perf_event_open" },
+};
+
+static struct {
+       const char *dso_name;
+       struct fake_sym *syms;
+       size_t nr_syms;
+} fake_symbols[] = {
+       { "perf", perf_syms, ARRAY_SIZE(perf_syms) },
+       { "bash", bash_syms, ARRAY_SIZE(bash_syms) },
+       { "libc", libc_syms, ARRAY_SIZE(libc_syms) },
+       { "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) },
+};
+
+static struct machine *setup_fake_machine(struct machines *machines)
+{
+       struct machine *machine = machines__find(machines, HOST_KERNEL_ID);
+       size_t i;
+
+       if (machine == NULL) {
+               pr_debug("Not enough memory for machine setup\n");
+               return NULL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(fake_threads); i++) {
+               struct thread *thread;
+
+               thread = machine__findnew_thread(machine, fake_threads[i].pid);
+               if (thread == NULL)
+                       goto out;
+
+               thread__set_comm(thread, fake_threads[i].comm);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
+               union perf_event fake_mmap_event = {
+                       .mmap = {
+                               .header = { .misc = PERF_RECORD_MISC_USER, },
+                               .pid = fake_mmap_info[i].pid,
+                               .start = fake_mmap_info[i].start,
+                               .len = 0x1000ULL,
+                               .pgoff = 0ULL,
+                       },
+               };
+
+               strcpy(fake_mmap_event.mmap.filename,
+                      fake_mmap_info[i].filename);
+
+               machine__process_mmap_event(machine, &fake_mmap_event);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
+               size_t k;
+               struct dso *dso;
+
+               dso = __dsos__findnew(&machine->user_dsos,
+                                     fake_symbols[i].dso_name);
+               if (dso == NULL)
+                       goto out;
+
+               /* emulate dso__load() */
+               dso__set_loaded(dso, MAP__FUNCTION);
+
+               for (k = 0; k < fake_symbols[i].nr_syms; k++) {
+                       struct symbol *sym;
+                       struct fake_sym *fsym = &fake_symbols[i].syms[k];
+
+                       sym = symbol__new(fsym->start, fsym->length,
+                                         STB_GLOBAL, fsym->name);
+                       if (sym == NULL)
+                               goto out;
+
+                       symbols__insert(&dso->symbols[MAP__FUNCTION], sym);
+               }
+       }
+
+       return machine;
+
+out:
+       pr_debug("Not enough memory for machine setup\n");
+       machine__delete_threads(machine);
+       machine__delete(machine);
+       return NULL;
+}
+
+struct sample {
+       u32 pid;
+       u64 ip;
+       struct thread *thread;
+       struct map *map;
+       struct symbol *sym;
+};
+
+static struct sample fake_common_samples[] = {
+       /* perf [kernel] schedule() */
+       { .pid = 100, .ip = 0xf0000 + 700, },
+       /* perf [perf]   main() */
+       { .pid = 200, .ip = 0x40000 + 700, },
+       /* perf [perf]   cmd_record() */
+       { .pid = 200, .ip = 0x40000 + 900, },
+       /* bash [bash]   xmalloc() */
+       { .pid = 300, .ip = 0x40000 + 800, },
+       /* bash [libc]   malloc() */
+       { .pid = 300, .ip = 0x50000 + 700, },
+};
+
+static struct sample fake_samples[][5] = {
+       {
+               /* perf [perf]   run_command() */
+               { .pid = 100, .ip = 0x40000 + 800, },
+               /* perf [libc]   malloc() */
+               { .pid = 100, .ip = 0x50000 + 700, },
+               /* perf [kernel] page_fault() */
+               { .pid = 100, .ip = 0xf0000 + 800, },
+               /* perf [kernel] sys_perf_event_open() */
+               { .pid = 200, .ip = 0xf0000 + 900, },
+               /* bash [libc]   free() */
+               { .pid = 300, .ip = 0x50000 + 800, },
+       },
+       {
+               /* perf [libc]   free() */
+               { .pid = 200, .ip = 0x50000 + 800, },
+               /* bash [libc]   malloc() */
+               { .pid = 300, .ip = 0x50000 + 700, }, /* will be merged */
+               /* bash [bash]   xfee() */
+               { .pid = 300, .ip = 0x40000 + 900, },
+               /* bash [libc]   realloc() */
+               { .pid = 300, .ip = 0x50000 + 900, },
+               /* bash [kernel] page_fault() */
+               { .pid = 300, .ip = 0xf0000 + 800, },
+       },
+};
+
+static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
+{
+       struct perf_evsel *evsel;
+       struct addr_location al;
+       struct hist_entry *he;
+       struct perf_sample sample = { .cpu = 0, };
+       size_t i = 0, k;
+
+       /*
+        * each evsel will have 10 samples - 5 common and 5 distinct.
+        * However the second evsel also has a collapsed entry for
+        * "bash [libc] malloc" so total 9 entries will be in the tree.
+        */
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
+                       const union perf_event event = {
+                               .ip = {
+                                       .header = {
+                                               .misc = PERF_RECORD_MISC_USER,
+                                       },
+                                       .pid = fake_common_samples[k].pid,
+                                       .ip  = fake_common_samples[k].ip,
+                               },
+                       };
+
+                       if (perf_event__preprocess_sample(&event, machine, &al,
+                                                         &sample, 0) < 0)
+                               goto out;
+
+                       he = __hists__add_entry(&evsel->hists, &al, NULL, 1);
+                       if (he == NULL)
+                               goto out;
+
+                       fake_common_samples[k].thread = al.thread;
+                       fake_common_samples[k].map = al.map;
+                       fake_common_samples[k].sym = al.sym;
+               }
+
+               for (k = 0; k < ARRAY_SIZE(fake_samples[i]); k++) {
+                       const union perf_event event = {
+                               .ip = {
+                                       .header = {
+                                               .misc = PERF_RECORD_MISC_USER,
+                                       },
+                                       .pid = fake_samples[i][k].pid,
+                                       .ip  = fake_samples[i][k].ip,
+                               },
+                       };
+
+                       if (perf_event__preprocess_sample(&event, machine, &al,
+                                                         &sample, 0) < 0)
+                               goto out;
+
+                       he = __hists__add_entry(&evsel->hists, &al, NULL, 1);
+                       if (he == NULL)
+                               goto out;
+
+                       fake_samples[i][k].thread = al.thread;
+                       fake_samples[i][k].map = al.map;
+                       fake_samples[i][k].sym = al.sym;
+               }
+               i++;
+       }
+
+       return 0;
+
+out:
+       pr_debug("Not enough memory for adding a hist entry\n");
+       return -1;
+}
+
+static int find_sample(struct sample *samples, size_t nr_samples,
+                      struct thread *t, struct map *m, struct symbol *s)
+{
+       while (nr_samples--) {
+               if (samples->thread == t && samples->map == m &&
+                   samples->sym == s)
+                       return 1;
+               samples++;
+       }
+       return 0;
+}
+
+static int __validate_match(struct hists *hists)
+{
+       size_t count = 0;
+       struct rb_root *root;
+       struct rb_node *node;
+
+       /*
+        * Only entries from fake_common_samples should have a pair.
+        */
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       node = rb_first(root);
+       while (node) {
+               struct hist_entry *he;
+
+               he = rb_entry(node, struct hist_entry, rb_node_in);
+
+               if (hist_entry__has_pairs(he)) {
+                       if (find_sample(fake_common_samples,
+                                       ARRAY_SIZE(fake_common_samples),
+                                       he->thread, he->ms.map, he->ms.sym)) {
+                               count++;
+                       } else {
+                               pr_debug("Can't find the matched entry\n");
+                               return -1;
+                       }
+               }
+
+               node = rb_next(node);
+       }
+
+       if (count != ARRAY_SIZE(fake_common_samples)) {
+               pr_debug("Invalid count for matched entries: %zd of %zd\n",
+                        count, ARRAY_SIZE(fake_common_samples));
+               return -1;
+       }
+
+       return 0;
+}
+
+static int validate_match(struct hists *leader, struct hists *other)
+{
+       return __validate_match(leader) || __validate_match(other);
+}
+
+static int __validate_link(struct hists *hists, int idx)
+{
+       size_t count = 0;
+       size_t count_pair = 0;
+       size_t count_dummy = 0;
+       struct rb_root *root;
+       struct rb_node *node;
+
+       /*
+        * Leader hists (idx = 0) will have dummy entries from other,
+        * and some entries will have no pair.  However every entry
+        * in other hists should have (dummy) pair.
+        */
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       node = rb_first(root);
+       while (node) {
+               struct hist_entry *he;
+
+               he = rb_entry(node, struct hist_entry, rb_node_in);
+
+               if (hist_entry__has_pairs(he)) {
+                       if (!find_sample(fake_common_samples,
+                                        ARRAY_SIZE(fake_common_samples),
+                                        he->thread, he->ms.map, he->ms.sym) &&
+                           !find_sample(fake_samples[idx],
+                                        ARRAY_SIZE(fake_samples[idx]),
+                                        he->thread, he->ms.map, he->ms.sym)) {
+                               count_dummy++;
+                       }
+                       count_pair++;
+               } else if (idx) {
+                       pr_debug("A entry from the other hists should have pair\n");
+                       return -1;
+               }
+
+               count++;
+               node = rb_next(node);
+       }
+
+       /*
+        * Note that we have a entry collapsed in the other (idx = 1) hists.
+        */
+       if (idx == 0) {
+               if (count_dummy != ARRAY_SIZE(fake_samples[1]) - 1) {
+                       pr_debug("Invalid count of dummy entries: %zd of %zd\n",
+                                count_dummy, ARRAY_SIZE(fake_samples[1]) - 1);
+                       return -1;
+               }
+               if (count != count_pair + ARRAY_SIZE(fake_samples[0])) {
+                       pr_debug("Invalid count of total leader entries: %zd of %zd\n",
+                                count, count_pair + ARRAY_SIZE(fake_samples[0]));
+                       return -1;
+               }
+       } else {
+               if (count != count_pair) {
+                       pr_debug("Invalid count of total other entries: %zd of %zd\n",
+                                count, count_pair);
+                       return -1;
+               }
+               if (count_dummy > 0) {
+                       pr_debug("Other hists should not have dummy entries: %zd\n",
+                                count_dummy);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static int validate_link(struct hists *leader, struct hists *other)
+{
+       return __validate_link(leader, 0) || __validate_link(other, 1);
+}
+
+static void print_hists(struct hists *hists)
+{
+       int i = 0;
+       struct rb_root *root;
+       struct rb_node *node;
+
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       pr_info("----- %s --------\n", __func__);
+       node = rb_first(root);
+       while (node) {
+               struct hist_entry *he;
+
+               he = rb_entry(node, struct hist_entry, rb_node_in);
+
+               pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
+                       i, he->thread->comm, he->ms.map->dso->short_name,
+                       he->ms.sym->name, he->stat.period);
+
+               i++;
+               node = rb_next(node);
+       }
+}
+
+int test__hists_link(void)
+{
+       int err = -1;
+       struct machines machines;
+       struct machine *machine = NULL;
+       struct perf_evsel *evsel, *first;
+        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
+
+       if (evlist == NULL)
+                return -ENOMEM;
+
+       err = parse_events(evlist, "cpu-clock");
+       if (err)
+               goto out;
+       err = parse_events(evlist, "task-clock");
+       if (err)
+               goto out;
+
+       /* default sort order (comm,dso,sym) will be used */
+       if (setup_sorting() < 0)
+               goto out;
+
+       machines__init(&machines);
+
+       /* setup threads/dso/map/symbols also */
+       machine = setup_fake_machine(&machines);
+       if (!machine)
+               goto out;
+
+       if (verbose > 1)
+               machine__fprintf(machine, stderr);
+
+       /* process sample events */
+       err = add_hist_entries(evlist, machine);
+       if (err < 0)
+               goto out;
+
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               hists__collapse_resort(&evsel->hists);
+
+               if (verbose > 2)
+                       print_hists(&evsel->hists);
+       }
+
+       first = perf_evlist__first(evlist);
+       evsel = perf_evlist__last(evlist);
+
+       /* match common entries */
+       hists__match(&first->hists, &evsel->hists);
+       err = validate_match(&first->hists, &evsel->hists);
+       if (err)
+               goto out;
+
+       /* link common and/or dummy entries */
+       hists__link(&first->hists, &evsel->hists);
+       err = validate_link(&first->hists, &evsel->hists);
+       if (err)
+               goto out;
+
+       err = 0;
+
+out:
+       /* tear down everything */
+       perf_evlist__delete(evlist);
+       machines__exit(&machines);
+
+       return err;
+}
index e1746811e14bab193788e294540119f3f7100de3..cdd50755af51d6155e1fcf875965ae5576fe70d1 100644 (file)
@@ -22,36 +22,16 @@ int test__basic_mmap(void)
        struct thread_map *threads;
        struct cpu_map *cpus;
        struct perf_evlist *evlist;
-       struct perf_event_attr attr = {
-               .type           = PERF_TYPE_TRACEPOINT,
-               .read_format    = PERF_FORMAT_ID,
-               .sample_type    = PERF_SAMPLE_ID,
-               .watermark      = 0,
-       };
        cpu_set_t cpu_set;
        const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
                                        "getpgid", };
        pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
                                      (void*)getpgid };
 #define nsyscalls ARRAY_SIZE(syscall_names)
-       int ids[nsyscalls];
        unsigned int nr_events[nsyscalls],
                     expected_nr_events[nsyscalls], i, j;
        struct perf_evsel *evsels[nsyscalls], *evsel;
 
-       for (i = 0; i < nsyscalls; ++i) {
-               char name[64];
-
-               snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
-               ids[i] = trace_event__id(name);
-               if (ids[i] < 0) {
-                       pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
-                       return -1;
-               }
-               nr_events[i] = 0;
-               expected_nr_events[i] = random() % 257;
-       }
-
        threads = thread_map__new(-1, getpid(), UINT_MAX);
        if (threads == NULL) {
                pr_debug("thread_map__new\n");
@@ -79,18 +59,19 @@ int test__basic_mmap(void)
                goto out_free_cpus;
        }
 
-       /* anonymous union fields, can't be initialized above */
-       attr.wakeup_events = 1;
-       attr.sample_period = 1;
-
        for (i = 0; i < nsyscalls; ++i) {
-               attr.config = ids[i];
-               evsels[i] = perf_evsel__new(&attr, i);
+               char name[64];
+
+               snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
+               evsels[i] = perf_evsel__newtp("syscalls", name, i);
                if (evsels[i] == NULL) {
                        pr_debug("perf_evsel__new\n");
                        goto out_free_evlist;
                }
 
+               evsels[i]->attr.wakeup_events = 1;
+               perf_evsel__set_sample_id(evsels[i]);
+
                perf_evlist__add(evlist, evsels[i]);
 
                if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
@@ -99,6 +80,9 @@ int test__basic_mmap(void)
                                 strerror(errno));
                        goto out_close_fd;
                }
+
+               nr_events[i] = 0;
+               expected_nr_events[i] = 1 + rand() % 127;
        }
 
        if (perf_evlist__mmap(evlist, 128, true) < 0) {
@@ -128,6 +112,7 @@ int test__basic_mmap(void)
                        goto out_munmap;
                }
 
+               err = -1;
                evsel = perf_evlist__id2evsel(evlist, sample.id);
                if (evsel == NULL) {
                        pr_debug("event with id %" PRIu64
@@ -137,16 +122,17 @@ int test__basic_mmap(void)
                nr_events[evsel->idx]++;
        }
 
+       err = 0;
        list_for_each_entry(evsel, &evlist->entries, node) {
                if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
                        pr_debug("expected %d %s events, got %d\n",
                                 expected_nr_events[evsel->idx],
                                 perf_evsel__name(evsel), nr_events[evsel->idx]);
+                       err = -1;
                        goto out_munmap;
                }
        }
 
-       err = 0;
 out_munmap:
        perf_evlist__munmap(evlist);
 out_close_fd:
index 31072aba0d549d1690ee147e5cd06102de8852b3..b0657a9ccda638febdcd39c40f30cecf06c0ece6 100644 (file)
@@ -7,20 +7,12 @@
 int test__open_syscall_event_on_all_cpus(void)
 {
        int err = -1, fd, cpu;
-       struct thread_map *threads;
        struct cpu_map *cpus;
        struct perf_evsel *evsel;
-       struct perf_event_attr attr;
        unsigned int nr_open_calls = 111, i;
        cpu_set_t cpu_set;
-       int id = trace_event__id("sys_enter_open");
+       struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
 
-       if (id < 0) {
-               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
-               return -1;
-       }
-
-       threads = thread_map__new(-1, getpid(), UINT_MAX);
        if (threads == NULL) {
                pr_debug("thread_map__new\n");
                return -1;
@@ -32,15 +24,11 @@ int test__open_syscall_event_on_all_cpus(void)
                goto out_thread_map_delete;
        }
 
-
        CPU_ZERO(&cpu_set);
 
-       memset(&attr, 0, sizeof(attr));
-       attr.type = PERF_TYPE_TRACEPOINT;
-       attr.config = id;
-       evsel = perf_evsel__new(&attr, 0);
+       evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
        if (evsel == NULL) {
-               pr_debug("perf_evsel__new\n");
+               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
                goto out_thread_map_delete;
        }
 
@@ -110,6 +98,7 @@ int test__open_syscall_event_on_all_cpus(void)
                }
        }
 
+       perf_evsel__free_counts(evsel);
 out_close_fd:
        perf_evsel__close_fd(evsel, 1, threads->nr);
 out_evsel_delete:
index 98be8b518b4fe6613fe5988594bb430768a5ccca..befc0671f95dab0162ec67c5e7ed60ea7f0c0b53 100644 (file)
@@ -6,29 +6,18 @@
 int test__open_syscall_event(void)
 {
        int err = -1, fd;
-       struct thread_map *threads;
        struct perf_evsel *evsel;
-       struct perf_event_attr attr;
        unsigned int nr_open_calls = 111, i;
-       int id = trace_event__id("sys_enter_open");
+       struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
 
-       if (id < 0) {
-               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
-               return -1;
-       }
-
-       threads = thread_map__new(-1, getpid(), UINT_MAX);
        if (threads == NULL) {
                pr_debug("thread_map__new\n");
                return -1;
        }
 
-       memset(&attr, 0, sizeof(attr));
-       attr.type = PERF_TYPE_TRACEPOINT;
-       attr.config = id;
-       evsel = perf_evsel__new(&attr, 0);
+       evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
        if (evsel == NULL) {
-               pr_debug("perf_evsel__new\n");
+               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
                goto out_thread_map_delete;
        }
 
index 32ee478905eb8ed0bd182bed13fd3a57bb0746bd..c5636f36fe3128e279115ff3ece1faddacfb58d5 100644 (file)
@@ -3,6 +3,7 @@
 #include "evsel.h"
 #include "evlist.h"
 #include "sysfs.h"
+#include "debugfs.h"
 #include "tests.h"
 #include <linux/hw_breakpoint.h>
 
@@ -22,6 +23,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)
        struct perf_evsel *evsel = perf_evlist__first(evlist);
 
        TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
        TEST_ASSERT_VAL("wrong sample_type",
                PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
@@ -34,6 +36,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
        struct perf_evsel *evsel;
 
        TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+       TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
 
        list_for_each_entry(evsel, &evlist->entries, node) {
                TEST_ASSERT_VAL("wrong type",
@@ -463,10 +466,10 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist)
 
 static int test__checkterms_simple(struct list_head *terms)
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
        /* config=10 */
-       term = list_entry(terms->next, struct parse_events__term, list);
+       term = list_entry(terms->next, struct parse_events_term, list);
        TEST_ASSERT_VAL("wrong type term",
                        term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
        TEST_ASSERT_VAL("wrong type val",
@@ -475,7 +478,7 @@ static int test__checkterms_simple(struct list_head *terms)
        TEST_ASSERT_VAL("wrong config", !term->config);
 
        /* config1 */
-       term = list_entry(term->list.next, struct parse_events__term, list);
+       term = list_entry(term->list.next, struct parse_events_term, list);
        TEST_ASSERT_VAL("wrong type term",
                        term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
        TEST_ASSERT_VAL("wrong type val",
@@ -484,7 +487,7 @@ static int test__checkterms_simple(struct list_head *terms)
        TEST_ASSERT_VAL("wrong config", !term->config);
 
        /* config2=3 */
-       term = list_entry(term->list.next, struct parse_events__term, list);
+       term = list_entry(term->list.next, struct parse_events_term, list);
        TEST_ASSERT_VAL("wrong type term",
                        term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
        TEST_ASSERT_VAL("wrong type val",
@@ -493,7 +496,7 @@ static int test__checkterms_simple(struct list_head *terms)
        TEST_ASSERT_VAL("wrong config", !term->config);
 
        /* umask=1*/
-       term = list_entry(term->list.next, struct parse_events__term, list);
+       term = list_entry(term->list.next, struct parse_events_term, list);
        TEST_ASSERT_VAL("wrong type term",
                        term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
        TEST_ASSERT_VAL("wrong type val",
@@ -509,6 +512,7 @@ static int test__group1(struct perf_evlist *evlist)
        struct perf_evsel *evsel, *leader;
 
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
        /* instructions:k */
        evsel = leader = perf_evlist__first(evlist);
@@ -521,7 +525,9 @@ static int test__group1(struct perf_evlist *evlist)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* cycles:upp */
        evsel = perf_evsel__next(evsel);
@@ -536,6 +542,7 @@ static int test__group1(struct perf_evlist *evlist)
        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);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        return 0;
 }
@@ -545,6 +552,7 @@ static int test__group2(struct perf_evlist *evlist)
        struct perf_evsel *evsel, *leader;
 
        TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
        /* faults + :ku modifier */
        evsel = leader = perf_evlist__first(evlist);
@@ -557,7 +565,9 @@ static int test__group2(struct perf_evlist *evlist)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* cache-references + :u modifier */
        evsel = perf_evsel__next(evsel);
@@ -567,10 +577,11 @@ static int test__group2(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);
+       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);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        /* cycles:k */
        evsel = perf_evsel__next(evsel);
@@ -583,7 +594,7 @@ static int test__group2(struct perf_evlist *evlist)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
 
        return 0;
 }
@@ -593,6 +604,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        struct perf_evsel *evsel, *leader;
 
        TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
 
        /* group1 syscalls:sys_enter_open:H */
        evsel = leader = perf_evlist__first(evlist);
@@ -606,9 +618,11 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
        TEST_ASSERT_VAL("wrong group name",
                !strcmp(leader->group_name, "group1"));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* group1 cycles:kppp */
        evsel = perf_evsel__next(evsel);
@@ -624,6 +638,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        /* group2 cycles + G modifier */
        evsel = leader = perf_evsel__next(evsel);
@@ -636,9 +651,11 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
        TEST_ASSERT_VAL("wrong group name",
                !strcmp(leader->group_name, "group2"));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* group2 1:3 + G modifier */
        evsel = perf_evsel__next(evsel);
@@ -651,6 +668,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        /* instructions:u */
        evsel = perf_evsel__next(evsel);
@@ -663,7 +681,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
 
        return 0;
 }
@@ -673,6 +691,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        struct perf_evsel *evsel, *leader;
 
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
 
        /* cycles:u + p */
        evsel = leader = perf_evlist__first(evlist);
@@ -687,7 +706,9 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* instructions:kp + p */
        evsel = perf_evsel__next(evsel);
@@ -702,6 +723,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        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);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        return 0;
 }
@@ -711,6 +733,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        struct perf_evsel *evsel, *leader;
 
        TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups);
 
        /* cycles + G */
        evsel = leader = perf_evlist__first(evlist);
@@ -724,7 +747,9 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* instructions + G */
        evsel = perf_evsel__next(evsel);
@@ -738,6 +763,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        /* cycles:G */
        evsel = leader = perf_evsel__next(evsel);
@@ -751,7 +777,9 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
 
        /* instructions:G */
        evsel = perf_evsel__next(evsel);
@@ -765,6 +793,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        /* cycles */
        evsel = perf_evsel__next(evsel);
@@ -777,18 +806,235 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
        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);
-       TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+
+       return 0;
+}
+
+static int test__group_gh1(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel, *leader;
+
+       TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
+
+       /* cycles + :H group modifier */
+       evsel = leader = perf_evlist__first(evlist);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
+
+       /* cache-misses:G + :H group modifier */
+       evsel = perf_evsel__next(evsel);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
+
+       return 0;
+}
+
+static int test__group_gh2(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel, *leader;
+
+       TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
+
+       /* cycles + :G group modifier */
+       evsel = leader = perf_evlist__first(evlist);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
+
+       /* cache-misses:H + :G group modifier */
+       evsel = perf_evsel__next(evsel);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
+
+       return 0;
+}
+
+static int test__group_gh3(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel, *leader;
+
+       TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
+
+       /* cycles:G + :u group modifier */
+       evsel = leader = perf_evlist__first(evlist);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
+
+       /* cache-misses:H + :u group modifier */
+       evsel = perf_evsel__next(evsel);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
+
+       return 0;
+}
+
+static int test__group_gh4(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel, *leader;
+
+       TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups);
+
+       /* cycles:G + :uG group modifier */
+       evsel = leader = perf_evlist__first(evlist);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+       TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
+       TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
+
+       /* cache-misses:H + :uG group modifier */
+       evsel = perf_evsel__next(evsel);
+       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config",
+                       PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
+       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);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+       TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
 
        return 0;
 }
 
-struct test__event_st {
+static int count_tracepoints(void)
+{
+       char events_path[PATH_MAX];
+       struct dirent *events_ent;
+       DIR *events_dir;
+       int cnt = 0;
+
+       scnprintf(events_path, PATH_MAX, "%s/tracing/events",
+                 debugfs_find_mountpoint());
+
+       events_dir = opendir(events_path);
+
+       TEST_ASSERT_VAL("Can't open events dir", events_dir);
+
+       while ((events_ent = readdir(events_dir))) {
+               char sys_path[PATH_MAX];
+               struct dirent *sys_ent;
+               DIR *sys_dir;
+
+               if (!strcmp(events_ent->d_name, ".")
+                   || !strcmp(events_ent->d_name, "..")
+                   || !strcmp(events_ent->d_name, "enable")
+                   || !strcmp(events_ent->d_name, "header_event")
+                   || !strcmp(events_ent->d_name, "header_page"))
+                       continue;
+
+               scnprintf(sys_path, PATH_MAX, "%s/%s",
+                         events_path, events_ent->d_name);
+
+               sys_dir = opendir(sys_path);
+               TEST_ASSERT_VAL("Can't open sys dir", sys_dir);
+
+               while ((sys_ent = readdir(sys_dir))) {
+                       if (!strcmp(sys_ent->d_name, ".")
+                           || !strcmp(sys_ent->d_name, "..")
+                           || !strcmp(sys_ent->d_name, "enable")
+                           || !strcmp(sys_ent->d_name, "filter"))
+                               continue;
+
+                       cnt++;
+               }
+
+               closedir(sys_dir);
+       }
+
+       closedir(events_dir);
+       return cnt;
+}
+
+static int test__all_tracepoints(struct perf_evlist *evlist)
+{
+       TEST_ASSERT_VAL("wrong events count",
+                       count_tracepoints() == evlist->nr_entries);
+
+       return test__checkevent_tracepoint_multi(evlist);
+}
+
+struct evlist_test {
        const char *name;
        __u32 type;
        int (*check)(struct perf_evlist *evlist);
 };
 
-static struct test__event_st test__events[] = {
+static struct evlist_test test__events[] = {
        [0] = {
                .name  = "syscalls:sys_enter_open",
                .check = test__checkevent_tracepoint,
@@ -921,9 +1167,29 @@ static struct test__event_st test__events[] = {
                .name  = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
                .check = test__group5,
        },
+       [33] = {
+               .name  = "*:*",
+               .check = test__all_tracepoints,
+       },
+       [34] = {
+               .name  = "{cycles,cache-misses:G}:H",
+               .check = test__group_gh1,
+       },
+       [35] = {
+               .name  = "{cycles,cache-misses:H}:G",
+               .check = test__group_gh2,
+       },
+       [36] = {
+               .name  = "{cycles:G,cache-misses:H}:u",
+               .check = test__group_gh3,
+       },
+       [37] = {
+               .name  = "{cycles:G,cache-misses:H}:uG",
+               .check = test__group_gh4,
+       },
 };
 
-static struct test__event_st test__events_pmu[] = {
+static struct evlist_test test__events_pmu[] = {
        [0] = {
                .name  = "cpu/config=10,config1,config2=3,period=1000/u",
                .check = test__checkevent_pmu,
@@ -934,20 +1200,20 @@ static struct test__event_st test__events_pmu[] = {
        },
 };
 
-struct test__term {
+struct terms_test {
        const char *str;
        __u32 type;
        int (*check)(struct list_head *terms);
 };
 
-static struct test__term test__terms[] = {
+static struct terms_test test__terms[] = {
        [0] = {
                .str   = "config=10,config1,config2=3,umask=1",
                .check = test__checkterms_simple,
        },
 };
 
-static int test_event(struct test__event_st *e)
+static int test_event(struct evlist_test *e)
 {
        struct perf_evlist *evlist;
        int ret;
@@ -956,7 +1222,7 @@ static int test_event(struct test__event_st *e)
        if (evlist == NULL)
                return -ENOMEM;
 
-       ret = parse_events(evlist, e->name, 0);
+       ret = parse_events(evlist, e->name);
        if (ret) {
                pr_debug("failed to parse event '%s', err %d\n",
                         e->name, ret);
@@ -969,13 +1235,13 @@ static int test_event(struct test__event_st *e)
        return ret;
 }
 
-static int test_events(struct test__event_st *events, unsigned cnt)
+static int test_events(struct evlist_test *events, unsigned cnt)
 {
        int ret1, ret2 = 0;
        unsigned i;
 
        for (i = 0; i < cnt; i++) {
-               struct test__event_st *e = &events[i];
+               struct evlist_test *e = &events[i];
 
                pr_debug("running test %d '%s'\n", i, e->name);
                ret1 = test_event(e);
@@ -986,7 +1252,7 @@ static int test_events(struct test__event_st *events, unsigned cnt)
        return ret2;
 }
 
-static int test_term(struct test__term *t)
+static int test_term(struct terms_test *t)
 {
        struct list_head *terms;
        int ret;
@@ -1010,13 +1276,13 @@ static int test_term(struct test__term *t)
        return ret;
 }
 
-static int test_terms(struct test__term *terms, unsigned cnt)
+static int test_terms(struct terms_test *terms, unsigned cnt)
 {
        int ret = 0;
        unsigned i;
 
        for (i = 0; i < cnt; i++) {
-               struct test__term *t = &terms[i];
+               struct terms_test *t = &terms[i];
 
                pr_debug("running test %d '%s'\n", i, t->str);
                ret = test_term(t);
@@ -1067,7 +1333,7 @@ static int test_pmu_events(void)
 
        while (!ret && (ent = readdir(dir))) {
 #define MAX_NAME 100
-               struct test__event_st e;
+               struct evlist_test e;
                char name[MAX_NAME];
 
                if (!strcmp(ent->d_name, ".") ||
index 70e0d4421df884ba9a5f1091b47d52e1fb362024..1e8e5128d0da31a94fccfadc036cd8e0e48da8f4 100644 (file)
@@ -96,22 +96,22 @@ int test__PERF_RECORD(void)
        err = perf_evlist__prepare_workload(evlist, &opts, argv);
        if (err < 0) {
                pr_debug("Couldn't run the workload!\n");
-               goto out_delete_evlist;
+               goto out_delete_maps;
        }
 
        /*
         * Config the evsels, setting attr->comm on the first one, etc.
         */
        evsel = perf_evlist__first(evlist);
-       evsel->attr.sample_type |= PERF_SAMPLE_CPU;
-       evsel->attr.sample_type |= PERF_SAMPLE_TID;
-       evsel->attr.sample_type |= PERF_SAMPLE_TIME;
-       perf_evlist__config_attrs(evlist, &opts);
+       perf_evsel__set_sample_bit(evsel, CPU);
+       perf_evsel__set_sample_bit(evsel, TID);
+       perf_evsel__set_sample_bit(evsel, TIME);
+       perf_evlist__config(evlist, &opts);
 
        err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
        if (err < 0) {
                pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
-               goto out_delete_evlist;
+               goto out_delete_maps;
        }
 
        cpu = err;
@@ -121,7 +121,7 @@ int test__PERF_RECORD(void)
         */
        if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
                pr_debug("sched_setaffinity: %s\n", strerror(errno));
-               goto out_delete_evlist;
+               goto out_delete_maps;
        }
 
        /*
@@ -131,7 +131,7 @@ int test__PERF_RECORD(void)
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n", strerror(errno));
-               goto out_delete_evlist;
+               goto out_delete_maps;
        }
 
        /*
@@ -142,7 +142,7 @@ int test__PERF_RECORD(void)
        err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
-               goto out_delete_evlist;
+               goto out_delete_maps;
        }
 
        /*
@@ -305,6 +305,8 @@ found_exit:
        }
 out_err:
        perf_evlist__munmap(evlist);
+out_delete_maps:
+       perf_evlist__delete_maps(evlist);
 out_delete_evlist:
        perf_evlist__delete(evlist);
 out:
index a5f379863b8f8559a8b9d093dbe71fe426416175..12b322fa34753b9d463762276dc7ec4e9b0c909a 100644 (file)
@@ -19,10 +19,8 @@ static struct test_format {
        { "krava23", "config2:28-29,38\n", },
 };
 
-#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format))
-
 /* Simulated users input. */
-static struct parse_events__term test_terms[] = {
+static struct parse_events_term test_terms[] = {
        {
                .config    = (char *) "krava01",
                .val.num   = 15,
@@ -78,7 +76,6 @@ static struct parse_events__term test_terms[] = {
                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
        },
 };
-#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
 
 /*
  * Prepare format directory data, exported by kernel
@@ -93,7 +90,7 @@ static char *test_format_dir_get(void)
        if (!mkdtemp(dir))
                return NULL;
 
-       for (i = 0; i < TEST_FORMATS_CNT; i++) {
+       for (i = 0; i < ARRAY_SIZE(test_formats); i++) {
                static char name[PATH_MAX];
                struct test_format *format = &test_formats[i];
                FILE *file;
@@ -130,14 +127,12 @@ static struct list_head *test_terms_list(void)
        static LIST_HEAD(terms);
        unsigned int i;
 
-       for (i = 0; i < TERMS_CNT; i++)
+       for (i = 0; i < ARRAY_SIZE(test_terms); i++)
                list_add_tail(&test_terms[i].list, &terms);
 
        return &terms;
 }
 
-#undef TERMS_CNT
-
 int test__pmu(void)
 {
        char *format = test_format_dir_get();
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
new file mode 100644 (file)
index 0000000..7760277
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Just test if we can load the python binding.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "tests.h"
+
+extern int verbose;
+
+int test__python_use(void)
+{
+       char *cmd;
+       int ret;
+
+       if (asprintf(&cmd, "echo \"import sys ; sys.path.append('%s'); import perf\" | %s %s",
+                    PYTHONPATH, PYTHON, verbose ? "" : "2> /dev/null") < 0)
+               return -1;
+
+       ret = system(cmd) ? -1 : 0;
+       free(cmd);
+       return ret;
+}
index fc121edab0168abc7b5ecd8597ddc97c392c3e7a..5de0be1ff4b614112c22e7c65d3a9808596ae9bc 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef TESTS_H
 #define TESTS_H
 
+enum {
+       TEST_OK   =  0,
+       TEST_FAIL = -1,
+       TEST_SKIP = -2,
+};
+
 /* Tests */
 int test__vmlinux_matches_kallsyms(void);
 int test__open_syscall_event(void);
@@ -15,8 +21,7 @@ int test__pmu(void);
 int test__attr(void);
 int test__dso_data(void);
 int test__parse_events(void);
-
-/* Util */
-int trace_event__id(const char *evname);
+int test__hists_link(void);
+int test__python_use(void);
 
 #endif /* TESTS_H */
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
deleted file mode 100644 (file)
index 748f2e8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "tests.h"
-#include "debugfs.h"
-
-int trace_event__id(const char *evname)
-{
-       char *filename;
-       int err = -1, fd;
-
-       if (asprintf(&filename,
-                    "%s/syscalls/%s/id",
-                    tracing_events_path, evname) < 0)
-               return -1;
-
-       fd = open(filename, O_RDONLY);
-       if (fd >= 0) {
-               char id[16];
-               if (read(fd, id, sizeof(id)) > 0)
-                       err = atoi(id);
-               close(fd);
-       }
-
-       free(filename);
-       return err;
-}
index 0d1cdbee2f59ed66a524d5c85fddb62ecdb8dd10..7b4c4d26d1baed24e2c5999d76457616c78c5d91 100644 (file)
@@ -44,7 +44,7 @@ int test__vmlinux_matches_kallsyms(void)
         */
        if (machine__create_kernel_maps(&kallsyms) < 0) {
                pr_debug("machine__create_kernel_maps ");
-               return -1;
+               goto out;
        }
 
        /*
@@ -101,7 +101,8 @@ int test__vmlinux_matches_kallsyms(void)
         */
        if (machine__load_vmlinux_path(&vmlinux, type,
                                       vmlinux_matches_kallsyms_filter) <= 0) {
-               pr_debug("machine__load_vmlinux_path ");
+               pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
+               err = TEST_SKIP;
                goto out;
        }
 
@@ -226,5 +227,7 @@ detour:
                        map__fprintf(pos, stderr);
        }
 out:
+       machine__exit(&kallsyms);
+       machine__exit(&vmlinux);
        return err;
 }
index 4aeb7d5df93933fd8babfafaadd47c755cbb9671..809ea4632a34fc0f90e766eb3cf16175904cbefa 100644 (file)
@@ -273,6 +273,8 @@ void ui_browser__hide(struct ui_browser *browser __maybe_unused)
 {
        pthread_mutex_lock(&ui__lock);
        ui_helpline__pop();
+       free(browser->helpline);
+       browser->helpline = NULL;
        pthread_mutex_unlock(&ui__lock);
 }
 
@@ -471,7 +473,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
        return row;
 }
 
-static struct ui_browser__colorset {
+static struct ui_browser_colorset {
        const char *name, *fg, *bg;
        int colorset;
 } ui_browser__colorsets[] = {
@@ -706,7 +708,7 @@ void ui_browser__init(void)
        perf_config(ui_browser__color_config, NULL);
 
        while (ui_browser__colorsets[i].name) {
-               struct ui_browser__colorset *c = &ui_browser__colorsets[i++];
+               struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
                sltt_set_color(c->colorset, c->name, c->fg, c->bg);
        }
 
index 5dab3ca96980baf107158352b149799636002055..7dca1555c6109bbb8a85611397f984245235de21 100644 (file)
@@ -182,6 +182,16 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
                ab->selection = dl;
 }
 
+static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
+{
+       if (!dl || !dl->ins || !ins__is_jump(dl->ins)
+           || !disasm_line__has_offset(dl)
+           || dl->ops.target.offset >= symbol__size(sym))
+               return false;
+
+       return true;
+}
+
 static void annotate_browser__draw_current_jump(struct ui_browser *browser)
 {
        struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -195,8 +205,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
        if (strstr(sym->name, "@plt"))
                return;
 
-       if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) ||
-           !disasm_line__has_offset(cursor))
+       if (!disasm_line__is_valid_jump(cursor, sym))
                return;
 
        target = ab->offsets[cursor->ops.target.offset];
@@ -788,17 +797,9 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
                struct disasm_line *dl = browser->offsets[offset], *dlt;
                struct browser_disasm_line *bdlt;
 
-               if (!dl || !dl->ins || !ins__is_jump(dl->ins) ||
-                   !disasm_line__has_offset(dl))
+               if (!disasm_line__is_valid_jump(dl, sym))
                        continue;
 
-               if (dl->ops.target.offset >= size) {
-                       ui__error("jump to after symbol!\n"
-                                 "size: %zx, jump target: %" PRIx64,
-                                 size, dl->ops.target.offset);
-                       continue;
-               }
-
                dlt = browser->offsets[dl->ops.target.offset];
                /*
                 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
@@ -921,11 +922,11 @@ out_free_offsets:
 
 #define ANNOTATE_CFG(n) \
        { .name = #n, .value = &annotate_browser__opts.n, }
-       
+
 /*
  * Keep the entries sorted, they are bsearch'ed
  */
-static struct annotate__config {
+static struct annotate_config {
        const char *name;
        bool *value;
 } annotate__configs[] = {
@@ -939,7 +940,7 @@ static struct annotate__config {
 
 static int annotate_config__cmp(const void *name, const void *cfgp)
 {
-       const struct annotate__config *cfg = cfgp;
+       const struct annotate_config *cfg = cfgp;
 
        return strcmp(name, cfg->name);
 }
@@ -947,7 +948,7 @@ static int annotate_config__cmp(const void *name, const void *cfgp)
 static int annotate__config(const char *var, const char *value,
                            void *data __maybe_unused)
 {
-       struct annotate__config *cfg;
+       struct annotate_config *cfg;
        const char *name;
 
        if (prefixcmp(var, "annotate.") != 0)
@@ -955,7 +956,7 @@ static int annotate__config(const char *var, const char *value,
 
        name = var + 9;
        cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
-                     sizeof(struct annotate__config), annotate_config__cmp);
+                     sizeof(struct annotate_config), annotate_config__cmp);
 
        if (cfg == NULL)
                return -1;
index ccc4bd16142094d7a1a0617ae72f141ad0058a1a..aa22704047d684caf07806e4a39d4e43a9f9fe28 100644 (file)
@@ -567,26 +567,128 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
        return row - first_row;
 }
 
-#define HPP__COLOR_FN(_name, _field)                                   \
-static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,     \
-                                            struct hist_entry *he)     \
+struct hpp_arg {
+       struct ui_browser *b;
+       char folded_sign;
+       bool current_entry;
+};
+
+static int __hpp__color_callchain(struct hpp_arg *arg)
+{
+       if (!symbol_conf.use_callchain)
+               return 0;
+
+       slsmg_printf("%c ", arg->folded_sign);
+       return 2;
+}
+
+static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+                           u64 (*get_field)(struct hist_entry *),
+                           int (*callchain_cb)(struct hpp_arg *))
+{
+       int ret = 0;
+       double percent = 0.0;
+       struct hists *hists = he->hists;
+       struct hpp_arg *arg = hpp->ptr;
+
+       if (hists->stats.total_period)
+               percent = 100.0 * get_field(he) / hists->stats.total_period;
+
+       ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
+
+       if (callchain_cb)
+               ret += callchain_cb(arg);
+
+       ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
+       slsmg_printf("%s", hpp->buf);
+
+       if (symbol_conf.event_group) {
+               int prev_idx, idx_delta;
+               struct perf_evsel *evsel = hists_to_evsel(hists);
+               struct hist_entry *pair;
+               int nr_members = evsel->nr_members;
+
+               if (nr_members <= 1)
+                       goto out;
+
+               prev_idx = perf_evsel__group_idx(evsel);
+
+               list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+                       u64 period = get_field(pair);
+                       u64 total = pair->hists->stats.total_period;
+
+                       if (!total)
+                               continue;
+
+                       evsel = hists_to_evsel(pair->hists);
+                       idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
+
+                       while (idx_delta--) {
+                               /*
+                                * zero-fill group members in the middle which
+                                * have no sample
+                                */
+                               ui_browser__set_percent_color(arg->b, 0.0,
+                                                       arg->current_entry);
+                               ret += scnprintf(hpp->buf, hpp->size,
+                                                " %6.2f%%", 0.0);
+                               slsmg_printf("%s", hpp->buf);
+                       }
+
+                       percent = 100.0 * period / total;
+                       ui_browser__set_percent_color(arg->b, percent,
+                                                     arg->current_entry);
+                       ret += scnprintf(hpp->buf, hpp->size,
+                                        " %6.2f%%", percent);
+                       slsmg_printf("%s", hpp->buf);
+
+                       prev_idx = perf_evsel__group_idx(evsel);
+               }
+
+               idx_delta = nr_members - prev_idx - 1;
+
+               while (idx_delta--) {
+                       /*
+                        * zero-fill group members at last which have no sample
+                        */
+                       ui_browser__set_percent_color(arg->b, 0.0,
+                                                     arg->current_entry);
+                       ret += scnprintf(hpp->buf, hpp->size,
+                                        " %6.2f%%", 0.0);
+                       slsmg_printf("%s", hpp->buf);
+               }
+       }
+out:
+       if (!arg->current_entry || !arg->b->navkeypressed)
+               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
+
+       return ret;
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field, _cb)                     \
+static u64 __hpp_get_##_field(struct hist_entry *he)                   \
+{                                                                      \
+       return he->stat._field;                                         \
+}                                                                      \
+                                                                       \
+static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp,       \
+                                          struct hist_entry *he)       \
 {                                                                      \
-       struct hists *hists = he->hists;                                \
-       double percent = 100.0 * he->stat._field / hists->stats.total_period; \
-       *(double *)hpp->ptr = percent;                                  \
-       return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);      \
+       return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb);      \
 }
 
-HPP__COLOR_FN(overhead, period)
-HPP__COLOR_FN(overhead_sys, period_sys)
-HPP__COLOR_FN(overhead_us, period_us)
-HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
-HPP__COLOR_FN(overhead_guest_us, period_guest_us)
+__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__color_callchain)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, NULL)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us, NULL)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, NULL)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL)
 
-#undef HPP__COLOR_FN
+#undef __HPP_COLOR_PERCENT_FN
 
 void hist_browser__init_hpp(void)
 {
+       perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+
        perf_hpp__init();
 
        perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -606,13 +708,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                                    unsigned short row)
 {
        char s[256];
-       double percent;
-       int i, printed = 0;
+       int printed = 0;
        int width = browser->b.width;
        char folded_sign = ' ';
        bool current_entry = ui_browser__is_current_entry(&browser->b, row);
        off_t row_offset = entry->row_offset;
        bool first = true;
+       struct perf_hpp_fmt *fmt;
 
        if (current_entry) {
                browser->he_selection = entry;
@@ -625,41 +727,30 @@ static int hist_browser__show_entry(struct hist_browser *browser,
        }
 
        if (row_offset == 0) {
+               struct hpp_arg arg = {
+                       .b              = &browser->b,
+                       .folded_sign    = folded_sign,
+                       .current_entry  = current_entry,
+               };
                struct perf_hpp hpp = {
                        .buf            = s,
                        .size           = sizeof(s),
+                       .ptr            = &arg,
                };
 
                ui_browser__gotorc(&browser->b, row, 0);
 
-               for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-                       if (!perf_hpp__format[i].cond)
-                               continue;
-
+               perf_hpp__for_each_format(fmt) {
                        if (!first) {
                                slsmg_printf("  ");
                                width -= 2;
                        }
                        first = false;
 
-                       if (perf_hpp__format[i].color) {
-                               hpp.ptr = &percent;
-                               /* It will set percent for us. See HPP__COLOR_FN above. */
-                               width -= perf_hpp__format[i].color(&hpp, entry);
-
-                               ui_browser__set_percent_color(&browser->b, percent, current_entry);
-
-                               if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
-                                       slsmg_printf("%c ", folded_sign);
-                                       width -= 2;
-                               }
-
-                               slsmg_printf("%s", s);
-
-                               if (!current_entry || !browser->b.navkeypressed)
-                                       ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
+                       if (fmt->color) {
+                               width -= fmt->color(&hpp, entry);
                        } else {
-                               width -= perf_hpp__format[i].entry(&hpp, entry);
+                               width -= fmt->entry(&hpp, entry);
                                slsmg_printf("%s", s);
                        }
                }
@@ -1098,6 +1189,21 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
        const struct thread *thread = hists->thread_filter;
        unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
        u64 nr_events = hists->stats.total_period;
+       struct perf_evsel *evsel = hists_to_evsel(hists);
+       char buf[512];
+       size_t buflen = sizeof(buf);
+
+       if (symbol_conf.event_group && evsel->nr_members > 1) {
+               struct perf_evsel *pos;
+
+               perf_evsel__group_desc(evsel, buf, buflen);
+               ev_name = buf;
+
+               for_each_group_member(pos, evsel) {
+                       nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+                       nr_events += pos->hists.stats.total_period;
+               }
+       }
 
        nr_samples = convert_unit(nr_samples, &unit);
        printed = scnprintf(bf, size,
@@ -1135,6 +1241,96 @@ static inline bool is_report_browser(void *timer)
        return timer == NULL;
 }
 
+/*
+ * Only runtime switching of perf data file will make "input_name" point
+ * to a malloced buffer. So add "is_input_name_malloced" flag to decide
+ * whether we need to call free() for current "input_name" during the switch.
+ */
+static bool is_input_name_malloced = false;
+
+static int switch_data_file(void)
+{
+       char *pwd, *options[32], *abs_path[32], *tmp;
+       DIR *pwd_dir;
+       int nr_options = 0, choice = -1, ret = -1;
+       struct dirent *dent;
+
+       pwd = getenv("PWD");
+       if (!pwd)
+               return ret;
+
+       pwd_dir = opendir(pwd);
+       if (!pwd_dir)
+               return ret;
+
+       memset(options, 0, sizeof(options));
+       memset(options, 0, sizeof(abs_path));
+
+       while ((dent = readdir(pwd_dir))) {
+               char path[PATH_MAX];
+               u64 magic;
+               char *name = dent->d_name;
+               FILE *file;
+
+               if (!(dent->d_type == DT_REG))
+                       continue;
+
+               snprintf(path, sizeof(path), "%s/%s", pwd, name);
+
+               file = fopen(path, "r");
+               if (!file)
+                       continue;
+
+               if (fread(&magic, 1, 8, file) < 8)
+                       goto close_file_and_continue;
+
+               if (is_perf_magic(magic)) {
+                       options[nr_options] = strdup(name);
+                       if (!options[nr_options])
+                               goto close_file_and_continue;
+
+                       abs_path[nr_options] = strdup(path);
+                       if (!abs_path[nr_options]) {
+                               free(options[nr_options]);
+                               ui__warning("Can't search all data files due to memory shortage.\n");
+                               fclose(file);
+                               break;
+                       }
+
+                       nr_options++;
+               }
+
+close_file_and_continue:
+               fclose(file);
+               if (nr_options >= 32) {
+                       ui__warning("Too many perf data files in PWD!\n"
+                                   "Only the first 32 files will be listed.\n");
+                       break;
+               }
+       }
+       closedir(pwd_dir);
+
+       if (nr_options) {
+               choice = ui__popup_menu(nr_options, options);
+               if (choice < nr_options && choice >= 0) {
+                       tmp = strdup(abs_path[choice]);
+                       if (tmp) {
+                               if (is_input_name_malloced)
+                                       free((void *)input_name);
+                               input_name = tmp;
+                               is_input_name_malloced = true;
+                               ret = 0;
+                       } else
+                               ui__warning("Data switch failed due to memory shortage!\n");
+               }
+       }
+
+       free_popup_options(options, nr_options);
+       free_popup_options(abs_path, nr_options);
+       return ret;
+}
+
+
 static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                    const char *helpline, const char *ev_name,
                                    bool left_exits,
@@ -1169,7 +1365,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                int choice = 0,
                    annotate = -2, zoom_dso = -2, zoom_thread = -2,
                    annotate_f = -2, annotate_t = -2, browse_map = -2;
-               int scripts_comm = -2, scripts_symbol = -2, scripts_all = -2;
+               int scripts_comm = -2, scripts_symbol = -2,
+                   scripts_all = -2, switch_data = -2;
 
                nr_options = 0;
 
@@ -1226,6 +1423,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        if (is_report_browser(hbt))
                                goto do_scripts;
                        continue;
+               case 's':
+                       if (is_report_browser(hbt))
+                               goto do_data_switch;
+                       continue;
                case K_F1:
                case 'h':
                case '?':
@@ -1245,6 +1446,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                        "d             Zoom into current DSO\n"
                                        "t             Zoom into current Thread\n"
                                        "r             Run available scripts('perf report' only)\n"
+                                       "s             Switch to another data file in PWD ('perf report' only)\n"
                                        "P             Print histograms to perf.hist.N\n"
                                        "V             Verbose (DSO names in callchains, etc)\n"
                                        "/             Filter symbol by name");
@@ -1352,6 +1554,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                if (asprintf(&options[nr_options], "Run scripts for all samples") > 0)
                        scripts_all = nr_options++;
 
+               if (is_report_browser(hbt) && asprintf(&options[nr_options],
+                               "Switch to another data file in PWD") > 0)
+                       switch_data = nr_options++;
 add_exit_option:
                options[nr_options++] = (char *)"Exit";
 retry_popup_menu:
@@ -1462,6 +1667,16 @@ do_scripts:
 
                        script_browse(script_opt);
                }
+               /* Switch to another data file */
+               else if (choice == switch_data) {
+do_data_switch:
+                       if (!switch_data_file()) {
+                               key = K_SWITCH_INPUT_DATA;
+                               break;
+                       } else
+                               ui__warning("Won't switch the data files due to\n"
+                                       "no valid data file get selected!\n");
+               }
        }
 out_free_stack:
        pstack__delete(fstack);
@@ -1494,6 +1709,16 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
        ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
                                                       HE_COLORSET_NORMAL);
 
+       if (symbol_conf.event_group && evsel->nr_members > 1) {
+               struct perf_evsel *pos;
+
+               ev_name = perf_evsel__group_name(evsel);
+
+               for_each_group_member(pos, evsel) {
+                       nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+               }
+       }
+
        nr_events = convert_unit(nr_events, &unit);
        printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
                           unit, unit == ' ' ? "" : " ", ev_name);
@@ -1578,6 +1803,7 @@ browse_hists:
                                                "Do you really want to exit?"))
                                        continue;
                                /* Fall thru */
+                       case K_SWITCH_INPUT_DATA:
                        case 'q':
                        case CTRL('c'):
                                goto out;
@@ -1604,8 +1830,19 @@ out:
        return key;
 }
 
+static bool filter_group_entries(struct ui_browser *self __maybe_unused,
+                                void *entry)
+{
+       struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+
+       if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
+               return true;
+
+       return false;
+}
+
 static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
-                                          const char *help,
+                                          int nr_entries, const char *help,
                                           struct hist_browser_timer *hbt,
                                           struct perf_session_env *env)
 {
@@ -1616,7 +1853,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
                        .refresh    = ui_browser__list_head_refresh,
                        .seek       = ui_browser__list_head_seek,
                        .write      = perf_evsel_menu__write,
-                       .nr_entries = evlist->nr_entries,
+                       .filter     = filter_group_entries,
+                       .nr_entries = nr_entries,
                        .priv       = evlist,
                },
                .env = env,
@@ -1632,20 +1870,37 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
                        menu.b.width = line_len;
        }
 
-       return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt);
+       return perf_evsel_menu__run(&menu, nr_entries, help, hbt);
 }
 
 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
                                  struct hist_browser_timer *hbt,
                                  struct perf_session_env *env)
 {
-       if (evlist->nr_entries == 1) {
+       int nr_entries = evlist->nr_entries;
+
+single_entry:
+       if (nr_entries == 1) {
                struct perf_evsel *first = list_entry(evlist->entries.next,
                                                      struct perf_evsel, node);
                const char *ev_name = perf_evsel__name(first);
-               return perf_evsel__hists_browse(first, evlist->nr_entries, help,
+
+               return perf_evsel__hists_browse(first, nr_entries, help,
                                                ev_name, false, hbt, env);
        }
 
-       return __perf_evlist__tui_browse_hists(evlist, help, hbt, env);
+       if (symbol_conf.event_group) {
+               struct perf_evsel *pos;
+
+               nr_entries = 0;
+               list_for_each_entry(pos, &evlist->entries, node)
+                       if (perf_evsel__is_group_leader(pos))
+                               nr_entries++;
+
+               if (nr_entries == 1)
+                       goto single_entry;
+       }
+
+       return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
+                                              hbt, env);
 }
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
new file mode 100644 (file)
index 0000000..7d8dc58
--- /dev/null
@@ -0,0 +1,229 @@
+#include "gtk.h"
+#include "util/debug.h"
+#include "util/annotate.h"
+#include "ui/helpline.h"
+
+
+enum {
+       ANN_COL__PERCENT,
+       ANN_COL__OFFSET,
+       ANN_COL__LINE,
+
+       MAX_ANN_COLS
+};
+
+static const char *const col_names[] = {
+       "Overhead",
+       "Offset",
+       "Line"
+};
+
+static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
+                                struct disasm_line *dl, int evidx)
+{
+       struct sym_hist *symhist;
+       double percent = 0.0;
+       const char *markup;
+       int ret = 0;
+
+       strcpy(buf, "");
+
+       if (dl->offset == (s64) -1)
+               return 0;
+
+       symhist = annotation__histogram(symbol__annotation(sym), evidx);
+       if (!symhist->addr[dl->offset])
+               return 0;
+
+       percent = 100.0 * symhist->addr[dl->offset] / symhist->sum;
+
+       markup = perf_gtk__get_percent_color(percent);
+       if (markup)
+               ret += scnprintf(buf, size, "%s", markup);
+       ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent);
+       if (markup)
+               ret += scnprintf(buf + ret, size - ret, "</span>");
+
+       return ret;
+}
+
+static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym,
+                               struct map *map, struct disasm_line *dl)
+{
+       u64 start = map__rip_2objdump(map, sym->start);
+
+       strcpy(buf, "");
+
+       if (dl->offset == (s64) -1)
+               return 0;
+
+       return scnprintf(buf, size, "%"PRIx64, start + dl->offset);
+}
+
+static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
+{
+       int ret = 0;
+       char *line = g_markup_escape_text(dl->line, -1);
+       const char *markup = "<span fgcolor='gray'>";
+
+       strcpy(buf, "");
+
+       if (!line)
+               return 0;
+
+       if (dl->offset != (s64) -1)
+               markup = NULL;
+
+       if (markup)
+               ret += scnprintf(buf, size, "%s", markup);
+       ret += scnprintf(buf + ret, size - ret, "%s", line);
+       if (markup)
+               ret += scnprintf(buf + ret, size - ret, "</span>");
+
+       g_free(line);
+       return ret;
+}
+
+static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
+                               struct map *map, int evidx,
+                               struct hist_browser_timer *hbt __maybe_unused)
+{
+       struct disasm_line *pos, *n;
+       struct annotation *notes;
+       GType col_types[MAX_ANN_COLS];
+       GtkCellRenderer *renderer;
+       GtkListStore *store;
+       GtkWidget *view;
+       int i;
+       char s[512];
+
+       notes = symbol__annotation(sym);
+
+       for (i = 0; i < MAX_ANN_COLS; i++) {
+               col_types[i] = G_TYPE_STRING;
+       }
+       store = gtk_list_store_newv(MAX_ANN_COLS, col_types);
+
+       view = gtk_tree_view_new();
+       renderer = gtk_cell_renderer_text_new();
+
+       for (i = 0; i < MAX_ANN_COLS; i++) {
+               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+                                       -1, col_names[i], renderer, "markup",
+                                       i, NULL);
+       }
+
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
+       g_object_unref(GTK_TREE_MODEL(store));
+
+       list_for_each_entry(pos, &notes->src->source, node) {
+               GtkTreeIter iter;
+
+               gtk_list_store_append(store, &iter);
+
+               if (perf_gtk__get_percent(s, sizeof(s), sym, pos, evidx))
+                       gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1);
+               if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos))
+                       gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1);
+               if (perf_gtk__get_line(s, sizeof(s), pos))
+                       gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1);
+       }
+
+       gtk_container_add(GTK_CONTAINER(window), view);
+
+       list_for_each_entry_safe(pos, n, &notes->src->source, node) {
+               list_del(&pos->node);
+               disasm_line__free(pos);
+       }
+
+       return 0;
+}
+
+int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx,
+                        struct hist_browser_timer *hbt)
+{
+       GtkWidget *window;
+       GtkWidget *notebook;
+       GtkWidget *scrolled_window;
+       GtkWidget *tab_label;
+
+       if (map->dso->annotate_warned)
+               return -1;
+
+       if (symbol__annotate(sym, map, 0) < 0) {
+               ui__error("%s", ui_helpline__current);
+               return -1;
+       }
+
+       if (perf_gtk__is_active_context(pgctx)) {
+               window = pgctx->main_window;
+               notebook = pgctx->notebook;
+       } else {
+               GtkWidget *vbox;
+               GtkWidget *infobar;
+               GtkWidget *statbar;
+
+               signal(SIGSEGV, perf_gtk__signal);
+               signal(SIGFPE,  perf_gtk__signal);
+               signal(SIGINT,  perf_gtk__signal);
+               signal(SIGQUIT, perf_gtk__signal);
+               signal(SIGTERM, perf_gtk__signal);
+
+               window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+               gtk_window_set_title(GTK_WINDOW(window), "perf annotate");
+
+               g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
+
+               pgctx = perf_gtk__activate_context(window);
+               if (!pgctx)
+                       return -1;
+
+               vbox = gtk_vbox_new(FALSE, 0);
+               notebook = gtk_notebook_new();
+               pgctx->notebook = notebook;
+
+               gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
+
+               infobar = perf_gtk__setup_info_bar();
+               if (infobar) {
+                       gtk_box_pack_start(GTK_BOX(vbox), infobar,
+                                          FALSE, FALSE, 0);
+               }
+
+               statbar = perf_gtk__setup_statusbar();
+               gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
+
+               gtk_container_add(GTK_CONTAINER(window), vbox);
+       }
+
+       scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+       tab_label = gtk_label_new(sym->name);
+
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+                                      GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window,
+                                tab_label);
+
+       perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt);
+       return 0;
+}
+
+void perf_gtk__show_annotations(void)
+{
+       GtkWidget *window;
+
+       if (!perf_gtk__is_active_context(pgctx))
+               return;
+
+       window = pgctx->main_window;
+       gtk_widget_show_all(window);
+
+       perf_gtk__resize_window(window);
+       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+
+       gtk_main();
+
+       perf_gtk__deactivate_context(&pgctx);
+}
index 253b6219a39efbdd119f358571c22f5a83a7aef8..c95012cdb4387f95a4125f7da3f58cf224f33dc8 100644 (file)
@@ -8,15 +8,13 @@
 
 #include <signal.h>
 
-#define MAX_COLUMNS                    32
-
-static void perf_gtk__signal(int sig)
+void perf_gtk__signal(int sig)
 {
        perf_gtk__exit(false);
        psignal(sig, "perf");
 }
 
-static void perf_gtk__resize_window(GtkWidget *window)
+void perf_gtk__resize_window(GtkWidget *window)
 {
        GdkRectangle rect;
        GdkScreen *screen;
@@ -36,7 +34,7 @@ static void perf_gtk__resize_window(GtkWidget *window)
        gtk_window_resize(GTK_WINDOW(window), width, height);
 }
 
-static const char *perf_gtk__get_percent_color(double percent)
+const char *perf_gtk__get_percent_color(double percent)
 {
        if (percent >= MIN_RED)
                return "<span fgcolor='red'>";
@@ -45,155 +43,8 @@ static const char *perf_gtk__get_percent_color(double percent)
        return NULL;
 }
 
-#define HPP__COLOR_FN(_name, _field)                                           \
-static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,                 \
-                                        struct hist_entry *he)                 \
-{                                                                              \
-       struct hists *hists = he->hists;                                        \
-       double percent = 100.0 * he->stat._field / hists->stats.total_period;   \
-       const char *markup;                                                     \
-       int ret = 0;                                                            \
-                                                                               \
-       markup = perf_gtk__get_percent_color(percent);                          \
-       if (markup)                                                             \
-               ret += scnprintf(hpp->buf, hpp->size, "%s", markup);            \
-       ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent);  \
-       if (markup)                                                             \
-               ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>");   \
-                                                                               \
-       return ret;                                                             \
-}
-
-HPP__COLOR_FN(overhead, period)
-HPP__COLOR_FN(overhead_sys, period_sys)
-HPP__COLOR_FN(overhead_us, period_us)
-HPP__COLOR_FN(overhead_guest_sys, period_guest_sys)
-HPP__COLOR_FN(overhead_guest_us, period_guest_us)
-
-#undef HPP__COLOR_FN
-
-void perf_gtk__init_hpp(void)
-{
-       perf_hpp__init();
-
-       perf_hpp__format[PERF_HPP__OVERHEAD].color =
-                               perf_gtk__hpp_color_overhead;
-       perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
-                               perf_gtk__hpp_color_overhead_sys;
-       perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
-                               perf_gtk__hpp_color_overhead_us;
-       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
-                               perf_gtk__hpp_color_overhead_guest_sys;
-       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
-                               perf_gtk__hpp_color_overhead_guest_us;
-}
-
-static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
-{
-       GType col_types[MAX_COLUMNS];
-       GtkCellRenderer *renderer;
-       struct sort_entry *se;
-       GtkListStore *store;
-       struct rb_node *nd;
-       GtkWidget *view;
-       int i, col_idx;
-       int nr_cols;
-       char s[512];
-
-       struct perf_hpp hpp = {
-               .buf            = s,
-               .size           = sizeof(s),
-       };
-
-       nr_cols = 0;
-
-       for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-               if (!perf_hpp__format[i].cond)
-                       continue;
-
-               col_types[nr_cols++] = G_TYPE_STRING;
-       }
-
-       list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (se->elide)
-                       continue;
-
-               col_types[nr_cols++] = G_TYPE_STRING;
-       }
-
-       store = gtk_list_store_newv(nr_cols, col_types);
-
-       view = gtk_tree_view_new();
-
-       renderer = gtk_cell_renderer_text_new();
-
-       col_idx = 0;
-
-       for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-               if (!perf_hpp__format[i].cond)
-                       continue;
-
-               perf_hpp__format[i].header(&hpp);
-
-               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-                                                           -1, s,
-                                                           renderer, "markup",
-                                                           col_idx++, NULL);
-       }
-
-       list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (se->elide)
-                       continue;
-
-               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-                                                           -1, se->se_header,
-                                                           renderer, "text",
-                                                           col_idx++, NULL);
-       }
-
-       gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
-
-       g_object_unref(GTK_TREE_MODEL(store));
-
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
-               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-               GtkTreeIter iter;
-
-               if (h->filtered)
-                       continue;
-
-               gtk_list_store_append(store, &iter);
-
-               col_idx = 0;
-
-               for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-                       if (!perf_hpp__format[i].cond)
-                               continue;
-
-                       if (perf_hpp__format[i].color)
-                               perf_hpp__format[i].color(&hpp, h);
-                       else
-                               perf_hpp__format[i].entry(&hpp, h);
-
-                       gtk_list_store_set(store, &iter, col_idx++, s, -1);
-               }
-
-               list_for_each_entry(se, &hist_entry__sort_list, list) {
-                       if (se->elide)
-                               continue;
-
-                       se->se_snprintf(h, s, ARRAY_SIZE(s),
-                                       hists__col_len(hists, se->se_width_idx));
-
-                       gtk_list_store_set(store, &iter, col_idx++, s, -1);
-               }
-       }
-
-       gtk_container_add(GTK_CONTAINER(window), view);
-}
-
 #ifdef HAVE_GTK_INFO_BAR
-static GtkWidget *perf_gtk__setup_info_bar(void)
+GtkWidget *perf_gtk__setup_info_bar(void)
 {
        GtkWidget *info_bar;
        GtkWidget *label;
@@ -220,7 +71,7 @@ static GtkWidget *perf_gtk__setup_info_bar(void)
 }
 #endif
 
-static GtkWidget *perf_gtk__setup_statusbar(void)
+GtkWidget *perf_gtk__setup_statusbar(void)
 {
        GtkWidget *stbar;
        unsigned ctxid;
@@ -234,79 +85,3 @@ static GtkWidget *perf_gtk__setup_statusbar(void)
 
        return stbar;
 }
-
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
-                                 const char *help,
-                                 struct hist_browser_timer *hbt __maybe_unused)
-{
-       struct perf_evsel *pos;
-       GtkWidget *vbox;
-       GtkWidget *notebook;
-       GtkWidget *info_bar;
-       GtkWidget *statbar;
-       GtkWidget *window;
-
-       signal(SIGSEGV, perf_gtk__signal);
-       signal(SIGFPE,  perf_gtk__signal);
-       signal(SIGINT,  perf_gtk__signal);
-       signal(SIGQUIT, perf_gtk__signal);
-       signal(SIGTERM, perf_gtk__signal);
-
-       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
-       gtk_window_set_title(GTK_WINDOW(window), "perf report");
-
-       g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
-
-       pgctx = perf_gtk__activate_context(window);
-       if (!pgctx)
-               return -1;
-
-       vbox = gtk_vbox_new(FALSE, 0);
-
-       notebook = gtk_notebook_new();
-
-       list_for_each_entry(pos, &evlist->entries, node) {
-               struct hists *hists = &pos->hists;
-               const char *evname = perf_evsel__name(pos);
-               GtkWidget *scrolled_window;
-               GtkWidget *tab_label;
-
-               scrolled_window = gtk_scrolled_window_new(NULL, NULL);
-
-               gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
-                                                       GTK_POLICY_AUTOMATIC,
-                                                       GTK_POLICY_AUTOMATIC);
-
-               perf_gtk__show_hists(scrolled_window, hists);
-
-               tab_label = gtk_label_new(evname);
-
-               gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
-       }
-
-       gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
-
-       info_bar = perf_gtk__setup_info_bar();
-       if (info_bar)
-               gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
-
-       statbar = perf_gtk__setup_statusbar();
-       gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
-
-       gtk_container_add(GTK_CONTAINER(window), vbox);
-
-       gtk_widget_show_all(window);
-
-       perf_gtk__resize_window(window);
-
-       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
-
-       ui_helpline__push(help);
-
-       gtk_main();
-
-       perf_gtk__deactivate_context(&pgctx);
-
-       return 0;
-}
index 856320e2cc05c796a5774de845f24fda78dcef3e..3d96785ef155044d006f4438bf35b17ee3717148 100644 (file)
@@ -10,6 +10,7 @@
 
 struct perf_gtk_context {
        GtkWidget *main_window;
+       GtkWidget *notebook;
 
 #ifdef HAVE_GTK_INFO_BAR
        GtkWidget *info_bar;
@@ -33,7 +34,14 @@ void perf_gtk__init_helpline(void);
 void perf_gtk__init_progress(void);
 void perf_gtk__init_hpp(void);
 
-#ifndef HAVE_GTK_INFO_BAR
+void perf_gtk__signal(int sig);
+void perf_gtk__resize_window(GtkWidget *window);
+const char *perf_gtk__get_percent_color(double percent);
+GtkWidget *perf_gtk__setup_statusbar(void);
+
+#ifdef HAVE_GTK_INFO_BAR
+GtkWidget *perf_gtk__setup_info_bar(void);
+#else
 static inline GtkWidget *perf_gtk__setup_info_bar(void)
 {
        return NULL;
index 5db4432ff12a0d3c538da300ae66a98c9622dfd8..3388cbd12186ac5848562e0de10faa7afa025982 100644 (file)
@@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg)
                           pgctx->statbar_ctx_id, msg);
 }
 
-static struct ui_helpline gtk_helpline_fns = {
-       .pop    = gtk_helpline_pop,
-       .push   = gtk_helpline_push,
-};
-
-void perf_gtk__init_helpline(void)
-{
-       helpline_fns = &gtk_helpline_fns;
-}
-
-int perf_gtk__show_helpline(const char *fmt, va_list ap)
+static int gtk_helpline_show(const char *fmt, va_list ap)
 {
        int ret;
        char *ptr;
@@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap)
 
        return ret;
 }
+
+static struct ui_helpline gtk_helpline_fns = {
+       .pop    = gtk_helpline_pop,
+       .push   = gtk_helpline_push,
+       .show   = gtk_helpline_show,
+};
+
+void perf_gtk__init_helpline(void)
+{
+       helpline_fns = &gtk_helpline_fns;
+}
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
new file mode 100644 (file)
index 0000000..1e764a8
--- /dev/null
@@ -0,0 +1,312 @@
+#include "../evlist.h"
+#include "../cache.h"
+#include "../evsel.h"
+#include "../sort.h"
+#include "../hist.h"
+#include "../helpline.h"
+#include "gtk.h"
+
+#define MAX_COLUMNS                    32
+
+static int __percent_color_snprintf(char *buf, size_t size, double percent)
+{
+       int ret = 0;
+       const char *markup;
+
+       markup = perf_gtk__get_percent_color(percent);
+       if (markup)
+               ret += scnprintf(buf, size, markup);
+
+       ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent);
+
+       if (markup)
+               ret += scnprintf(buf + ret, size - ret, "</span>");
+
+       return ret;
+}
+
+
+static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
+                           u64 (*get_field)(struct hist_entry *))
+{
+       int ret;
+       double percent = 0.0;
+       struct hists *hists = he->hists;
+
+       if (hists->stats.total_period)
+               percent = 100.0 * get_field(he) / hists->stats.total_period;
+
+       ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);
+
+       if (symbol_conf.event_group) {
+               int prev_idx, idx_delta;
+               struct perf_evsel *evsel = hists_to_evsel(hists);
+               struct hist_entry *pair;
+               int nr_members = evsel->nr_members;
+
+               if (nr_members <= 1)
+                       return ret;
+
+               prev_idx = perf_evsel__group_idx(evsel);
+
+               list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+                       u64 period = get_field(pair);
+                       u64 total = pair->hists->stats.total_period;
+
+                       evsel = hists_to_evsel(pair->hists);
+                       idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
+
+                       while (idx_delta--) {
+                               /*
+                                * zero-fill group members in the middle which
+                                * have no sample
+                                */
+                               ret += __percent_color_snprintf(hpp->buf + ret,
+                                                               hpp->size - ret,
+                                                               0.0);
+                       }
+
+                       percent = 100.0 * period / total;
+                       ret += __percent_color_snprintf(hpp->buf + ret,
+                                                       hpp->size - ret,
+                                                       percent);
+
+                       prev_idx = perf_evsel__group_idx(evsel);
+               }
+
+               idx_delta = nr_members - prev_idx - 1;
+
+               while (idx_delta--) {
+                       /*
+                        * zero-fill group members at last which have no sample
+                        */
+                       ret += __percent_color_snprintf(hpp->buf + ret,
+                                                       hpp->size - ret,
+                                                       0.0);
+               }
+       }
+       return ret;
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field)                                  \
+static u64 he_get_##_field(struct hist_entry *he)                              \
+{                                                                              \
+       return he->stat._field;                                                 \
+}                                                                              \
+                                                                               \
+static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,                   \
+                                      struct hist_entry *he)                   \
+{                                                                              \
+       return __hpp__color_fmt(hpp, he, he_get_##_field);                      \
+}
+
+__HPP_COLOR_PERCENT_FN(overhead, period)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
+
+#undef __HPP_COLOR_PERCENT_FN
+
+
+void perf_gtk__init_hpp(void)
+{
+       perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+
+       perf_hpp__init();
+
+       perf_hpp__format[PERF_HPP__OVERHEAD].color =
+                               perf_gtk__hpp_color_overhead;
+       perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
+                               perf_gtk__hpp_color_overhead_sys;
+       perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
+                               perf_gtk__hpp_color_overhead_us;
+       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
+                               perf_gtk__hpp_color_overhead_guest_sys;
+       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
+                               perf_gtk__hpp_color_overhead_guest_us;
+}
+
+static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
+{
+       struct perf_hpp_fmt *fmt;
+       GType col_types[MAX_COLUMNS];
+       GtkCellRenderer *renderer;
+       struct sort_entry *se;
+       GtkListStore *store;
+       struct rb_node *nd;
+       GtkWidget *view;
+       int col_idx;
+       int nr_cols;
+       char s[512];
+
+       struct perf_hpp hpp = {
+               .buf            = s,
+               .size           = sizeof(s),
+               .ptr            = hists_to_evsel(hists),
+       };
+
+       nr_cols = 0;
+
+       perf_hpp__for_each_format(fmt)
+               col_types[nr_cols++] = G_TYPE_STRING;
+
+       list_for_each_entry(se, &hist_entry__sort_list, list) {
+               if (se->elide)
+                       continue;
+
+               col_types[nr_cols++] = G_TYPE_STRING;
+       }
+
+       store = gtk_list_store_newv(nr_cols, col_types);
+
+       view = gtk_tree_view_new();
+
+       renderer = gtk_cell_renderer_text_new();
+
+       col_idx = 0;
+
+       perf_hpp__for_each_format(fmt) {
+               fmt->header(&hpp);
+
+               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+                                                           -1, ltrim(s),
+                                                           renderer, "markup",
+                                                           col_idx++, NULL);
+       }
+
+       list_for_each_entry(se, &hist_entry__sort_list, list) {
+               if (se->elide)
+                       continue;
+
+               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+                                                           -1, se->se_header,
+                                                           renderer, "text",
+                                                           col_idx++, NULL);
+       }
+
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
+
+       g_object_unref(GTK_TREE_MODEL(store));
+
+       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+               GtkTreeIter iter;
+
+               if (h->filtered)
+                       continue;
+
+               gtk_list_store_append(store, &iter);
+
+               col_idx = 0;
+
+               perf_hpp__for_each_format(fmt) {
+                       if (fmt->color)
+                               fmt->color(&hpp, h);
+                       else
+                               fmt->entry(&hpp, h);
+
+                       gtk_list_store_set(store, &iter, col_idx++, s, -1);
+               }
+
+               list_for_each_entry(se, &hist_entry__sort_list, list) {
+                       if (se->elide)
+                               continue;
+
+                       se->se_snprintf(h, s, ARRAY_SIZE(s),
+                                       hists__col_len(hists, se->se_width_idx));
+
+                       gtk_list_store_set(store, &iter, col_idx++, s, -1);
+               }
+       }
+
+       gtk_container_add(GTK_CONTAINER(window), view);
+}
+
+int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
+                                 const char *help,
+                                 struct hist_browser_timer *hbt __maybe_unused)
+{
+       struct perf_evsel *pos;
+       GtkWidget *vbox;
+       GtkWidget *notebook;
+       GtkWidget *info_bar;
+       GtkWidget *statbar;
+       GtkWidget *window;
+
+       signal(SIGSEGV, perf_gtk__signal);
+       signal(SIGFPE,  perf_gtk__signal);
+       signal(SIGINT,  perf_gtk__signal);
+       signal(SIGQUIT, perf_gtk__signal);
+       signal(SIGTERM, perf_gtk__signal);
+
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+       gtk_window_set_title(GTK_WINDOW(window), "perf report");
+
+       g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
+
+       pgctx = perf_gtk__activate_context(window);
+       if (!pgctx)
+               return -1;
+
+       vbox = gtk_vbox_new(FALSE, 0);
+
+       notebook = gtk_notebook_new();
+
+       gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
+
+       info_bar = perf_gtk__setup_info_bar();
+       if (info_bar)
+               gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
+
+       statbar = perf_gtk__setup_statusbar();
+       gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
+
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+
+       list_for_each_entry(pos, &evlist->entries, node) {
+               struct hists *hists = &pos->hists;
+               const char *evname = perf_evsel__name(pos);
+               GtkWidget *scrolled_window;
+               GtkWidget *tab_label;
+               char buf[512];
+               size_t size = sizeof(buf);
+
+               if (symbol_conf.event_group) {
+                       if (!perf_evsel__is_group_leader(pos))
+                               continue;
+
+                       if (pos->nr_members > 1) {
+                               perf_evsel__group_desc(pos, buf, size);
+                               evname = buf;
+                       }
+               }
+
+               scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+
+               gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+                                                       GTK_POLICY_AUTOMATIC,
+                                                       GTK_POLICY_AUTOMATIC);
+
+               perf_gtk__show_hists(scrolled_window, hists);
+
+               tab_label = gtk_label_new(evname);
+
+               gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
+       }
+
+       gtk_widget_show_all(window);
+
+       perf_gtk__resize_window(window);
+
+       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+
+       ui_helpline__push(help);
+
+       gtk_main();
+
+       perf_gtk__deactivate_context(&pgctx);
+
+       return 0;
+}
index a49bcf3c190b4066305cdf5af889087365d43608..700fb3cfa1c739128bc0c8009039f48e1f964c93 100644 (file)
@@ -16,9 +16,16 @@ static void nop_helpline__push(const char *msg __maybe_unused)
 {
 }
 
+static int nop_helpline__show(const char *fmt __maybe_unused,
+                              va_list ap __maybe_unused)
+{
+       return 0;
+}
+
 static struct ui_helpline default_helpline_fns = {
        .pop    = nop_helpline__pop,
        .push   = nop_helpline__push,
+       .show   = nop_helpline__show,
 };
 
 struct ui_helpline *helpline_fns = &default_helpline_fns;
@@ -59,3 +66,8 @@ void ui_helpline__puts(const char *msg)
        ui_helpline__pop();
        ui_helpline__push(msg);
 }
+
+int ui_helpline__vshow(const char *fmt, va_list ap)
+{
+       return helpline_fns->show(fmt, ap);
+}
index baa28a4d16b94dedafb02cf1f86fe821605fdf1d..46181f4fc07ebf2133e97898bd21acf5fe9c7551 100644 (file)
@@ -9,6 +9,7 @@
 struct ui_helpline {
        void (*pop)(void);
        void (*push)(const char *msg);
+       int  (*show)(const char *fmt, va_list ap);
 };
 
 extern struct ui_helpline *helpline_fns;
@@ -20,28 +21,9 @@ void ui_helpline__push(const char *msg);
 void ui_helpline__vpush(const char *fmt, va_list ap);
 void ui_helpline__fpush(const char *fmt, ...);
 void ui_helpline__puts(const char *msg);
+int  ui_helpline__vshow(const char *fmt, va_list ap);
 
 extern char ui_helpline__current[512];
-
-#ifdef NEWT_SUPPORT
 extern char ui_helpline__last_msg[];
-int ui_helpline__show_help(const char *format, va_list ap);
-#else
-static inline int ui_helpline__show_help(const char *format __maybe_unused,
-                                        va_list ap __maybe_unused)
-{
-       return 0;
-}
-#endif /* NEWT_SUPPORT */
-
-#ifdef GTK2_SUPPORT
-int perf_gtk__show_helpline(const char *format, va_list ap);
-#else
-static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
-                                         va_list ap __maybe_unused)
-{
-       return 0;
-}
-#endif /* GTK2_SUPPORT */
 
 #endif /* _PERF_UI_HELPLINE_H_ */
index aa84130024d58b3956bce290e09fa3eb4e982c2f..d671e63aa351ce4f5ccbf864fe72db80b5d2ffd6 100644 (file)
 #include "../util/hist.h"
 #include "../util/util.h"
 #include "../util/sort.h"
-
+#include "../util/evsel.h"
 
 /* hist period print (hpp) functions */
-static int hpp__header_overhead(struct perf_hpp *hpp)
-{
-       return scnprintf(hpp->buf, hpp->size, "Overhead");
-}
-
-static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
-{
-       return 8;
-}
-
-static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period / hists->stats.total_period;
 
-       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
-}
+typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...);
 
-static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
+static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
+                     u64 (*get_field)(struct hist_entry *),
+                     const char *fmt, hpp_snprint_fn print_fn,
+                     bool fmt_percent)
 {
+       int ret;
        struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period / hists->stats.total_period;
-       const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
 
-static int hpp__header_overhead_sys(struct perf_hpp *hpp)
-{
-       const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, "sys");
-}
+       if (fmt_percent) {
+               double percent = 0.0;
 
-static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
-{
-       return 7;
-}
+               if (hists->stats.total_period)
+                       percent = 100.0 * get_field(he) /
+                                 hists->stats.total_period;
 
-static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
+               ret = print_fn(hpp->buf, hpp->size, fmt, percent);
+       } else
+               ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he));
 
-       return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
-}
+       if (symbol_conf.event_group) {
+               int prev_idx, idx_delta;
+               struct perf_evsel *evsel = hists_to_evsel(hists);
+               struct hist_entry *pair;
+               int nr_members = evsel->nr_members;
 
-static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
-       const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
+               if (nr_members <= 1)
+                       return ret;
 
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
+               prev_idx = perf_evsel__group_idx(evsel);
 
-static int hpp__header_overhead_us(struct perf_hpp *hpp)
-{
-       const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
+               list_for_each_entry(pair, &he->pairs.head, pairs.node) {
+                       u64 period = get_field(pair);
+                       u64 total = pair->hists->stats.total_period;
 
-       return scnprintf(hpp->buf, hpp->size, fmt, "user");
-}
+                       if (!total)
+                               continue;
 
-static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
-{
-       return 7;
-}
+                       evsel = hists_to_evsel(pair->hists);
+                       idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
 
-static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
+                       while (idx_delta--) {
+                               /*
+                                * zero-fill group members in the middle which
+                                * have no sample
+                                */
+                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
+                                               fmt, 0);
+                       }
 
-       return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
-}
+                       if (fmt_percent)
+                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
+                                               fmt, 100.0 * period / total);
+                       else
+                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
+                                               fmt, period);
 
-static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
-       const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
-
-static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
-{
-       return scnprintf(hpp->buf, hpp->size, "guest sys");
-}
-
-static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
-{
-       return 9;
-}
-
-static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
-                                        struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
-
-       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
-}
-
-static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
-                                        struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
-       const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
-
-static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
-{
-       return scnprintf(hpp->buf, hpp->size, "guest usr");
-}
+                       prev_idx = perf_evsel__group_idx(evsel);
+               }
 
-static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
-{
-       return 9;
-}
+               idx_delta = nr_members - prev_idx - 1;
 
-static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
-                                       struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
-
-       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
+               while (idx_delta--) {
+                       /*
+                        * zero-fill group members at last which have no sample
+                        */
+                       ret += print_fn(hpp->buf + ret, hpp->size - ret,
+                                       fmt, 0);
+               }
+       }
+       return ret;
 }
 
-static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
-                                       struct hist_entry *he)
-{
-       struct hists *hists = he->hists;
-       double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
-       const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
+#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width)          \
+static int hpp__header_##_type(struct perf_hpp *hpp)                   \
+{                                                                      \
+       int len = _min_width;                                           \
+                                                                       \
+       if (symbol_conf.event_group) {                                  \
+               struct perf_evsel *evsel = hpp->ptr;                    \
+                                                                       \
+               len = max(len, evsel->nr_members * _unit_width);        \
+       }                                                               \
+       return scnprintf(hpp->buf, hpp->size, "%*s", len, _str);        \
+}
+
+#define __HPP_WIDTH_FN(_type, _min_width, _unit_width)                         \
+static int hpp__width_##_type(struct perf_hpp *hpp __maybe_unused)     \
+{                                                                      \
+       int len = _min_width;                                           \
+                                                                       \
+       if (symbol_conf.event_group) {                                  \
+               struct perf_evsel *evsel = hpp->ptr;                    \
+                                                                       \
+               len = max(len, evsel->nr_members * _unit_width);        \
+       }                                                               \
+       return len;                                                     \
+}
+
+#define __HPP_COLOR_PERCENT_FN(_type, _field)                                  \
+static u64 he_get_##_field(struct hist_entry *he)                              \
+{                                                                              \
+       return he->stat._field;                                                 \
+}                                                                              \
+                                                                               \
+static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he)     \
+{                                                                              \
+       return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%",                 \
+                         (hpp_snprint_fn)percent_color_snprintf, true);        \
+}
+
+#define __HPP_ENTRY_PERCENT_FN(_type, _field)                                  \
+static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he)     \
+{                                                                              \
+       const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%";         \
+       return __hpp__fmt(hpp, he, he_get_##_field, fmt,                        \
+                         scnprintf, true);                                     \
+}
+
+#define __HPP_ENTRY_RAW_FN(_type, _field)                                      \
+static u64 he_get_raw_##_field(struct hist_entry *he)                          \
+{                                                                              \
+       return he->stat._field;                                                 \
+}                                                                              \
+                                                                               \
+static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he)     \
+{                                                                              \
+       const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64;    \
+       return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \
+}
+
+#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width)  \
+__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)                  \
+__HPP_WIDTH_FN(_type, _min_width, _unit_width)                         \
+__HPP_COLOR_PERCENT_FN(_type, _field)                                  \
+__HPP_ENTRY_PERCENT_FN(_type, _field)
+
+#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width)      \
+__HPP_HEADER_FN(_type, _str, _min_width, _unit_width)                  \
+__HPP_WIDTH_FN(_type, _min_width, _unit_width)                         \
+__HPP_ENTRY_RAW_FN(_type, _field)
+
+
+HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8)
+HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8)
+HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8)
+HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8)
+HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
+
+HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
+HPP_RAW_FNS(period, "Period", period, 12, 12)
 
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
-}
 
 static int hpp__header_baseline(struct perf_hpp *hpp)
 {
@@ -179,7 +191,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 {
        double percent = baseline_percent(he);
 
-       if (hist_entry__has_pairs(he))
+       if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
                return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
        else
                return scnprintf(hpp->buf, hpp->size, "        ");
@@ -196,44 +208,6 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
                return scnprintf(hpp->buf, hpp->size, "            ");
 }
 
-static int hpp__header_samples(struct perf_hpp *hpp)
-{
-       const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
-}
-
-static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
-{
-       return 11;
-}
-
-static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
-
-       return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
-}
-
-static int hpp__header_period(struct perf_hpp *hpp)
-{
-       const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
-
-       return scnprintf(hpp->buf, hpp->size, fmt, "Period");
-}
-
-static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
-{
-       return 12;
-}
-
-static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
-{
-       const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
-
-       return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
-}
-
 static int hpp__header_period_baseline(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
@@ -254,6 +228,7 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h
 
        return scnprintf(hpp->buf, hpp->size, fmt, period);
 }
+
 static int hpp__header_delta(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
@@ -268,14 +243,18 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 {
+       struct hist_entry *pair = hist_entry__next_pair(he);
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
        char buf[32] = " ";
-       double diff;
+       double diff = 0.0;
 
-       if (he->diff.computed)
-               diff = he->diff.period_ratio_delta;
-       else
-               diff = perf_diff__compute_delta(he);
+       if (pair) {
+               if (he->diff.computed)
+                       diff = he->diff.period_ratio_delta;
+               else
+                       diff = perf_diff__compute_delta(he, pair);
+       } else
+               diff = perf_diff__period_percent(he, he->stat.period);
 
        if (fabs(diff) >= 0.01)
                scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
@@ -297,14 +276,17 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
 {
+       struct hist_entry *pair = hist_entry__next_pair(he);
        const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
        char buf[32] = " ";
-       double ratio;
+       double ratio = 0.0;
 
-       if (he->diff.computed)
-               ratio = he->diff.period_ratio;
-       else
-               ratio = perf_diff__compute_ratio(he);
+       if (pair) {
+               if (he->diff.computed)
+                       ratio = he->diff.period_ratio;
+               else
+                       ratio = perf_diff__compute_ratio(he, pair);
+       }
 
        if (ratio > 0.0)
                scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
@@ -326,14 +308,17 @@ static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
 {
+       struct hist_entry *pair = hist_entry__next_pair(he);
        const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
        char buf[32] = " ";
-       s64 wdiff;
+       s64 wdiff = 0;
 
-       if (he->diff.computed)
-               wdiff = he->diff.wdiff;
-       else
-               wdiff = perf_diff__compute_wdiff(he);
+       if (pair) {
+               if (he->diff.computed)
+                       wdiff = he->diff.wdiff;
+               else
+                       wdiff = perf_diff__compute_wdiff(he, pair);
+       }
 
        if (wdiff != 0)
                scnprintf(buf, sizeof(buf), "%14ld", wdiff);
@@ -341,30 +326,6 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
-static int hpp__header_displ(struct perf_hpp *hpp)
-{
-       return scnprintf(hpp->buf, hpp->size, "Displ.");
-}
-
-static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
-{
-       return 6;
-}
-
-static int hpp__entry_displ(struct perf_hpp *hpp,
-                           struct hist_entry *he)
-{
-       struct hist_entry *pair = hist_entry__next_pair(he);
-       long displacement = pair ? pair->position - he->position : 0;
-       const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
-       char buf[32] = " ";
-
-       if (displacement)
-               scnprintf(buf, sizeof(buf), "%+4ld", displacement);
-
-       return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
 static int hpp__header_formula(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
@@ -379,67 +340,91 @@ static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
 {
+       struct hist_entry *pair = hist_entry__next_pair(he);
        const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
        char buf[96] = " ";
 
-       perf_diff__formula(buf, sizeof(buf), he);
+       if (pair)
+               perf_diff__formula(he, pair, buf, sizeof(buf));
+
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
-#define HPP__COLOR_PRINT_FNS(_name)            \
-       .header = hpp__header_ ## _name,                \
-       .width  = hpp__width_ ## _name,         \
-       .color  = hpp__color_ ## _name,         \
-       .entry  = hpp__entry_ ## _name
+#define HPP__COLOR_PRINT_FNS(_name)                    \
+       {                                               \
+               .header = hpp__header_ ## _name,        \
+               .width  = hpp__width_ ## _name,         \
+               .color  = hpp__color_ ## _name,         \
+               .entry  = hpp__entry_ ## _name          \
+       }
 
-#define HPP__PRINT_FNS(_name)                  \
-       .header = hpp__header_ ## _name,                \
-       .width  = hpp__width_ ## _name,         \
-       .entry  = hpp__entry_ ## _name
+#define HPP__PRINT_FNS(_name)                          \
+       {                                               \
+               .header = hpp__header_ ## _name,        \
+               .width  = hpp__width_ ## _name,         \
+               .entry  = hpp__entry_ ## _name          \
+       }
 
 struct perf_hpp_fmt perf_hpp__format[] = {
-       { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
-       { .cond = true,  HPP__COLOR_PRINT_FNS(overhead) },
-       { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
-       { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
-       { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
-       { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
-       { .cond = false, HPP__PRINT_FNS(samples) },
-       { .cond = false, HPP__PRINT_FNS(period) },
-       { .cond = false, HPP__PRINT_FNS(period_baseline) },
-       { .cond = false, HPP__PRINT_FNS(delta) },
-       { .cond = false, HPP__PRINT_FNS(ratio) },
-       { .cond = false, HPP__PRINT_FNS(wdiff) },
-       { .cond = false, HPP__PRINT_FNS(displ) },
-       { .cond = false, HPP__PRINT_FNS(formula) }
+       HPP__COLOR_PRINT_FNS(baseline),
+       HPP__COLOR_PRINT_FNS(overhead),
+       HPP__COLOR_PRINT_FNS(overhead_sys),
+       HPP__COLOR_PRINT_FNS(overhead_us),
+       HPP__COLOR_PRINT_FNS(overhead_guest_sys),
+       HPP__COLOR_PRINT_FNS(overhead_guest_us),
+       HPP__PRINT_FNS(samples),
+       HPP__PRINT_FNS(period),
+       HPP__PRINT_FNS(period_baseline),
+       HPP__PRINT_FNS(delta),
+       HPP__PRINT_FNS(ratio),
+       HPP__PRINT_FNS(wdiff),
+       HPP__PRINT_FNS(formula)
 };
 
+LIST_HEAD(perf_hpp__list);
+
+
 #undef HPP__COLOR_PRINT_FNS
 #undef HPP__PRINT_FNS
 
+#undef HPP_PERCENT_FNS
+#undef HPP_RAW_FNS
+
+#undef __HPP_HEADER_FN
+#undef __HPP_WIDTH_FN
+#undef __HPP_COLOR_PERCENT_FN
+#undef __HPP_ENTRY_PERCENT_FN
+#undef __HPP_ENTRY_RAW_FN
+
+
 void perf_hpp__init(void)
 {
        if (symbol_conf.show_cpu_utilization) {
-               perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
-               perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
+               perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
+               perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);
 
                if (perf_guest) {
-                       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
-                       perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
+                       perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS);
+                       perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US);
                }
        }
 
        if (symbol_conf.show_nr_samples)
-               perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
+               perf_hpp__column_enable(PERF_HPP__SAMPLES);
 
        if (symbol_conf.show_total_period)
-               perf_hpp__format[PERF_HPP__PERIOD].cond = true;
+               perf_hpp__column_enable(PERF_HPP__PERIOD);
+}
+
+void perf_hpp__column_register(struct perf_hpp_fmt *format)
+{
+       list_add_tail(&format->list, &perf_hpp__list);
 }
 
-void perf_hpp__column_enable(unsigned col, bool enable)
+void perf_hpp__column_enable(unsigned col)
 {
        BUG_ON(col >= PERF_HPP__MAX_INDEX);
-       perf_hpp__format[col].cond = enable;
+       perf_hpp__column_register(&perf_hpp__format[col]);
 }
 
 static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -452,27 +437,29 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
                                bool color)
 {
        const char *sep = symbol_conf.field_sep;
+       struct perf_hpp_fmt *fmt;
        char *start = hpp->buf;
-       int i, ret;
+       int ret;
        bool first = true;
 
        if (symbol_conf.exclude_other && !he->parent)
                return 0;
 
-       for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-               if (!perf_hpp__format[i].cond)
-                       continue;
-
+       perf_hpp__for_each_format(fmt) {
+               /*
+                * If there's no field_sep, we still need
+                * to display initial '  '.
+                */
                if (!sep || !first) {
                        ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
                        advance_hpp(hpp, ret);
+               } else
                        first = false;
-               }
 
-               if (color && perf_hpp__format[i].color)
-                       ret = perf_hpp__format[i].color(hpp, he);
+               if (color && fmt->color)
+                       ret = fmt->color(hpp, he);
                else
-                       ret = perf_hpp__format[i].entry(hpp, he);
+                       ret = fmt->entry(hpp, he);
 
                advance_hpp(hpp, ret);
        }
@@ -504,16 +491,18 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
  */
 unsigned int hists__sort_list_width(struct hists *hists)
 {
+       struct perf_hpp_fmt *fmt;
        struct sort_entry *se;
-       int i, ret = 0;
+       int i = 0, ret = 0;
+       struct perf_hpp dummy_hpp = {
+               .ptr    = hists_to_evsel(hists),
+       };
 
-       for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
-               if (!perf_hpp__format[i].cond)
-                       continue;
+       perf_hpp__for_each_format(fmt) {
                if (i)
                        ret += 2;
 
-               ret += perf_hpp__format[i].width(NULL);
+               ret += fmt->width(&dummy_hpp);
        }
 
        list_for_each_entry(se, &hist_entry__sort_list, list)
index 809eca5707fae1fccee91dcd8a22ef46603f347c..65092d576b4e25fb4d8ad7876e6d399492165218 100644 (file)
@@ -23,5 +23,6 @@
 #define K_TIMER         -1
 #define K_ERROR         -2
 #define K_RESIZE -3
+#define K_SWITCH_INPUT_DATA -4
 
 #endif /* _PERF_KEYSYMS_H_ */
index ebb4cc10787625aca596f6a41a14d56efd9e60d8..ae6a789cb0f62780a9fa088f7fe99939c798ef2d 100644 (file)
@@ -8,7 +8,7 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 
 void setup_browser(bool fallback_to_pager)
 {
-       if (!isatty(1) || dump_trace)
+       if (use_browser < 2 && (!isatty(1) || dump_trace))
                use_browser = 0;
 
        /* default to TUI */
@@ -30,6 +30,7 @@ void setup_browser(bool fallback_to_pager)
                if (fallback_to_pager)
                        setup_pager();
 
+               perf_hpp__column_enable(PERF_HPP__OVERHEAD);
                perf_hpp__init();
                break;
        }
index f0ee204f99bb4bffddedd7434d276f05d98cfb9c..ff1f60cf442e164f6843031fe89d7a9f14d0c288 100644 (file)
@@ -3,6 +3,7 @@
 #include "../../util/util.h"
 #include "../../util/hist.h"
 #include "../../util/sort.h"
+#include "../../util/evsel.h"
 
 
 static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -335,17 +336,19 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
 size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                      int max_cols, FILE *fp)
 {
+       struct perf_hpp_fmt *fmt;
        struct sort_entry *se;
        struct rb_node *nd;
        size_t ret = 0;
        unsigned int width;
        const char *sep = symbol_conf.field_sep;
        const char *col_width = symbol_conf.col_width_list_str;
-       int idx, nr_rows = 0;
+       int nr_rows = 0;
        char bf[96];
        struct perf_hpp dummy_hpp = {
                .buf    = bf,
                .size   = sizeof(bf),
+               .ptr    = hists_to_evsel(hists),
        };
        bool first = true;
 
@@ -355,16 +358,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                goto print_entries;
 
        fprintf(fp, "# ");
-       for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
-               if (!perf_hpp__format[idx].cond)
-                       continue;
 
+       perf_hpp__for_each_format(fmt) {
                if (!first)
                        fprintf(fp, "%s", sep ?: "  ");
                else
                        first = false;
 
-               perf_hpp__format[idx].header(&dummy_hpp);
+               fmt->header(&dummy_hpp);
                fprintf(fp, "%s", bf);
        }
 
@@ -400,18 +401,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
        first = true;
 
        fprintf(fp, "# ");
-       for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
-               unsigned int i;
 
-               if (!perf_hpp__format[idx].cond)
-                       continue;
+       perf_hpp__for_each_format(fmt) {
+               unsigned int i;
 
                if (!first)
                        fprintf(fp, "%s", sep ?: "  ");
                else
                        first = false;
 
-               width = perf_hpp__format[idx].width(&dummy_hpp);
+               width = fmt->width(&dummy_hpp);
                for (i = 0; i < width; i++)
                        fprintf(fp, ".");
        }
@@ -462,7 +461,7 @@ out:
        return ret;
 }
 
-size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
+size_t events_stats__fprintf(struct events_stats *stats, FILE *fp)
 {
        int i;
        size_t ret = 0;
@@ -470,7 +469,7 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
        for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
                const char *name;
 
-               if (hists->stats.nr_events[i] == 0)
+               if (stats->nr_events[i] == 0)
                        continue;
 
                name = perf_event__name(i);
@@ -478,7 +477,7 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
                        continue;
 
                ret += fprintf(fp, "%16s events: %10d\n", name,
-                              hists->stats.nr_events[i]);
+                              stats->nr_events[i]);
        }
 
        return ret;
index 2884d2f41e33ffb336431f8aac42be19625d0a91..1c8b9afd5d6e723127ade5700e52a07eeee2cf8d 100644 (file)
@@ -8,6 +8,8 @@
 #include "../ui.h"
 #include "../libslang.h"
 
+char ui_helpline__last_msg[1024];
+
 static void tui_helpline__pop(void)
 {
 }
@@ -23,20 +25,7 @@ static void tui_helpline__push(const char *msg)
        strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
 }
 
-struct ui_helpline tui_helpline_fns = {
-       .pop    = tui_helpline__pop,
-       .push   = tui_helpline__push,
-};
-
-void ui_helpline__init(void)
-{
-       helpline_fns = &tui_helpline_fns;
-       ui_helpline__puts(" ");
-}
-
-char ui_helpline__last_msg[1024];
-
-int ui_helpline__show_help(const char *format, va_list ap)
+static int tui_helpline__show(const char *format, va_list ap)
 {
        int ret;
        static int backlog;
@@ -55,3 +44,15 @@ int ui_helpline__show_help(const char *format, va_list ap)
 
        return ret;
 }
+
+struct ui_helpline tui_helpline_fns = {
+       .pop    = tui_helpline__pop,
+       .push   = tui_helpline__push,
+       .show   = tui_helpline__show,
+};
+
+void ui_helpline__init(void)
+{
+       helpline_fns = &tui_helpline_fns;
+       ui_helpline__puts(" ");
+}
index 4f989774c8c674c535990dcf82ae2ba47d5971e3..e3e0a963d03aa3559924af97a33bb67c3f48b275 100644 (file)
@@ -52,7 +52,6 @@ int ui__warning(const char *format, ...)
        return ret;
 }
 
-
 /**
  * perf_error__register - Register error logging functions
  * @eops: The pointer to error logging function struct
index 6aa34e5afdcfc0a57cafc12d6bc631d2d8169fbb..055fef34b6f6cf791a4b7daa8e73a8e3765591ff 100755 (executable)
@@ -26,13 +26,13 @@ VN=$(expr "$VN" : v*'\(.*\)')
 
 if test -r $GVF
 then
-       VC=$(sed -e 's/^PERF_VERSION = //' <$GVF)
+       VC=$(sed -e 's/^#define PERF_VERSION "\(.*\)"/\1/' <$GVF)
 else
        VC=unset
 fi
 test "$VN" = "$VC" || {
        echo >&2 "PERF_VERSION = $VN"
-       echo "PERF_VERSION = $VN" >$GVF
+       echo "#define PERF_VERSION \"$VN\"" >$GVF
 }
 
 
index 07aaeea600007b05dab7ff8b04e720735e5f4643..d33fe937e6f18ea6775e653d934878955f70f0be 100644 (file)
@@ -809,7 +809,7 @@ fallback:
                pr_err("Can't annotate %s:\n\n"
                       "No vmlinux file%s\nwas found in the path.\n\n"
                       "Please use:\n\n"
-                      "  perf buildid-cache -av vmlinux\n\n"
+                      "  perf buildid-cache -vu vmlinux\n\n"
                       "or:\n\n"
                       "  --vmlinux vmlinux\n",
                       sym->name, build_id_msg ?: "");
index 8eec94358a4a1cc627e2d7b16acd62679626bd65..c422440fe611689b1a0b089f308a4aa876e547fc 100644 (file)
@@ -6,6 +6,7 @@
 #include "types.h"
 #include "symbol.h"
 #include "hist.h"
+#include "sort.h"
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <pthread.h>
@@ -154,6 +155,29 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 }
 #endif
 
+#ifdef GTK2_SUPPORT
+int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx,
+                        struct hist_browser_timer *hbt);
+
+static inline int hist_entry__gtk_annotate(struct hist_entry *he, int evidx,
+                                          struct hist_browser_timer *hbt)
+{
+       return symbol__gtk_annotate(he->ms.sym, he->ms.map, evidx, hbt);
+}
+
+void perf_gtk__show_annotations(void);
+#else
+static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused,
+                                          int evidx __maybe_unused,
+                                          struct hist_browser_timer *hbt
+                                          __maybe_unused)
+{
+       return 0;
+}
+
+static inline void perf_gtk__show_annotations(void) {}
+#endif
+
 extern const char      *disassembler_style;
 
 #endif /* __PERF_ANNOTATE_H */
index d3b3f5d82137fd23cbdee5ab4686bec78802ff49..42b6a632fe7b75bb297433e9ad9962814e5016d9 100644 (file)
@@ -444,7 +444,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
        struct callchain_cursor_node *node = *cursor->last;
 
        if (!node) {
-               node = calloc(sizeof(*node), 1);
+               node = calloc(1, sizeof(*node));
                if (!node)
                        return -ENOMEM;
 
index eb340571e7d6928394b218010926898029569d9d..3ee9f67d5af0bed457cb7ae22d5efe99ccdbfd8f 100644 (file)
@@ -143,4 +143,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
        cursor->curr = cursor->curr->next;
        cursor->pos++;
 }
+
+struct option;
+
+int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
+extern const char record_callchain_help[];
 #endif /* __PERF_CALLCHAIN_H */
index 2b32ffa9ebdb188e8edeb31fc4176380d99b2337..f817046e22b1204bc75c41d701464bb893e530fd 100644 (file)
@@ -1,4 +1,5 @@
 #include "util.h"
+#include "sysfs.h"
 #include "../perf.h"
 #include "cpumap.h"
 #include <assert.h>
@@ -201,3 +202,56 @@ void cpu_map__delete(struct cpu_map *map)
 {
        free(map);
 }
+
+int cpu_map__get_socket(struct cpu_map *map, int idx)
+{
+       FILE *fp;
+       const char *mnt;
+       char path[PATH_MAX];
+       int cpu, ret;
+
+       if (idx > map->nr)
+               return -1;
+
+       cpu = map->map[idx];
+
+       mnt = sysfs_find_mountpoint();
+       if (!mnt)
+               return -1;
+
+       sprintf(path,
+               "%s/devices/system/cpu/cpu%d/topology/physical_package_id",
+               mnt, cpu);
+
+       fp = fopen(path, "r");
+       if (!fp)
+               return -1;
+       ret = fscanf(fp, "%d", &cpu);
+       fclose(fp);
+       return ret == 1 ? cpu : -1;
+}
+
+int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
+{
+       struct cpu_map *sock;
+       int nr = cpus->nr;
+       int cpu, s1, s2;
+
+       sock = calloc(1, sizeof(*sock) + nr * sizeof(int));
+       if (!sock)
+               return -1;
+
+       for (cpu = 0; cpu < nr; cpu++) {
+               s1 = cpu_map__get_socket(cpus, cpu);
+               for (s2 = 0; s2 < sock->nr; s2++) {
+                       if (s1 == sock->map[s2])
+                               break;
+               }
+               if (s2 == sock->nr) {
+                       sock->map[sock->nr] = s1;
+                       sock->nr++;
+               }
+       }
+       *sockp = sock;
+       return 0;
+}
index 2f68a3b8c285dd80f6c21bc47f180e326528cc15..161b00756a1205a25f42ab171127e56f7677c1b0 100644 (file)
@@ -14,6 +14,15 @@ struct cpu_map *cpu_map__dummy_new(void);
 void cpu_map__delete(struct cpu_map *map);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
+int cpu_map__get_socket(struct cpu_map *map, int idx);
+int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
+
+static inline int cpu_map__socket(struct cpu_map *sock, int s)
+{
+       if (!sock || s > sock->nr || s < 0)
+               return 0;
+       return sock->map[s];
+}
 
 static inline int cpu_map__nr(const struct cpu_map *map)
 {
index 03f830b48148a7b41f0c4bb1b59b7f1614db035c..399e74c34c1aa5220ecc29bd0d33cca2d2a3ac82 100644 (file)
@@ -23,10 +23,8 @@ int eprintf(int level, const char *fmt, ...)
 
        if (verbose >= level) {
                va_start(args, fmt);
-               if (use_browser == 1)
-                       ret = ui_helpline__show_help(fmt, args);
-               else if (use_browser == 2)
-                       ret = perf_gtk__show_helpline(fmt, args);
+               if (use_browser >= 1)
+                       ui_helpline__vshow(fmt, args);
                else
                        ret = vfprintf(stderr, fmt, args);
                va_end(args);
@@ -49,28 +47,6 @@ int dump_printf(const char *fmt, ...)
        return ret;
 }
 
-#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
-int ui__warning(const char *format, ...)
-{
-       va_list args;
-
-       va_start(args, format);
-       vfprintf(stderr, format, args);
-       va_end(args);
-       return 0;
-}
-#endif
-
-int ui__error_paranoid(void)
-{
-       return ui__error("Permission error - are you root?\n"
-                   "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
-                   " -1 - Not paranoid at all\n"
-                   "  0 - Disallow raw tracepoint access for unpriv\n"
-                   "  1 - Disallow cpu events for unpriv\n"
-                   "  2 - Disallow kernel profiling for unpriv\n");
-}
-
 void trace_event(union perf_event *event)
 {
        unsigned char *raw_event = (void *)event;
index 83e8d234af6b149a045902c267dbb8c6b8926ad0..efbd98805ad0b0086996298b698122a2b0ceb018 100644 (file)
@@ -5,6 +5,8 @@
 #include <stdbool.h>
 #include "event.h"
 #include "../ui/helpline.h"
+#include "../ui/progress.h"
+#include "../ui/util.h"
 
 extern int verbose;
 extern bool quiet, dump_trace;
@@ -12,39 +14,7 @@ extern bool quiet, dump_trace;
 int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void trace_event(union perf_event *event);
 
-struct ui_progress;
-struct perf_error_ops;
-
-#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
-
-#include "../ui/progress.h"
 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#include "../ui/util.h"
-
-#else
-
-static inline void ui_progress__update(u64 curr __maybe_unused,
-                                      u64 total __maybe_unused,
-                                      const char *title __maybe_unused) {}
-static inline void ui_progress__finish(void) {}
-
-#define ui__error(format, arg...) ui__warning(format, ##arg)
-
-static inline int
-perf_error__register(struct perf_error_ops *eops __maybe_unused)
-{
-       return 0;
-}
-
-static inline int
-perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
-{
-       return 0;
-}
-
-#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
-
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
-int ui__error_paranoid(void);
 
 #endif /* __PERF_DEBUG_H */
index d6d9a465acdbe09437571ca737e7d28cb5fdf770..6f7d5a9d6b050ddec28b0b76461e155c8829794a 100644 (file)
@@ -539,13 +539,13 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name)
 }
 
 size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
-                              bool with_hits)
+                              bool (skip)(struct dso *dso, int parm), int parm)
 {
        struct dso *pos;
        size_t ret = 0;
 
        list_for_each_entry(pos, head, node) {
-               if (with_hits && !pos->hit)
+               if (skip && skip(pos, parm))
                        continue;
                ret += dso__fprintf_buildid(pos, fp);
                ret += fprintf(fp, " %s\n", pos->long_name);
@@ -583,7 +583,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
        if (dso->short_name != dso->long_name)
                ret += fprintf(fp, "%s, ", dso->long_name);
        ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
-                      dso->loaded ? "" : "NOT ");
+                      dso__loaded(dso, type) ? "" : "NOT ");
        ret += dso__fprintf_buildid(dso, fp);
        ret += fprintf(fp, ")\n");
        for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
index e03276940b99638b2a25c90f6bd852800051ffb2..450199ab51b5d8364dd0393a75c5f04d913b6300 100644 (file)
@@ -138,7 +138,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name);
 bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
 
 size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
-                              bool with_hits);
+                              bool (skip)(struct dso *dso, int parm), int parm);
 size_t __dsos__fprintf(struct list_head *head, FILE *fp);
 
 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
index 3cf2c3e0605f249543c11ddbe2c39cb2607a6f7a..5cd13d768cecee1a630ca51715dba4b6d8f19f0b 100644 (file)
@@ -476,8 +476,10 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                }
        }
 
-       if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0)
+       if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
+               free(event);
                return -ENOENT;
+       }
 
        map = machine->vmlinux_maps[MAP__FUNCTION];
        size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
index 705293489e3c319c0b13ec3f5f32a3c1fd1fe5ed..bc4ad79774387aec0a0e9355c7a1a47c747b0528 100644 (file)
@@ -49,10 +49,16 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
        return evlist;
 }
 
-void perf_evlist__config_attrs(struct perf_evlist *evlist,
-                              struct perf_record_opts *opts)
+void perf_evlist__config(struct perf_evlist *evlist,
+                       struct perf_record_opts *opts)
 {
        struct perf_evsel *evsel;
+       /*
+        * Set the evsel leader links before we configure attributes,
+        * since some might depend on this info.
+        */
+       if (opts->group)
+               perf_evlist__set_leader(evlist);
 
        if (evlist->cpus->map[0] < 0)
                opts->no_inherit = true;
@@ -61,7 +67,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
                perf_evsel__config(evsel, opts);
 
                if (evlist->nr_entries > 1)
-                       evsel->attr.sample_type |= PERF_SAMPLE_ID;
+                       perf_evsel__set_sample_id(evsel);
        }
 }
 
@@ -111,18 +117,21 @@ void __perf_evlist__set_leader(struct list_head *list)
        struct perf_evsel *evsel, *leader;
 
        leader = list_entry(list->next, struct perf_evsel, node);
-       leader->leader = NULL;
+       evsel = list_entry(list->prev, struct perf_evsel, node);
+
+       leader->nr_members = evsel->idx - leader->idx + 1;
 
        list_for_each_entry(evsel, list, node) {
-               if (evsel != leader)
-                       evsel->leader = leader;
+               evsel->leader = leader;
        }
 }
 
 void perf_evlist__set_leader(struct perf_evlist *evlist)
 {
-       if (evlist->nr_entries)
+       if (evlist->nr_entries) {
+               evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
                __perf_evlist__set_leader(&evlist->entries);
+       }
 }
 
 int perf_evlist__add_default(struct perf_evlist *evlist)
@@ -222,7 +231,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
 
        for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
                list_for_each_entry(pos, &evlist->entries, node) {
-                       if (perf_evsel__is_group_member(pos))
+                       if (!perf_evsel__is_group_leader(pos))
                                continue;
                        for (thread = 0; thread < evlist->threads->nr; thread++)
                                ioctl(FD(pos, cpu, thread),
@@ -238,7 +247,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
 
        for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
                list_for_each_entry(pos, &evlist->entries, node) {
-                       if (perf_evsel__is_group_member(pos))
+                       if (!perf_evsel__is_group_leader(pos))
                                continue;
                        for (thread = 0; thread < evlist->threads->nr; thread++)
                                ioctl(FD(pos, cpu, thread),
@@ -366,7 +375,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
                if ((old & md->mask) + size != ((old + size) & md->mask)) {
                        unsigned int offset = old;
                        unsigned int len = min(sizeof(*event), size), cpy;
-                       void *dst = &evlist->event_copy;
+                       void *dst = &md->event_copy;
 
                        do {
                                cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -376,7 +385,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
                                len -= cpy;
                        } while (len);
 
-                       event = &evlist->event_copy;
+                       event = &md->event_copy;
                }
 
                old += size;
index 56003f779e601d181eec34fd38de5bb66c30bc5c..2dd07bd60b4f7048a41752a92aa7dc4dc23fced8 100644 (file)
@@ -17,10 +17,18 @@ struct perf_record_opts;
 #define PERF_EVLIST__HLIST_BITS 8
 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
 
+struct perf_mmap {
+       void             *base;
+       int              mask;
+       unsigned int     prev;
+       union perf_event event_copy;
+};
+
 struct perf_evlist {
        struct list_head entries;
        struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
        int              nr_entries;
+       int              nr_groups;
        int              nr_fds;
        int              nr_mmaps;
        int              mmap_len;
@@ -29,7 +37,6 @@ struct perf_evlist {
                pid_t   pid;
        } workload;
        bool             overwrite;
-       union perf_event event_copy;
        struct perf_mmap *mmap;
        struct pollfd    *pollfd;
        struct thread_map *threads;
@@ -76,8 +83,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
 
 int perf_evlist__open(struct perf_evlist *evlist);
 
-void perf_evlist__config_attrs(struct perf_evlist *evlist,
-                              struct perf_record_opts *opts);
+void perf_evlist__config(struct perf_evlist *evlist,
+                        struct perf_record_opts *opts);
 
 int perf_evlist__prepare_workload(struct perf_evlist *evlist,
                                  struct perf_record_opts *opts,
@@ -135,4 +142,25 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
 }
 
 size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
+
+static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
+{
+       struct perf_event_mmap_page *pc = mm->base;
+       int head = pc->data_head;
+       rmb();
+       return head;
+}
+
+static inline void perf_mmap__write_tail(struct perf_mmap *md,
+                                        unsigned long tail)
+{
+       struct perf_event_mmap_page *pc = md->base;
+
+       /*
+        * ensure all reads are done before we write the tail out.
+        */
+       /* mb(); */
+       pc->data_tail = tail;
+}
+
 #endif /* __PERF_EVLIST_H */
index 1b16dd1edc8eb2c6d632ec313e7380aac6c575c7..9c82f98f26dedd460fb5b2c70fcb8256c33fca42 100644 (file)
 #include <linux/perf_event.h>
 #include "perf_regs.h"
 
+static struct {
+       bool sample_id_all;
+       bool exclude_guest;
+} perf_missing_features;
+
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 
 static int __perf_evsel__sample_size(u64 sample_type)
@@ -50,11 +55,36 @@ void hists__init(struct hists *hists)
        pthread_mutex_init(&hists->lock, NULL);
 }
 
+void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+                                 enum perf_event_sample_format bit)
+{
+       if (!(evsel->attr.sample_type & bit)) {
+               evsel->attr.sample_type |= bit;
+               evsel->sample_size += sizeof(u64);
+       }
+}
+
+void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+                                   enum perf_event_sample_format bit)
+{
+       if (evsel->attr.sample_type & bit) {
+               evsel->attr.sample_type &= ~bit;
+               evsel->sample_size -= sizeof(u64);
+       }
+}
+
+void perf_evsel__set_sample_id(struct perf_evsel *evsel)
+{
+       perf_evsel__set_sample_bit(evsel, ID);
+       evsel->attr.read_format |= PERF_FORMAT_ID;
+}
+
 void perf_evsel__init(struct perf_evsel *evsel,
                      struct perf_event_attr *attr, int idx)
 {
        evsel->idx         = idx;
        evsel->attr        = *attr;
+       evsel->leader      = evsel;
        INIT_LIST_HEAD(&evsel->node);
        hists__init(&evsel->hists);
        evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -404,6 +434,31 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
        return evsel->name ?: "unknown";
 }
 
+const char *perf_evsel__group_name(struct perf_evsel *evsel)
+{
+       return evsel->group_name ?: "anon group";
+}
+
+int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
+{
+       int ret;
+       struct perf_evsel *pos;
+       const char *group_name = perf_evsel__group_name(evsel);
+
+       ret = scnprintf(buf, size, "%s", group_name);
+
+       ret += scnprintf(buf + ret, size - ret, " { %s",
+                        perf_evsel__name(evsel));
+
+       for_each_group_member(pos, evsel)
+               ret += scnprintf(buf + ret, size - ret, ", %s",
+                                perf_evsel__name(pos));
+
+       ret += scnprintf(buf + ret, size - ret, " }");
+
+       return ret;
+}
+
 /*
  * The enable_on_exec/disabled value strategy:
  *
@@ -438,13 +493,11 @@ void perf_evsel__config(struct perf_evsel *evsel,
        struct perf_event_attr *attr = &evsel->attr;
        int track = !evsel->idx; /* only the first counter needs these */
 
-       attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
+       attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
        attr->inherit       = !opts->no_inherit;
-       attr->read_format   = PERF_FORMAT_TOTAL_TIME_ENABLED |
-                             PERF_FORMAT_TOTAL_TIME_RUNNING |
-                             PERF_FORMAT_ID;
 
-       attr->sample_type  |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+       perf_evsel__set_sample_bit(evsel, IP);
+       perf_evsel__set_sample_bit(evsel, TID);
 
        /*
         * We default some events to a 1 default interval. But keep
@@ -453,7 +506,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
        if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
                                     opts->user_interval != ULLONG_MAX)) {
                if (opts->freq) {
-                       attr->sample_type       |= PERF_SAMPLE_PERIOD;
+                       perf_evsel__set_sample_bit(evsel, PERIOD);
                        attr->freq              = 1;
                        attr->sample_freq       = opts->freq;
                } else {
@@ -468,16 +521,16 @@ void perf_evsel__config(struct perf_evsel *evsel,
                attr->inherit_stat = 1;
 
        if (opts->sample_address) {
-               attr->sample_type       |= PERF_SAMPLE_ADDR;
+               perf_evsel__set_sample_bit(evsel, ADDR);
                attr->mmap_data = track;
        }
 
        if (opts->call_graph) {
-               attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
+               perf_evsel__set_sample_bit(evsel, CALLCHAIN);
 
                if (opts->call_graph == CALLCHAIN_DWARF) {
-                       attr->sample_type |= PERF_SAMPLE_REGS_USER |
-                                            PERF_SAMPLE_STACK_USER;
+                       perf_evsel__set_sample_bit(evsel, REGS_USER);
+                       perf_evsel__set_sample_bit(evsel, STACK_USER);
                        attr->sample_regs_user = PERF_REGS_MASK;
                        attr->sample_stack_user = opts->stack_dump_size;
                        attr->exclude_callchain_user = 1;
@@ -485,20 +538,20 @@ void perf_evsel__config(struct perf_evsel *evsel,
        }
 
        if (perf_target__has_cpu(&opts->target))
-               attr->sample_type       |= PERF_SAMPLE_CPU;
+               perf_evsel__set_sample_bit(evsel, CPU);
 
        if (opts->period)
-               attr->sample_type       |= PERF_SAMPLE_PERIOD;
+               perf_evsel__set_sample_bit(evsel, PERIOD);
 
-       if (!opts->sample_id_all_missing &&
+       if (!perf_missing_features.sample_id_all &&
            (opts->sample_time || !opts->no_inherit ||
             perf_target__has_cpu(&opts->target)))
-               attr->sample_type       |= PERF_SAMPLE_TIME;
+               perf_evsel__set_sample_bit(evsel, TIME);
 
        if (opts->raw_samples) {
-               attr->sample_type       |= PERF_SAMPLE_TIME;
-               attr->sample_type       |= PERF_SAMPLE_RAW;
-               attr->sample_type       |= PERF_SAMPLE_CPU;
+               perf_evsel__set_sample_bit(evsel, TIME);
+               perf_evsel__set_sample_bit(evsel, RAW);
+               perf_evsel__set_sample_bit(evsel, CPU);
        }
 
        if (opts->no_delay) {
@@ -506,7 +559,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
                attr->wakeup_events = 1;
        }
        if (opts->branch_stack) {
-               attr->sample_type       |= PERF_SAMPLE_BRANCH_STACK;
+               perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
                attr->branch_sample_type = opts->branch_stack;
        }
 
@@ -519,14 +572,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
         * Disabling only independent events or group leaders,
         * keeping group members enabled.
         */
-       if (!perf_evsel__is_group_member(evsel))
+       if (perf_evsel__is_group_leader(evsel))
                attr->disabled = 1;
 
        /*
         * Setting enable_on_exec for independent events and
         * group leaders for traced executed by perf.
         */
-       if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel))
+       if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
                attr->enable_on_exec = 1;
 }
 
@@ -612,6 +665,11 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
                }
 }
 
+void perf_evsel__free_counts(struct perf_evsel *evsel)
+{
+       free(evsel->counts);
+}
+
 void perf_evsel__exit(struct perf_evsel *evsel)
 {
        assert(list_empty(&evsel->node));
@@ -631,6 +689,28 @@ void perf_evsel__delete(struct perf_evsel *evsel)
        free(evsel);
 }
 
+static inline void compute_deltas(struct perf_evsel *evsel,
+                                 int cpu,
+                                 struct perf_counts_values *count)
+{
+       struct perf_counts_values tmp;
+
+       if (!evsel->prev_raw_counts)
+               return;
+
+       if (cpu == -1) {
+               tmp = evsel->prev_raw_counts->aggr;
+               evsel->prev_raw_counts->aggr = *count;
+       } else {
+               tmp = evsel->prev_raw_counts->cpu[cpu];
+               evsel->prev_raw_counts->cpu[cpu] = *count;
+       }
+
+       count->val = count->val - tmp.val;
+       count->ena = count->ena - tmp.ena;
+       count->run = count->run - tmp.run;
+}
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
                              int cpu, int thread, bool scale)
 {
@@ -646,6 +726,8 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
        if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
                return -errno;
 
+       compute_deltas(evsel, cpu, &count);
+
        if (scale) {
                if (count.run == 0)
                        count.val = 0;
@@ -684,6 +766,8 @@ int __perf_evsel__read(struct perf_evsel *evsel,
                }
        }
 
+       compute_deltas(evsel, -1, aggr);
+
        evsel->counts->scaled = 0;
        if (scale) {
                if (aggr->run == 0) {
@@ -707,7 +791,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
        struct perf_evsel *leader = evsel->leader;
        int fd;
 
-       if (!perf_evsel__is_group_member(evsel))
+       if (perf_evsel__is_group_leader(evsel))
                return -1;
 
        /*
@@ -738,6 +822,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                pid = evsel->cgrp->fd;
        }
 
+fallback_missing_features:
+       if (perf_missing_features.exclude_guest)
+               evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
+retry_sample_id:
+       if (perf_missing_features.sample_id_all)
+               evsel->attr.sample_id_all = 0;
+
        for (cpu = 0; cpu < cpus->nr; cpu++) {
 
                for (thread = 0; thread < threads->nr; thread++) {
@@ -754,13 +845,26 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                                                                     group_fd, flags);
                        if (FD(evsel, cpu, thread) < 0) {
                                err = -errno;
-                               goto out_close;
+                               goto try_fallback;
                        }
                }
        }
 
        return 0;
 
+try_fallback:
+       if (err != -EINVAL || cpu > 0 || thread > 0)
+               goto out_close;
+
+       if (!perf_missing_features.exclude_guest &&
+           (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+               perf_missing_features.exclude_guest = true;
+               goto fallback_missing_features;
+       } else if (!perf_missing_features.sample_id_all) {
+               perf_missing_features.sample_id_all = true;
+               goto retry_sample_id;
+       }
+
 out_close:
        do {
                while (--thread >= 0) {
@@ -1205,3 +1309,225 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
 
        return 0;
 }
+
+static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
+{
+       va_list args;
+       int ret = 0;
+
+       if (!*first) {
+               ret += fprintf(fp, ",");
+       } else {
+               ret += fprintf(fp, ":");
+               *first = false;
+       }
+
+       va_start(args, fmt);
+       ret += vfprintf(fp, fmt, args);
+       va_end(args);
+       return ret;
+}
+
+static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
+{
+       if (value == 0)
+               return 0;
+
+       return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
+}
+
+#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
+
+struct bit_names {
+       int bit;
+       const char *name;
+};
+
+static int bits__fprintf(FILE *fp, const char *field, u64 value,
+                        struct bit_names *bits, bool *first)
+{
+       int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
+       bool first_bit = true;
+
+       do {
+               if (value & bits[i].bit) {
+                       printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
+                       first_bit = false;
+               }
+       } while (bits[++i].name != NULL);
+
+       return printed;
+}
+
+static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
+{
+#define bit_name(n) { PERF_SAMPLE_##n, #n }
+       struct bit_names bits[] = {
+               bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
+               bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
+               bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
+               bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
+               { .name = NULL, }
+       };
+#undef bit_name
+       return bits__fprintf(fp, "sample_type", value, bits, first);
+}
+
+static int read_format__fprintf(FILE *fp, bool *first, u64 value)
+{
+#define bit_name(n) { PERF_FORMAT_##n, #n }
+       struct bit_names bits[] = {
+               bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
+               bit_name(ID), bit_name(GROUP),
+               { .name = NULL, }
+       };
+#undef bit_name
+       return bits__fprintf(fp, "read_format", value, bits, first);
+}
+
+int perf_evsel__fprintf(struct perf_evsel *evsel,
+                       struct perf_attr_details *details, FILE *fp)
+{
+       bool first = true;
+       int printed = 0;
+
+       if (details->event_group) {
+               struct perf_evsel *pos;
+
+               if (!perf_evsel__is_group_leader(evsel))
+                       return 0;
+
+               if (evsel->nr_members > 1)
+                       printed += fprintf(fp, "%s{", evsel->group_name ?: "");
+
+               printed += fprintf(fp, "%s", perf_evsel__name(evsel));
+               for_each_group_member(pos, evsel)
+                       printed += fprintf(fp, ",%s", perf_evsel__name(pos));
+
+               if (evsel->nr_members > 1)
+                       printed += fprintf(fp, "}");
+               goto out;
+       }
+
+       printed += fprintf(fp, "%s", perf_evsel__name(evsel));
+
+       if (details->verbose || details->freq) {
+               printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
+                                        (u64)evsel->attr.sample_freq);
+       }
+
+       if (details->verbose) {
+               if_print(type);
+               if_print(config);
+               if_print(config1);
+               if_print(config2);
+               if_print(size);
+               printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
+               if (evsel->attr.read_format)
+                       printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
+               if_print(disabled);
+               if_print(inherit);
+               if_print(pinned);
+               if_print(exclusive);
+               if_print(exclude_user);
+               if_print(exclude_kernel);
+               if_print(exclude_hv);
+               if_print(exclude_idle);
+               if_print(mmap);
+               if_print(comm);
+               if_print(freq);
+               if_print(inherit_stat);
+               if_print(enable_on_exec);
+               if_print(task);
+               if_print(watermark);
+               if_print(precise_ip);
+               if_print(mmap_data);
+               if_print(sample_id_all);
+               if_print(exclude_host);
+               if_print(exclude_guest);
+               if_print(__reserved_1);
+               if_print(wakeup_events);
+               if_print(bp_type);
+               if_print(branch_sample_type);
+       }
+out:
+       fputc('\n', fp);
+       return ++printed;
+}
+
+bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
+                         char *msg, size_t msgsize)
+{
+       if ((err == ENOENT || err == ENXIO) &&
+           evsel->attr.type   == PERF_TYPE_HARDWARE &&
+           evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) {
+               /*
+                * If it's cycles then fall back to hrtimer based
+                * cpu-clock-tick sw counter, which is always available even if
+                * no PMU support.
+                *
+                * PPC returns ENXIO until 2.6.37 (behavior changed with commit
+                * b0a873e).
+                */
+               scnprintf(msg, msgsize, "%s",
+"The cycles event is not supported, trying to fall back to cpu-clock-ticks");
+
+               evsel->attr.type   = PERF_TYPE_SOFTWARE;
+               evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
+
+               free(evsel->name);
+               evsel->name = NULL;
+               return true;
+       }
+
+       return false;
+}
+
+int perf_evsel__open_strerror(struct perf_evsel *evsel,
+                             struct perf_target *target,
+                             int err, char *msg, size_t size)
+{
+       switch (err) {
+       case EPERM:
+       case EACCES:
+               return scnprintf(msg, size, "%s",
+                "You may not have permission to collect %sstats.\n"
+                "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
+                " -1 - Not paranoid at all\n"
+                "  0 - Disallow raw tracepoint access for unpriv\n"
+                "  1 - Disallow cpu events for unpriv\n"
+                "  2 - Disallow kernel profiling for unpriv",
+                                target->system_wide ? "system-wide " : "");
+       case ENOENT:
+               return scnprintf(msg, size, "The %s event is not supported.",
+                                perf_evsel__name(evsel));
+       case EMFILE:
+               return scnprintf(msg, size, "%s",
+                        "Too many events are opened.\n"
+                        "Try again after reducing the number of events.");
+       case ENODEV:
+               if (target->cpu_list)
+                       return scnprintf(msg, size, "%s",
+        "No such device - did you specify an out-of-range profile CPU?\n");
+               break;
+       case EOPNOTSUPP:
+               if (evsel->attr.precise_ip)
+                       return scnprintf(msg, size, "%s",
+       "\'precise\' request may not be supported. Try removing 'p' modifier.");
+#if defined(__i386__) || defined(__x86_64__)
+               if (evsel->attr.type == PERF_TYPE_HARDWARE)
+                       return scnprintf(msg, size, "%s",
+       "No hardware sampling interrupt available.\n"
+       "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
+#endif
+               break;
+       default:
+               break;
+       }
+
+       return scnprintf(msg, size,
+       "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).  \n"
+       "/bin/dmesg may provide additional information.\n"
+       "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
+                        err, strerror(err), perf_evsel__name(evsel));
+}
index 3d2b8017438c372f69458a2a39301c3bdf70425b..52021c3087dfe23b777544164a3ffa7492b70e57 100644 (file)
@@ -53,6 +53,7 @@ struct perf_evsel {
        struct xyarray          *sample_id;
        u64                     *id;
        struct perf_counts      *counts;
+       struct perf_counts      *prev_raw_counts;
        int                     idx;
        u32                     ids;
        struct hists            hists;
@@ -73,10 +74,13 @@ struct perf_evsel {
        bool                    needs_swap;
        /* parse modifier helper */
        int                     exclude_GH;
+       int                     nr_members;
        struct perf_evsel       *leader;
        char                    *group_name;
 };
 
+#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
+
 struct cpu_map;
 struct thread_map;
 struct perf_evlist;
@@ -110,14 +114,30 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
                                            char *bf, size_t size);
 const char *perf_evsel__name(struct perf_evsel *evsel);
+const char *perf_evsel__group_name(struct perf_evsel *evsel);
+int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
 void perf_evsel__free_fd(struct perf_evsel *evsel);
 void perf_evsel__free_id(struct perf_evsel *evsel);
+void perf_evsel__free_counts(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
+void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+                                 enum perf_event_sample_format bit);
+void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+                                   enum perf_event_sample_format bit);
+
+#define perf_evsel__set_sample_bit(evsel, bit) \
+       __perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit)
+
+#define perf_evsel__reset_sample_bit(evsel, bit) \
+       __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)
+
+void perf_evsel__set_sample_id(struct perf_evsel *evsel);
+
 int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
                           const char *filter);
 
@@ -226,8 +246,34 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
        return list_entry(evsel->node.next, struct perf_evsel, node);
 }
 
-static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel)
+static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
+{
+       return evsel->leader == evsel;
+}
+
+struct perf_attr_details {
+       bool freq;
+       bool verbose;
+       bool event_group;
+};
+
+int perf_evsel__fprintf(struct perf_evsel *evsel,
+                       struct perf_attr_details *details, FILE *fp);
+
+bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
+                         char *msg, size_t msgsize);
+int perf_evsel__open_strerror(struct perf_evsel *evsel,
+                             struct perf_target *target,
+                             int err, char *msg, size_t size);
+
+static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
 {
-       return evsel->leader != NULL;
+       return evsel->idx - evsel->leader->idx;
 }
+
+#define for_each_group_member(_evsel, _leader)                                         \
+for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node);     \
+     (_evsel) && (_evsel)->leader == (_leader);                                        \
+     (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
+
 #endif /* __PERF_EVSEL_H */
index b7da4634a047af37ffb261319b74792bdd5d337c..f4bfd79ef6a7e04aded216bb2c0540ce1dd17deb 100644 (file)
@@ -148,7 +148,7 @@ static char *do_read_string(int fd, struct perf_header *ph)
        u32 len;
        char *buf;
 
-       sz = read(fd, &len, sizeof(len));
+       sz = readn(fd, &len, sizeof(len));
        if (sz < (ssize_t)sizeof(len))
                return NULL;
 
@@ -159,7 +159,7 @@ static char *do_read_string(int fd, struct perf_header *ph)
        if (!buf)
                return NULL;
 
-       ret = read(fd, buf, len);
+       ret = readn(fd, buf, len);
        if (ret == (ssize_t)len) {
                /*
                 * strings are padded by zeroes
@@ -287,12 +287,12 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
        struct perf_session *session = container_of(header,
                        struct perf_session, header);
        struct rb_node *nd;
-       int err = machine__write_buildid_table(&session->host_machine, fd);
+       int err = machine__write_buildid_table(&session->machines.host, fd);
 
        if (err)
                return err;
 
-       for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                err = machine__write_buildid_table(pos, fd);
                if (err)
@@ -313,7 +313,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
        if (is_kallsyms) {
                if (symbol_conf.kptr_restrict) {
                        pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
-                       return 0;
+                       err = 0;
+                       goto out_free;
                }
                realname = (char *) name;
        } else
@@ -448,9 +449,9 @@ static int perf_session__cache_build_ids(struct perf_session *session)
        if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
                return -1;
 
-       ret = machine__cache_build_ids(&session->host_machine, debugdir);
+       ret = machine__cache_build_ids(&session->machines.host, debugdir);
 
-       for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                ret |= machine__cache_build_ids(pos, debugdir);
        }
@@ -467,9 +468,9 @@ static bool machine__read_build_ids(struct machine *machine, bool with_hits)
 static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
 {
        struct rb_node *nd;
-       bool ret = machine__read_build_ids(&session->host_machine, with_hits);
+       bool ret = machine__read_build_ids(&session->machines.host, with_hits);
 
-       for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                ret |= machine__read_build_ids(pos, with_hits);
        }
@@ -954,6 +955,7 @@ static int write_topo_node(int fd, int node)
        }
 
        fclose(fp);
+       fp = NULL;
 
        ret = do_write(fd, &mem_total, sizeof(u64));
        if (ret)
@@ -980,7 +982,8 @@ static int write_topo_node(int fd, int node)
        ret = do_write_string(fd, buf);
 done:
        free(buf);
-       fclose(fp);
+       if (fp)
+               fclose(fp);
        return ret;
 }
 
@@ -1051,16 +1054,25 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
        struct perf_pmu *pmu = NULL;
        off_t offset = lseek(fd, 0, SEEK_CUR);
        __u32 pmu_num = 0;
+       int ret;
 
        /* write real pmu_num later */
-       do_write(fd, &pmu_num, sizeof(pmu_num));
+       ret = do_write(fd, &pmu_num, sizeof(pmu_num));
+       if (ret < 0)
+               return ret;
 
        while ((pmu = perf_pmu__scan(pmu))) {
                if (!pmu->name)
                        continue;
                pmu_num++;
-               do_write(fd, &pmu->type, sizeof(pmu->type));
-               do_write_string(fd, pmu->name);
+
+               ret = do_write(fd, &pmu->type, sizeof(pmu->type));
+               if (ret < 0)
+                       return ret;
+
+               ret = do_write_string(fd, pmu->name);
+               if (ret < 0)
+                       return ret;
        }
 
        if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
@@ -1072,6 +1084,52 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
        return 0;
 }
 
+/*
+ * File format:
+ *
+ * struct group_descs {
+ *     u32     nr_groups;
+ *     struct group_desc {
+ *             char    name[];
+ *             u32     leader_idx;
+ *             u32     nr_members;
+ *     }[nr_groups];
+ * };
+ */
+static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
+                           struct perf_evlist *evlist)
+{
+       u32 nr_groups = evlist->nr_groups;
+       struct perf_evsel *evsel;
+       int ret;
+
+       ret = do_write(fd, &nr_groups, sizeof(nr_groups));
+       if (ret < 0)
+               return ret;
+
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               if (perf_evsel__is_group_leader(evsel) &&
+                   evsel->nr_members > 1) {
+                       const char *name = evsel->group_name ?: "{anon_group}";
+                       u32 leader_idx = evsel->idx;
+                       u32 nr_members = evsel->nr_members;
+
+                       ret = do_write_string(fd, name);
+                       if (ret < 0)
+                               return ret;
+
+                       ret = do_write(fd, &leader_idx, sizeof(leader_idx));
+                       if (ret < 0)
+                               return ret;
+
+                       ret = do_write(fd, &nr_members, sizeof(nr_members));
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+       return 0;
+}
+
 /*
  * default get_cpuid(): nothing gets recorded
  * actual implementation must be in arch/$(ARCH)/util/header.c
@@ -1209,14 +1267,14 @@ read_event_desc(struct perf_header *ph, int fd)
        size_t msz;
 
        /* number of events */
-       ret = read(fd, &nre, sizeof(nre));
+       ret = readn(fd, &nre, sizeof(nre));
        if (ret != (ssize_t)sizeof(nre))
                goto error;
 
        if (ph->needs_swap)
                nre = bswap_32(nre);
 
-       ret = read(fd, &sz, sizeof(sz));
+       ret = readn(fd, &sz, sizeof(sz));
        if (ret != (ssize_t)sizeof(sz))
                goto error;
 
@@ -1244,7 +1302,7 @@ read_event_desc(struct perf_header *ph, int fd)
                 * must read entire on-file attr struct to
                 * sync up with layout.
                 */
-               ret = read(fd, buf, sz);
+               ret = readn(fd, buf, sz);
                if (ret != (ssize_t)sz)
                        goto error;
 
@@ -1253,7 +1311,7 @@ read_event_desc(struct perf_header *ph, int fd)
 
                memcpy(&evsel->attr, buf, msz);
 
-               ret = read(fd, &nr, sizeof(nr));
+               ret = readn(fd, &nr, sizeof(nr));
                if (ret != (ssize_t)sizeof(nr))
                        goto error;
 
@@ -1274,7 +1332,7 @@ read_event_desc(struct perf_header *ph, int fd)
                evsel->id = id;
 
                for (j = 0 ; j < nr; j++) {
-                       ret = read(fd, id, sizeof(*id));
+                       ret = readn(fd, id, sizeof(*id));
                        if (ret != (ssize_t)sizeof(*id))
                                goto error;
                        if (ph->needs_swap)
@@ -1435,6 +1493,31 @@ error:
        fprintf(fp, "# pmu mappings: unable to read\n");
 }
 
+static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
+                            FILE *fp)
+{
+       struct perf_session *session;
+       struct perf_evsel *evsel;
+       u32 nr = 0;
+
+       session = container_of(ph, struct perf_session, header);
+
+       list_for_each_entry(evsel, &session->evlist->entries, node) {
+               if (perf_evsel__is_group_leader(evsel) &&
+                   evsel->nr_members > 1) {
+                       fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
+                               perf_evsel__name(evsel));
+
+                       nr = evsel->nr_members - 1;
+               } else if (nr) {
+                       fprintf(fp, ",%s", perf_evsel__name(evsel));
+
+                       if (--nr == 0)
+                               fprintf(fp, "}\n");
+               }
+       }
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
                                    char *filename,
                                    struct perf_session *session)
@@ -1506,14 +1589,14 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
        while (offset < limit) {
                ssize_t len;
 
-               if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
+               if (readn(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
                        return -1;
 
                if (header->needs_swap)
                        perf_event_header__bswap(&old_bev.header);
 
                len = old_bev.header.size - sizeof(old_bev);
-               if (read(input, filename, len) != len)
+               if (readn(input, filename, len) != len)
                        return -1;
 
                bev.header = old_bev.header;
@@ -1548,14 +1631,14 @@ static int perf_header__read_build_ids(struct perf_header *header,
        while (offset < limit) {
                ssize_t len;
 
-               if (read(input, &bev, sizeof(bev)) != sizeof(bev))
+               if (readn(input, &bev, sizeof(bev)) != sizeof(bev))
                        goto out;
 
                if (header->needs_swap)
                        perf_event_header__bswap(&bev.header);
 
                len = bev.header.size - sizeof(bev);
-               if (read(input, filename, len) != len)
+               if (readn(input, filename, len) != len)
                        goto out;
                /*
                 * The a1645ce1 changeset:
@@ -1641,7 +1724,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
        size_t ret;
        u32 nr;
 
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                return -1;
 
@@ -1650,7 +1733,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
 
        ph->env.nr_cpus_online = nr;
 
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                return -1;
 
@@ -1684,7 +1767,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused,
        uint64_t mem;
        size_t ret;
 
-       ret = read(fd, &mem, sizeof(mem));
+       ret = readn(fd, &mem, sizeof(mem));
        if (ret != sizeof(mem))
                return -1;
 
@@ -1756,7 +1839,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
        u32 nr, i;
        struct strbuf sb;
 
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                return -1;
 
@@ -1792,7 +1875,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
        char *str;
        struct strbuf sb;
 
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                return -1;
 
@@ -1813,7 +1896,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
        }
        ph->env.sibling_cores = strbuf_detach(&sb, NULL);
 
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                return -1;
 
@@ -1850,7 +1933,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
        struct strbuf sb;
 
        /* nr nodes */
-       ret = read(fd, &nr, sizeof(nr));
+       ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
                goto error;
 
@@ -1862,15 +1945,15 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
 
        for (i = 0; i < nr; i++) {
                /* node number */
-               ret = read(fd, &node, sizeof(node));
+               ret = readn(fd, &node, sizeof(node));
                if (ret != sizeof(node))
                        goto error;
 
-               ret = read(fd, &mem_total, sizeof(u64));
+               ret = readn(fd, &mem_total, sizeof(u64));
                if (ret != sizeof(u64))
                        goto error;
 
-               ret = read(fd, &mem_free, sizeof(u64));
+               ret = readn(fd, &mem_free, sizeof(u64));
                if (ret != sizeof(u64))
                        goto error;
 
@@ -1909,7 +1992,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
        u32 type;
        struct strbuf sb;
 
-       ret = read(fd, &pmu_num, sizeof(pmu_num));
+       ret = readn(fd, &pmu_num, sizeof(pmu_num));
        if (ret != sizeof(pmu_num))
                return -1;
 
@@ -1925,7 +2008,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
        strbuf_init(&sb, 128);
 
        while (pmu_num) {
-               if (read(fd, &type, sizeof(type)) != sizeof(type))
+               if (readn(fd, &type, sizeof(type)) != sizeof(type))
                        goto error;
                if (ph->needs_swap)
                        type = bswap_32(type);
@@ -1949,6 +2032,98 @@ error:
        return -1;
 }
 
+static int process_group_desc(struct perf_file_section *section __maybe_unused,
+                             struct perf_header *ph, int fd,
+                             void *data __maybe_unused)
+{
+       size_t ret = -1;
+       u32 i, nr, nr_groups;
+       struct perf_session *session;
+       struct perf_evsel *evsel, *leader = NULL;
+       struct group_desc {
+               char *name;
+               u32 leader_idx;
+               u32 nr_members;
+       } *desc;
+
+       if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
+               return -1;
+
+       if (ph->needs_swap)
+               nr_groups = bswap_32(nr_groups);
+
+       ph->env.nr_groups = nr_groups;
+       if (!nr_groups) {
+               pr_debug("group desc not available\n");
+               return 0;
+       }
+
+       desc = calloc(nr_groups, sizeof(*desc));
+       if (!desc)
+               return -1;
+
+       for (i = 0; i < nr_groups; i++) {
+               desc[i].name = do_read_string(fd, ph);
+               if (!desc[i].name)
+                       goto out_free;
+
+               if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32))
+                       goto out_free;
+
+               if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32))
+                       goto out_free;
+
+               if (ph->needs_swap) {
+                       desc[i].leader_idx = bswap_32(desc[i].leader_idx);
+                       desc[i].nr_members = bswap_32(desc[i].nr_members);
+               }
+       }
+
+       /*
+        * Rebuild group relationship based on the group_desc
+        */
+       session = container_of(ph, struct perf_session, header);
+       session->evlist->nr_groups = nr_groups;
+
+       i = nr = 0;
+       list_for_each_entry(evsel, &session->evlist->entries, node) {
+               if (evsel->idx == (int) desc[i].leader_idx) {
+                       evsel->leader = evsel;
+                       /* {anon_group} is a dummy name */
+                       if (strcmp(desc[i].name, "{anon_group}"))
+                               evsel->group_name = desc[i].name;
+                       evsel->nr_members = desc[i].nr_members;
+
+                       if (i >= nr_groups || nr > 0) {
+                               pr_debug("invalid group desc\n");
+                               goto out_free;
+                       }
+
+                       leader = evsel;
+                       nr = evsel->nr_members - 1;
+                       i++;
+               } else if (nr) {
+                       /* This is a group member */
+                       evsel->leader = leader;
+
+                       nr--;
+               }
+       }
+
+       if (i != nr_groups || nr != 0) {
+               pr_debug("invalid group desc\n");
+               goto out_free;
+       }
+
+       ret = 0;
+out_free:
+       while ((int) --i >= 0)
+               free(desc[i].name);
+       free(desc);
+
+       return ret;
+}
+
 struct feature_ops {
        int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
        void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1988,6 +2163,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
        FEAT_OPF(HEADER_NUMA_TOPOLOGY,  numa_topology),
        FEAT_OPA(HEADER_BRANCH_STACK,   branch_stack),
        FEAT_OPP(HEADER_PMU_MAPPINGS,   pmu_mappings),
+       FEAT_OPP(HEADER_GROUP_DESC,     group_desc),
 };
 
 struct header_print_data {
@@ -2077,7 +2253,7 @@ static int perf_header__adds_write(struct perf_header *header,
        if (!nr_sections)
                return 0;
 
-       feat_sec = p = calloc(sizeof(*feat_sec), nr_sections);
+       feat_sec = p = calloc(nr_sections, sizeof(*feat_sec));
        if (feat_sec == NULL)
                return -ENOMEM;
 
@@ -2249,7 +2425,7 @@ int perf_header__process_sections(struct perf_header *header, int fd,
        if (!nr_sections)
                return 0;
 
-       feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections);
+       feat_sec = sec = calloc(nr_sections, sizeof(*feat_sec));
        if (!feat_sec)
                return -1;
 
@@ -2912,16 +3088,22 @@ int perf_event__process_tracing_data(union perf_event *event,
                                 session->repipe);
        padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
 
-       if (read(session->fd, buf, padding) < 0)
-               die("reading input file");
+       if (readn(session->fd, buf, padding) < 0) {
+               pr_err("%s: reading input file", __func__);
+               return -1;
+       }
        if (session->repipe) {
                int retw = write(STDOUT_FILENO, buf, padding);
-               if (retw <= 0 || retw != padding)
-                       die("repiping tracing data padding");
+               if (retw <= 0 || retw != padding) {
+                       pr_err("%s: repiping tracing data padding", __func__);
+                       return -1;
+               }
        }
 
-       if (size_read + padding != size)
-               die("tracing data size mismatch");
+       if (size_read + padding != size) {
+               pr_err("%s: tracing data size mismatch", __func__);
+               return -1;
+       }
 
        perf_evlist__prepare_tracepoint_events(session->evlist,
                                               session->pevent);
index 20f0344accb1918e88946d70994cfab13a9c371a..c9fc55cada6d1ceaf04c001f40bc9c052ef566ff 100644 (file)
@@ -29,6 +29,7 @@ enum {
        HEADER_NUMA_TOPOLOGY,
        HEADER_BRANCH_STACK,
        HEADER_PMU_MAPPINGS,
+       HEADER_GROUP_DESC,
        HEADER_LAST_FEATURE,
        HEADER_FEAT_BITS        = 256,
 };
@@ -79,6 +80,7 @@ struct perf_session_env {
        char                    *numa_nodes;
        int                     nr_pmu_mappings;
        char                    *pmu_mappings;
+       int                     nr_groups;
 };
 
 struct perf_header {
index cb17e2a8c6ed49d95929984b3147178b3c02da5d..f855941bebea0afa369137d72306c86e5904a7bd 100644 (file)
@@ -4,6 +4,7 @@
 #include "hist.h"
 #include "session.h"
 #include "sort.h"
+#include "evsel.h"
 #include <math.h>
 
 static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -82,6 +83,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
                hists__new_col_len(hists, HISTC_DSO, len);
        }
 
+       if (h->parent)
+               hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);
+
        if (h->branch_info) {
                int symlen;
                /*
@@ -242,6 +246,14 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
 
                if (he->ms.map)
                        he->ms.map->referenced = true;
+
+               if (he->branch_info) {
+                       if (he->branch_info->from.map)
+                               he->branch_info->from.map->referenced = true;
+                       if (he->branch_info->to.map)
+                               he->branch_info->to.map->referenced = true;
+               }
+
                if (symbol_conf.use_callchain)
                        callchain_init(he->callchain);
 
@@ -251,7 +263,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
        return he;
 }
 
-static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
+void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
 {
        if (!h->filtered) {
                hists__calc_col_len(hists, h);
@@ -285,7 +297,13 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                parent = *p;
                he = rb_entry(parent, struct hist_entry, rb_node_in);
 
-               cmp = hist_entry__cmp(entry, he);
+               /*
+                * Make sure that it receives arguments in a same order as
+                * hist_entry__collapse() so that we can use an appropriate
+                * function when searching an entry regardless which sort
+                * keys were used.
+                */
+               cmp = hist_entry__cmp(he, entry);
 
                if (!cmp) {
                        he_stat__add_period(&he->stat, period);
@@ -523,6 +541,62 @@ void hists__collapse_resort_threaded(struct hists *hists)
  * reverse the map, sort on period.
  */
 
+static int period_cmp(u64 period_a, u64 period_b)
+{
+       if (period_a > period_b)
+               return 1;
+       if (period_a < period_b)
+               return -1;
+       return 0;
+}
+
+static int hist_entry__sort_on_period(struct hist_entry *a,
+                                     struct hist_entry *b)
+{
+       int ret;
+       int i, nr_members;
+       struct perf_evsel *evsel;
+       struct hist_entry *pair;
+       u64 *periods_a, *periods_b;
+
+       ret = period_cmp(a->stat.period, b->stat.period);
+       if (ret || !symbol_conf.event_group)
+               return ret;
+
+       evsel = hists_to_evsel(a->hists);
+       nr_members = evsel->nr_members;
+       if (nr_members <= 1)
+               return ret;
+
+       periods_a = zalloc(sizeof(periods_a) * nr_members);
+       periods_b = zalloc(sizeof(periods_b) * nr_members);
+
+       if (!periods_a || !periods_b)
+               goto out;
+
+       list_for_each_entry(pair, &a->pairs.head, pairs.node) {
+               evsel = hists_to_evsel(pair->hists);
+               periods_a[perf_evsel__group_idx(evsel)] = pair->stat.period;
+       }
+
+       list_for_each_entry(pair, &b->pairs.head, pairs.node) {
+               evsel = hists_to_evsel(pair->hists);
+               periods_b[perf_evsel__group_idx(evsel)] = pair->stat.period;
+       }
+
+       for (i = 1; i < nr_members; i++) {
+               ret = period_cmp(periods_a[i], periods_b[i]);
+               if (ret)
+                       break;
+       }
+
+out:
+       free(periods_a);
+       free(periods_b);
+
+       return ret;
+}
+
 static void __hists__insert_output_entry(struct rb_root *entries,
                                         struct hist_entry *he,
                                         u64 min_callchain_hits)
@@ -539,7 +613,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
                parent = *p;
                iter = rb_entry(parent, struct hist_entry, rb_node);
 
-               if (he->stat.period > iter->stat.period)
+               if (hist_entry__sort_on_period(he, iter) > 0)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -711,25 +785,38 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
        return symbol__annotate(he->ms.sym, he->ms.map, privsize);
 }
 
+void events_stats__inc(struct events_stats *stats, u32 type)
+{
+       ++stats->nr_events[0];
+       ++stats->nr_events[type];
+}
+
 void hists__inc_nr_events(struct hists *hists, u32 type)
 {
-       ++hists->stats.nr_events[0];
-       ++hists->stats.nr_events[type];
+       events_stats__inc(&hists->stats, type);
 }
 
 static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
                                                 struct hist_entry *pair)
 {
-       struct rb_node **p = &hists->entries.rb_node;
+       struct rb_root *root;
+       struct rb_node **p;
        struct rb_node *parent = NULL;
        struct hist_entry *he;
        int cmp;
 
+       if (sort__need_collapse)
+               root = &hists->entries_collapsed;
+       else
+               root = hists->entries_in;
+
+       p = &root->rb_node;
+
        while (*p != NULL) {
                parent = *p;
-               he = rb_entry(parent, struct hist_entry, rb_node);
+               he = rb_entry(parent, struct hist_entry, rb_node_in);
 
-               cmp = hist_entry__cmp(pair, he);
+               cmp = hist_entry__collapse(he, pair);
 
                if (!cmp)
                        goto out;
@@ -744,8 +831,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
        if (he) {
                memset(&he->stat, 0, sizeof(he->stat));
                he->hists = hists;
-               rb_link_node(&he->rb_node, parent, p);
-               rb_insert_color(&he->rb_node, &hists->entries);
+               rb_link_node(&he->rb_node_in, parent, p);
+               rb_insert_color(&he->rb_node_in, root);
                hists__inc_nr_entries(hists, he);
        }
 out:
@@ -755,11 +842,16 @@ out:
 static struct hist_entry *hists__find_entry(struct hists *hists,
                                            struct hist_entry *he)
 {
-       struct rb_node *n = hists->entries.rb_node;
+       struct rb_node *n;
+
+       if (sort__need_collapse)
+               n = hists->entries_collapsed.rb_node;
+       else
+               n = hists->entries_in->rb_node;
 
        while (n) {
-               struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
-               int64_t cmp = hist_entry__cmp(he, iter);
+               struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in);
+               int64_t cmp = hist_entry__collapse(iter, he);
 
                if (cmp < 0)
                        n = n->rb_left;
@@ -777,15 +869,21 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
  */
 void hists__match(struct hists *leader, struct hists *other)
 {
+       struct rb_root *root;
        struct rb_node *nd;
        struct hist_entry *pos, *pair;
 
-       for (nd = rb_first(&leader->entries); nd; nd = rb_next(nd)) {
-               pos  = rb_entry(nd, struct hist_entry, rb_node);
+       if (sort__need_collapse)
+               root = &leader->entries_collapsed;
+       else
+               root = leader->entries_in;
+
+       for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+               pos  = rb_entry(nd, struct hist_entry, rb_node_in);
                pair = hists__find_entry(other, pos);
 
                if (pair)
-                       hist__entry_add_pair(pos, pair);
+                       hist_entry__add_pair(pair, pos);
        }
 }
 
@@ -796,17 +894,23 @@ void hists__match(struct hists *leader, struct hists *other)
  */
 int hists__link(struct hists *leader, struct hists *other)
 {
+       struct rb_root *root;
        struct rb_node *nd;
        struct hist_entry *pos, *pair;
 
-       for (nd = rb_first(&other->entries); nd; nd = rb_next(nd)) {
-               pos = rb_entry(nd, struct hist_entry, rb_node);
+       if (sort__need_collapse)
+               root = &other->entries_collapsed;
+       else
+               root = other->entries_in;
+
+       for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+               pos = rb_entry(nd, struct hist_entry, rb_node_in);
 
                if (!hist_entry__has_pairs(pos)) {
                        pair = hists__add_dummy_entry(leader, pos);
                        if (pair == NULL)
                                return -1;
-                       hist__entry_add_pair(pair, pos);
+                       hist_entry__add_pair(pos, pair);
                }
        }
 
index 8b091a51e4a265361f6dc0cdab2b93567bf79943..38624686ee9a145ffaacbcfa063e5d985da750f0 100644 (file)
@@ -96,8 +96,10 @@ void hists__decay_entries_threaded(struct hists *hists, bool zap_user,
                                   bool zap_kernel);
 void hists__output_recalc_col_len(struct hists *hists, int max_rows);
 
+void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
 void hists__inc_nr_events(struct hists *self, u32 type);
-size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
+void events_stats__inc(struct events_stats *stats, u32 type);
+size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
 
 size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
                      int max_cols, FILE *fp);
@@ -126,13 +128,19 @@ struct perf_hpp {
 };
 
 struct perf_hpp_fmt {
-       bool cond;
        int (*header)(struct perf_hpp *hpp);
        int (*width)(struct perf_hpp *hpp);
        int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
        int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
+
+       struct list_head list;
 };
 
+extern struct list_head perf_hpp__list;
+
+#define perf_hpp__for_each_format(format) \
+       list_for_each_entry(format, &perf_hpp__list, list)
+
 extern struct perf_hpp_fmt perf_hpp__format[];
 
 enum {
@@ -148,14 +156,14 @@ enum {
        PERF_HPP__DELTA,
        PERF_HPP__RATIO,
        PERF_HPP__WEIGHTED_DIFF,
-       PERF_HPP__DISPL,
        PERF_HPP__FORMULA,
 
        PERF_HPP__MAX_INDEX
 };
 
 void perf_hpp__init(void);
-void perf_hpp__column_enable(unsigned col, bool enable);
+void perf_hpp__column_register(struct perf_hpp_fmt *format);
+void perf_hpp__column_enable(unsigned col);
 int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
                                bool color);
 
@@ -219,8 +227,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 
 unsigned int hists__sort_list_width(struct hists *self);
 
-double perf_diff__compute_delta(struct hist_entry *he);
-double perf_diff__compute_ratio(struct hist_entry *he);
-s64 perf_diff__compute_wdiff(struct hist_entry *he);
-int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
+double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
+double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
+s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
+int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
+                      char *buf, size_t size);
+double perf_diff__period_percent(struct hist_entry *he, u64 period);
 #endif /* __PERF_HIST_H */
index a55d8cf083c98ed4a237a25e1a3844be02673466..45cf10a562bd7958c9edd160ab20a0725ecb0385 100644 (file)
@@ -14,6 +14,7 @@
 #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #define BITS_TO_U64(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
 #define BITS_TO_U32(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
+#define BITS_TO_BYTES(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE)
 
 #define for_each_set_bit(bit, addr, size) \
        for ((bit) = find_first_bit((addr), (size));            \
index 9d0740024ba88550c5db5329babd7e5238abe3b2..11a8d86f7fea3bf4ec5fb8cb05f27dc4c491d948 100644 (file)
@@ -59,16 +59,40 @@ void intlist__remove(struct intlist *ilist, struct int_node *node)
 
 struct int_node *intlist__find(struct intlist *ilist, int i)
 {
-       struct int_node *node = NULL;
-       struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
+       struct int_node *node;
+       struct rb_node *rb_node;
 
+       if (ilist == NULL)
+               return NULL;
+
+       node = NULL;
+       rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
        if (rb_node)
                node = container_of(rb_node, struct int_node, rb_node);
 
        return node;
 }
 
-struct intlist *intlist__new(void)
+static int intlist__parse_list(struct intlist *ilist, const char *s)
+{
+       char *sep;
+       int err;
+
+       do {
+               long value = strtol(s, &sep, 10);
+               err = -EINVAL;
+               if (*sep != ',' && *sep != '\0')
+                       break;
+               err = intlist__add(ilist, value);
+               if (err)
+                       break;
+               s = sep + 1;
+       } while (*sep != '\0');
+
+       return err;
+}
+
+struct intlist *intlist__new(const char *slist)
 {
        struct intlist *ilist = malloc(sizeof(*ilist));
 
@@ -77,9 +101,15 @@ struct intlist *intlist__new(void)
                ilist->rblist.node_cmp    = intlist__node_cmp;
                ilist->rblist.node_new    = intlist__node_new;
                ilist->rblist.node_delete = intlist__node_delete;
+
+               if (slist && intlist__parse_list(ilist, slist))
+                       goto out_delete;
        }
 
        return ilist;
+out_delete:
+       intlist__delete(ilist);
+       return NULL;
 }
 
 void intlist__delete(struct intlist *ilist)
index 6d63ab90db508e29fd7b1e8affdaae3bd7d9f401..62351dad848f76c478cced833c315cc71ff1ed63 100644 (file)
@@ -15,7 +15,7 @@ struct intlist {
        struct rblist rblist;
 };
 
-struct intlist *intlist__new(void);
+struct intlist *intlist__new(const char *slist);
 void intlist__delete(struct intlist *ilist);
 
 void intlist__remove(struct intlist *ilist, struct int_node *in);
index 1f09d0581e6b021e37ba5d97f27e5e2b592e6c05..efdb38e65a92f75c0addc2ee16817c28ab07731b 100644 (file)
@@ -1,10 +1,15 @@
+#include "callchain.h"
 #include "debug.h"
 #include "event.h"
+#include "evsel.h"
+#include "hist.h"
 #include "machine.h"
 #include "map.h"
+#include "sort.h"
 #include "strlist.h"
 #include "thread.h"
 #include <stdbool.h>
+#include "unwind.h"
 
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
 {
@@ -48,6 +53,29 @@ static void dsos__delete(struct list_head *dsos)
        }
 }
 
+void machine__delete_dead_threads(struct machine *machine)
+{
+       struct thread *n, *t;
+
+       list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
+               list_del(&t->node);
+               thread__delete(t);
+       }
+}
+
+void machine__delete_threads(struct machine *machine)
+{
+       struct rb_node *nd = rb_first(&machine->threads);
+
+       while (nd) {
+               struct thread *t = rb_entry(nd, struct thread, rb_node);
+
+               rb_erase(&t->rb_node, &machine->threads);
+               nd = rb_next(nd);
+               thread__delete(t);
+       }
+}
+
 void machine__exit(struct machine *machine)
 {
        map_groups__exit(&machine->kmaps);
@@ -63,10 +91,22 @@ void machine__delete(struct machine *machine)
        free(machine);
 }
 
-struct machine *machines__add(struct rb_root *machines, pid_t pid,
+void machines__init(struct machines *machines)
+{
+       machine__init(&machines->host, "", HOST_KERNEL_ID);
+       machines->guests = RB_ROOT;
+}
+
+void machines__exit(struct machines *machines)
+{
+       machine__exit(&machines->host);
+       /* XXX exit guest */
+}
+
+struct machine *machines__add(struct machines *machines, pid_t pid,
                              const char *root_dir)
 {
-       struct rb_node **p = &machines->rb_node;
+       struct rb_node **p = &machines->guests.rb_node;
        struct rb_node *parent = NULL;
        struct machine *pos, *machine = malloc(sizeof(*machine));
 
@@ -88,18 +128,21 @@ struct machine *machines__add(struct rb_root *machines, pid_t pid,
        }
 
        rb_link_node(&machine->rb_node, parent, p);
-       rb_insert_color(&machine->rb_node, machines);
+       rb_insert_color(&machine->rb_node, &machines->guests);
 
        return machine;
 }
 
-struct machine *machines__find(struct rb_root *machines, pid_t pid)
+struct machine *machines__find(struct machines *machines, pid_t pid)
 {
-       struct rb_node **p = &machines->rb_node;
+       struct rb_node **p = &machines->guests.rb_node;
        struct rb_node *parent = NULL;
        struct machine *machine;
        struct machine *default_machine = NULL;
 
+       if (pid == HOST_KERNEL_ID)
+               return &machines->host;
+
        while (*p != NULL) {
                parent = *p;
                machine = rb_entry(parent, struct machine, rb_node);
@@ -116,7 +159,7 @@ struct machine *machines__find(struct rb_root *machines, pid_t pid)
        return default_machine;
 }
 
-struct machine *machines__findnew(struct rb_root *machines, pid_t pid)
+struct machine *machines__findnew(struct machines *machines, pid_t pid)
 {
        char path[PATH_MAX];
        const char *root_dir = "";
@@ -150,12 +193,12 @@ out:
        return machine;
 }
 
-void machines__process(struct rb_root *machines,
-                      machine__process_t process, void *data)
+void machines__process_guests(struct machines *machines,
+                             machine__process_t process, void *data)
 {
        struct rb_node *nd;
 
-       for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
                process(pos, data);
        }
@@ -175,12 +218,14 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
        return bf;
 }
 
-void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size)
+void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
 {
        struct rb_node *node;
        struct machine *machine;
 
-       for (node = rb_first(machines); node; node = rb_next(node)) {
+       machines->host.id_hdr_size = id_hdr_size;
+
+       for (node = rb_first(&machines->guests); node; node = rb_next(node)) {
                machine = rb_entry(node, struct machine, rb_node);
                machine->id_hdr_size = id_hdr_size;
        }
@@ -264,6 +309,537 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
        return 0;
 }
 
+struct map *machine__new_module(struct machine *machine, u64 start,
+                               const char *filename)
+{
+       struct map *map;
+       struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
+
+       if (dso == NULL)
+               return NULL;
+
+       map = map__new2(start, dso, MAP__FUNCTION);
+       if (map == NULL)
+               return NULL;
+
+       if (machine__is_host(machine))
+               dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
+       else
+               dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+       map_groups__insert(&machine->kmaps, map);
+       return map;
+}
+
+size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
+{
+       struct rb_node *nd;
+       size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) +
+                    __dsos__fprintf(&machines->host.user_dsos, fp);
+
+       for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+               ret += __dsos__fprintf(&pos->kernel_dsos, fp);
+               ret += __dsos__fprintf(&pos->user_dsos, fp);
+       }
+
+       return ret;
+}
+
+size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
+                                    bool (skip)(struct dso *dso, int parm), int parm)
+{
+       return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
+              __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
+}
+
+size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
+                                    bool (skip)(struct dso *dso, int parm), int parm)
+{
+       struct rb_node *nd;
+       size_t ret = machine__fprintf_dsos_buildid(&machines->host, fp, skip, parm);
+
+       for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+               ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
+       }
+       return ret;
+}
+
+size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
+{
+       int i;
+       size_t printed = 0;
+       struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
+
+       if (kdso->has_build_id) {
+               char filename[PATH_MAX];
+               if (dso__build_id_filename(kdso, filename, sizeof(filename)))
+                       printed += fprintf(fp, "[0] %s\n", filename);
+       }
+
+       for (i = 0; i < vmlinux_path__nr_entries; ++i)
+               printed += fprintf(fp, "[%d] %s\n",
+                                  i + kdso->has_build_id, vmlinux_path[i]);
+
+       return printed;
+}
+
+size_t machine__fprintf(struct machine *machine, FILE *fp)
+{
+       size_t ret = 0;
+       struct rb_node *nd;
+
+       for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
+               struct thread *pos = rb_entry(nd, struct thread, rb_node);
+
+               ret += thread__fprintf(pos, fp);
+       }
+
+       return ret;
+}
+
+static struct dso *machine__get_kernel(struct machine *machine)
+{
+       const char *vmlinux_name = NULL;
+       struct dso *kernel;
+
+       if (machine__is_host(machine)) {
+               vmlinux_name = symbol_conf.vmlinux_name;
+               if (!vmlinux_name)
+                       vmlinux_name = "[kernel.kallsyms]";
+
+               kernel = dso__kernel_findnew(machine, vmlinux_name,
+                                            "[kernel]",
+                                            DSO_TYPE_KERNEL);
+       } else {
+               char bf[PATH_MAX];
+
+               if (machine__is_default_guest(machine))
+                       vmlinux_name = symbol_conf.default_guest_vmlinux_name;
+               if (!vmlinux_name)
+                       vmlinux_name = machine__mmap_name(machine, bf,
+                                                         sizeof(bf));
+
+               kernel = dso__kernel_findnew(machine, vmlinux_name,
+                                            "[guest.kernel]",
+                                            DSO_TYPE_GUEST_KERNEL);
+       }
+
+       if (kernel != NULL && (!kernel->has_build_id))
+               dso__read_running_kernel_build_id(kernel, machine);
+
+       return kernel;
+}
+
+struct process_args {
+       u64 start;
+};
+
+static int symbol__in_kernel(void *arg, const char *name,
+                            char type __maybe_unused, u64 start)
+{
+       struct process_args *args = arg;
+
+       if (strchr(name, '['))
+               return 0;
+
+       args->start = start;
+       return 1;
+}
+
+/* Figure out the start address of kernel map from /proc/kallsyms */
+static u64 machine__get_kernel_start_addr(struct machine *machine)
+{
+       const char *filename;
+       char path[PATH_MAX];
+       struct process_args args;
+
+       if (machine__is_host(machine)) {
+               filename = "/proc/kallsyms";
+       } else {
+               if (machine__is_default_guest(machine))
+                       filename = (char *)symbol_conf.default_guest_kallsyms;
+               else {
+                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
+                       filename = path;
+               }
+       }
+
+       if (symbol__restricted_filename(filename, "/proc/kallsyms"))
+               return 0;
+
+       if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
+               return 0;
+
+       return args.start;
+}
+
+int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
+{
+       enum map_type type;
+       u64 start = machine__get_kernel_start_addr(machine);
+
+       for (type = 0; type < MAP__NR_TYPES; ++type) {
+               struct kmap *kmap;
+
+               machine->vmlinux_maps[type] = map__new2(start, kernel, type);
+               if (machine->vmlinux_maps[type] == NULL)
+                       return -1;
+
+               machine->vmlinux_maps[type]->map_ip =
+                       machine->vmlinux_maps[type]->unmap_ip =
+                               identity__map_ip;
+               kmap = map__kmap(machine->vmlinux_maps[type]);
+               kmap->kmaps = &machine->kmaps;
+               map_groups__insert(&machine->kmaps,
+                                  machine->vmlinux_maps[type]);
+       }
+
+       return 0;
+}
+
+void machine__destroy_kernel_maps(struct machine *machine)
+{
+       enum map_type type;
+
+       for (type = 0; type < MAP__NR_TYPES; ++type) {
+               struct kmap *kmap;
+
+               if (machine->vmlinux_maps[type] == NULL)
+                       continue;
+
+               kmap = map__kmap(machine->vmlinux_maps[type]);
+               map_groups__remove(&machine->kmaps,
+                                  machine->vmlinux_maps[type]);
+               if (kmap->ref_reloc_sym) {
+                       /*
+                        * ref_reloc_sym is shared among all maps, so free just
+                        * on one of them.
+                        */
+                       if (type == MAP__FUNCTION) {
+                               free((char *)kmap->ref_reloc_sym->name);
+                               kmap->ref_reloc_sym->name = NULL;
+                               free(kmap->ref_reloc_sym);
+                       }
+                       kmap->ref_reloc_sym = NULL;
+               }
+
+               map__delete(machine->vmlinux_maps[type]);
+               machine->vmlinux_maps[type] = NULL;
+       }
+}
+
+int machines__create_guest_kernel_maps(struct machines *machines)
+{
+       int ret = 0;
+       struct dirent **namelist = NULL;
+       int i, items = 0;
+       char path[PATH_MAX];
+       pid_t pid;
+       char *endp;
+
+       if (symbol_conf.default_guest_vmlinux_name ||
+           symbol_conf.default_guest_modules ||
+           symbol_conf.default_guest_kallsyms) {
+               machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
+       }
+
+       if (symbol_conf.guestmount) {
+               items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
+               if (items <= 0)
+                       return -ENOENT;
+               for (i = 0; i < items; i++) {
+                       if (!isdigit(namelist[i]->d_name[0])) {
+                               /* Filter out . and .. */
+                               continue;
+                       }
+                       pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
+                       if ((*endp != '\0') ||
+                           (endp == namelist[i]->d_name) ||
+                           (errno == ERANGE)) {
+                               pr_debug("invalid directory (%s). Skipping.\n",
+                                        namelist[i]->d_name);
+                               continue;
+                       }
+                       sprintf(path, "%s/%s/proc/kallsyms",
+                               symbol_conf.guestmount,
+                               namelist[i]->d_name);
+                       ret = access(path, R_OK);
+                       if (ret) {
+                               pr_debug("Can't access file %s\n", path);
+                               goto failure;
+                       }
+                       machines__create_kernel_maps(machines, pid);
+               }
+failure:
+               free(namelist);
+       }
+
+       return ret;
+}
+
+void machines__destroy_kernel_maps(struct machines *machines)
+{
+       struct rb_node *next = rb_first(&machines->guests);
+
+       machine__destroy_kernel_maps(&machines->host);
+
+       while (next) {
+               struct machine *pos = rb_entry(next, struct machine, rb_node);
+
+               next = rb_next(&pos->rb_node);
+               rb_erase(&pos->rb_node, &machines->guests);
+               machine__delete(pos);
+       }
+}
+
+int machines__create_kernel_maps(struct machines *machines, pid_t pid)
+{
+       struct machine *machine = machines__findnew(machines, pid);
+
+       if (machine == NULL)
+               return -1;
+
+       return machine__create_kernel_maps(machine);
+}
+
+int machine__load_kallsyms(struct machine *machine, const char *filename,
+                          enum map_type type, symbol_filter_t filter)
+{
+       struct map *map = machine->vmlinux_maps[type];
+       int ret = dso__load_kallsyms(map->dso, filename, map, filter);
+
+       if (ret > 0) {
+               dso__set_loaded(map->dso, type);
+               /*
+                * Since /proc/kallsyms will have multiple sessions for the
+                * kernel, with modules between them, fixup the end of all
+                * sections.
+                */
+               __map_groups__fixup_end(&machine->kmaps, type);
+       }
+
+       return ret;
+}
+
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
+                              symbol_filter_t filter)
+{
+       struct map *map = machine->vmlinux_maps[type];
+       int ret = dso__load_vmlinux_path(map->dso, map, filter);
+
+       if (ret > 0) {
+               dso__set_loaded(map->dso, type);
+               map__reloc_vmlinux(map);
+       }
+
+       return ret;
+}
+
+static void map_groups__fixup_end(struct map_groups *mg)
+{
+       int i;
+       for (i = 0; i < MAP__NR_TYPES; ++i)
+               __map_groups__fixup_end(mg, i);
+}
+
+static char *get_kernel_version(const char *root_dir)
+{
+       char version[PATH_MAX];
+       FILE *file;
+       char *name, *tmp;
+       const char *prefix = "Linux version ";
+
+       sprintf(version, "%s/proc/version", root_dir);
+       file = fopen(version, "r");
+       if (!file)
+               return NULL;
+
+       version[0] = '\0';
+       tmp = fgets(version, sizeof(version), file);
+       fclose(file);
+
+       name = strstr(version, prefix);
+       if (!name)
+               return NULL;
+       name += strlen(prefix);
+       tmp = strchr(name, ' ');
+       if (tmp)
+               *tmp = '\0';
+
+       return strdup(name);
+}
+
+static int map_groups__set_modules_path_dir(struct map_groups *mg,
+                               const char *dir_name)
+{
+       struct dirent *dent;
+       DIR *dir = opendir(dir_name);
+       int ret = 0;
+
+       if (!dir) {
+               pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
+               return -1;
+       }
+
+       while ((dent = readdir(dir)) != NULL) {
+               char path[PATH_MAX];
+               struct stat st;
+
+               /*sshfs might return bad dent->d_type, so we have to stat*/
+               snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
+               if (stat(path, &st))
+                       continue;
+
+               if (S_ISDIR(st.st_mode)) {
+                       if (!strcmp(dent->d_name, ".") ||
+                           !strcmp(dent->d_name, ".."))
+                               continue;
+
+                       ret = map_groups__set_modules_path_dir(mg, path);
+                       if (ret < 0)
+                               goto out;
+               } else {
+                       char *dot = strrchr(dent->d_name, '.'),
+                            dso_name[PATH_MAX];
+                       struct map *map;
+                       char *long_name;
+
+                       if (dot == NULL || strcmp(dot, ".ko"))
+                               continue;
+                       snprintf(dso_name, sizeof(dso_name), "[%.*s]",
+                                (int)(dot - dent->d_name), dent->d_name);
+
+                       strxfrchar(dso_name, '-', '_');
+                       map = map_groups__find_by_name(mg, MAP__FUNCTION,
+                                                      dso_name);
+                       if (map == NULL)
+                               continue;
+
+                       long_name = strdup(path);
+                       if (long_name == NULL) {
+                               ret = -1;
+                               goto out;
+                       }
+                       dso__set_long_name(map->dso, long_name);
+                       map->dso->lname_alloc = 1;
+                       dso__kernel_module_get_build_id(map->dso, "");
+               }
+       }
+
+out:
+       closedir(dir);
+       return ret;
+}
+
+static int machine__set_modules_path(struct machine *machine)
+{
+       char *version;
+       char modules_path[PATH_MAX];
+
+       version = get_kernel_version(machine->root_dir);
+       if (!version)
+               return -1;
+
+       snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
+                machine->root_dir, version);
+       free(version);
+
+       return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
+}
+
+static int machine__create_modules(struct machine *machine)
+{
+       char *line = NULL;
+       size_t n;
+       FILE *file;
+       struct map *map;
+       const char *modules;
+       char path[PATH_MAX];
+
+       if (machine__is_default_guest(machine))
+               modules = symbol_conf.default_guest_modules;
+       else {
+               sprintf(path, "%s/proc/modules", machine->root_dir);
+               modules = path;
+       }
+
+       if (symbol__restricted_filename(path, "/proc/modules"))
+               return -1;
+
+       file = fopen(modules, "r");
+       if (file == NULL)
+               return -1;
+
+       while (!feof(file)) {
+               char name[PATH_MAX];
+               u64 start;
+               char *sep;
+               int line_len;
+
+               line_len = getline(&line, &n, file);
+               if (line_len < 0)
+                       break;
+
+               if (!line)
+                       goto out_failure;
+
+               line[--line_len] = '\0'; /* \n */
+
+               sep = strrchr(line, 'x');
+               if (sep == NULL)
+                       continue;
+
+               hex2u64(sep + 1, &start);
+
+               sep = strchr(line, ' ');
+               if (sep == NULL)
+                       continue;
+
+               *sep = '\0';
+
+               snprintf(name, sizeof(name), "[%s]", line);
+               map = machine__new_module(machine, start, name);
+               if (map == NULL)
+                       goto out_delete_line;
+               dso__kernel_module_get_build_id(map->dso, machine->root_dir);
+       }
+
+       free(line);
+       fclose(file);
+
+       return machine__set_modules_path(machine);
+
+out_delete_line:
+       free(line);
+out_failure:
+       return -1;
+}
+
+int machine__create_kernel_maps(struct machine *machine)
+{
+       struct dso *kernel = machine__get_kernel(machine);
+
+       if (kernel == NULL ||
+           __machine__create_kernel_maps(machine, kernel) < 0)
+               return -1;
+
+       if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
+               if (machine__is_host(machine))
+                       pr_debug("Problems creating module maps, "
+                                "continuing anyway...\n");
+               else
+                       pr_debug("Problems creating module maps for guest %d, "
+                                "continuing anyway...\n", machine->pid);
+       }
+
+       /*
+        * Now that we have all the maps created, just set the ->end of them:
+        */
+       map_groups__fixup_end(&machine->kmaps);
+       return 0;
+}
+
 static void machine__set_kernel_mmap_len(struct machine *machine,
                                         union perf_event *event)
 {
@@ -462,3 +1038,189 @@ int machine__process_event(struct machine *machine, union perf_event *event)
 
        return ret;
 }
+
+void machine__remove_thread(struct machine *machine, struct thread *th)
+{
+       machine->last_match = NULL;
+       rb_erase(&th->rb_node, &machine->threads);
+       /*
+        * We may have references to this thread, for instance in some hist_entry
+        * instances, so just move them to a separate list.
+        */
+       list_add_tail(&th->node, &machine->dead_threads);
+}
+
+static bool symbol__match_parent_regex(struct symbol *sym)
+{
+       if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
+               return 1;
+
+       return 0;
+}
+
+static const u8 cpumodes[] = {
+       PERF_RECORD_MISC_USER,
+       PERF_RECORD_MISC_KERNEL,
+       PERF_RECORD_MISC_GUEST_USER,
+       PERF_RECORD_MISC_GUEST_KERNEL
+};
+#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
+
+static void ip__resolve_ams(struct machine *machine, struct thread *thread,
+                           struct addr_map_symbol *ams,
+                           u64 ip)
+{
+       struct addr_location al;
+       size_t i;
+       u8 m;
+
+       memset(&al, 0, sizeof(al));
+
+       for (i = 0; i < NCPUMODES; i++) {
+               m = cpumodes[i];
+               /*
+                * We cannot use the header.misc hint to determine whether a
+                * branch stack address is user, kernel, guest, hypervisor.
+                * Branches may straddle the kernel/user/hypervisor boundaries.
+                * Thus, we have to try consecutively until we find a match
+                * or else, the symbol is unknown
+                */
+               thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
+                               ip, &al, NULL);
+               if (al.sym)
+                       goto found;
+       }
+found:
+       ams->addr = ip;
+       ams->al_addr = al.addr;
+       ams->sym = al.sym;
+       ams->map = al.map;
+}
+
+struct branch_info *machine__resolve_bstack(struct machine *machine,
+                                           struct thread *thr,
+                                           struct branch_stack *bs)
+{
+       struct branch_info *bi;
+       unsigned int i;
+
+       bi = calloc(bs->nr, sizeof(struct branch_info));
+       if (!bi)
+               return NULL;
+
+       for (i = 0; i < bs->nr; i++) {
+               ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
+               ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
+               bi[i].flags = bs->entries[i].flags;
+       }
+       return bi;
+}
+
+static int machine__resolve_callchain_sample(struct machine *machine,
+                                            struct thread *thread,
+                                            struct ip_callchain *chain,
+                                            struct symbol **parent)
+
+{
+       u8 cpumode = PERF_RECORD_MISC_USER;
+       unsigned int i;
+       int err;
+
+       callchain_cursor_reset(&callchain_cursor);
+
+       if (chain->nr > PERF_MAX_STACK_DEPTH) {
+               pr_warning("corrupted callchain. skipping...\n");
+               return 0;
+       }
+
+       for (i = 0; i < chain->nr; i++) {
+               u64 ip;
+               struct addr_location al;
+
+               if (callchain_param.order == ORDER_CALLEE)
+                       ip = chain->ips[i];
+               else
+                       ip = chain->ips[chain->nr - i - 1];
+
+               if (ip >= PERF_CONTEXT_MAX) {
+                       switch (ip) {
+                       case PERF_CONTEXT_HV:
+                               cpumode = PERF_RECORD_MISC_HYPERVISOR;
+                               break;
+                       case PERF_CONTEXT_KERNEL:
+                               cpumode = PERF_RECORD_MISC_KERNEL;
+                               break;
+                       case PERF_CONTEXT_USER:
+                               cpumode = PERF_RECORD_MISC_USER;
+                               break;
+                       default:
+                               pr_debug("invalid callchain context: "
+                                        "%"PRId64"\n", (s64) ip);
+                               /*
+                                * It seems the callchain is corrupted.
+                                * Discard all.
+                                */
+                               callchain_cursor_reset(&callchain_cursor);
+                               return 0;
+                       }
+                       continue;
+               }
+
+               al.filtered = false;
+               thread__find_addr_location(thread, machine, cpumode,
+                                          MAP__FUNCTION, ip, &al, NULL);
+               if (al.sym != NULL) {
+                       if (sort__has_parent && !*parent &&
+                           symbol__match_parent_regex(al.sym))
+                               *parent = al.sym;
+                       if (!symbol_conf.use_callchain)
+                               break;
+               }
+
+               err = callchain_cursor_append(&callchain_cursor,
+                                             ip, al.map, al.sym);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int unwind_entry(struct unwind_entry *entry, void *arg)
+{
+       struct callchain_cursor *cursor = arg;
+       return callchain_cursor_append(cursor, entry->ip,
+                                      entry->map, entry->sym);
+}
+
+int machine__resolve_callchain(struct machine *machine,
+                              struct perf_evsel *evsel,
+                              struct thread *thread,
+                              struct perf_sample *sample,
+                              struct symbol **parent)
+
+{
+       int ret;
+
+       callchain_cursor_reset(&callchain_cursor);
+
+       ret = machine__resolve_callchain_sample(machine, thread,
+                                               sample->callchain, parent);
+       if (ret)
+               return ret;
+
+       /* Can we do dwarf post unwind? */
+       if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
+             (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
+               return 0;
+
+       /* Bail out if nothing was captured. */
+       if ((!sample->user_regs.regs) ||
+           (!sample->user_stack.size))
+               return 0;
+
+       return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
+                                  thread, evsel->attr.sample_regs_user,
+                                  sample);
+
+}
index b7cde7467d55018f82c254bf8d6cf49cf70db30e..5ac5892f23264a76c39b092c0b4933fd95a9779c 100644 (file)
@@ -47,23 +47,32 @@ int machine__process_event(struct machine *machine, union perf_event *event);
 
 typedef void (*machine__process_t)(struct machine *machine, void *data);
 
-void machines__process(struct rb_root *machines,
-                      machine__process_t process, void *data);
+struct machines {
+       struct machine host;
+       struct rb_root guests;
+};
+
+void machines__init(struct machines *machines);
+void machines__exit(struct machines *machines);
 
-struct machine *machines__add(struct rb_root *machines, pid_t pid,
+void machines__process_guests(struct machines *machines,
+                             machine__process_t process, void *data);
+
+struct machine *machines__add(struct machines *machines, pid_t pid,
                              const char *root_dir);
-struct machine *machines__find_host(struct rb_root *machines);
-struct machine *machines__find(struct rb_root *machines, pid_t pid);
-struct machine *machines__findnew(struct rb_root *machines, pid_t pid);
+struct machine *machines__find_host(struct machines *machines);
+struct machine *machines__find(struct machines *machines, pid_t pid);
+struct machine *machines__findnew(struct machines *machines, pid_t pid);
 
-void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size);
+void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
 char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
 
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
 void machine__exit(struct machine *machine);
+void machine__delete_dead_threads(struct machine *machine);
+void machine__delete_threads(struct machine *machine);
 void machine__delete(struct machine *machine);
 
-
 struct branch_info *machine__resolve_bstack(struct machine *machine,
                                            struct thread *thread,
                                            struct branch_stack *bs);
@@ -129,19 +138,19 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
 int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
                               symbol_filter_t filter);
 
-size_t machine__fprintf_dsos_buildid(struct machine *machine,
-                                    FILE *fp, bool with_hits);
-size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
-size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
-                                     FILE *fp, bool with_hits);
+size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
+                                    bool (skip)(struct dso *dso, int parm), int parm);
+size_t machines__fprintf_dsos(struct machines *machines, FILE *fp);
+size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
+                                    bool (skip)(struct dso *dso, int parm), int parm);
 
 void machine__destroy_kernel_maps(struct machine *machine);
 int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
 int machine__create_kernel_maps(struct machine *machine);
 
-int machines__create_kernel_maps(struct rb_root *machines, pid_t pid);
-int machines__create_guest_kernel_maps(struct rb_root *machines);
-void machines__destroy_guest_kernel_maps(struct rb_root *machines);
+int machines__create_kernel_maps(struct machines *machines, pid_t pid);
+int machines__create_guest_kernel_maps(struct machines *machines);
+void machines__destroy_kernel_maps(struct machines *machines);
 
 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
 
index 0328d45c4f2af4571785812b32b94bd692ad36e1..6fcb9de623401b8ac731c3c240eb1cd5863683f4 100644 (file)
@@ -11,6 +11,7 @@
 #include "strlist.h"
 #include "vdso.h"
 #include "build-id.h"
+#include <linux/string.h>
 
 const char *map_type__name[MAP__NR_TYPES] = {
        [MAP__FUNCTION] = "Functions",
@@ -19,7 +20,8 @@ const char *map_type__name[MAP__NR_TYPES] = {
 
 static inline int is_anon_memory(const char *filename)
 {
-       return strcmp(filename, "//anon") == 0;
+       return !strcmp(filename, "//anon") ||
+              !strcmp(filename, "/anon_hugepage (deleted)");
 }
 
 static inline int is_no_dso_memory(const char *filename)
@@ -28,29 +30,29 @@ static inline int is_no_dso_memory(const char *filename)
               !strcmp(filename, "[heap]");
 }
 
-void map__init(struct map *self, enum map_type type,
+void map__init(struct map *map, enum map_type type,
               u64 start, u64 end, u64 pgoff, struct dso *dso)
 {
-       self->type     = type;
-       self->start    = start;
-       self->end      = end;
-       self->pgoff    = pgoff;
-       self->dso      = dso;
-       self->map_ip   = map__map_ip;
-       self->unmap_ip = map__unmap_ip;
-       RB_CLEAR_NODE(&self->rb_node);
-       self->groups   = NULL;
-       self->referenced = false;
-       self->erange_warned = false;
+       map->type     = type;
+       map->start    = start;
+       map->end      = end;
+       map->pgoff    = pgoff;
+       map->dso      = dso;
+       map->map_ip   = map__map_ip;
+       map->unmap_ip = map__unmap_ip;
+       RB_CLEAR_NODE(&map->rb_node);
+       map->groups   = NULL;
+       map->referenced = false;
+       map->erange_warned = false;
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
                     u64 pgoff, u32 pid, char *filename,
                     enum map_type type)
 {
-       struct map *self = malloc(sizeof(*self));
+       struct map *map = malloc(sizeof(*map));
 
-       if (self != NULL) {
+       if (map != NULL) {
                char newfilename[PATH_MAX];
                struct dso *dso;
                int anon, no_dso, vdso;
@@ -73,10 +75,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
                if (dso == NULL)
                        goto out_delete;
 
-               map__init(self, type, start, start + len, pgoff, dso);
+               map__init(map, type, start, start + len, pgoff, dso);
 
                if (anon || no_dso) {
-                       self->map_ip = self->unmap_ip = identity__map_ip;
+                       map->map_ip = map->unmap_ip = identity__map_ip;
 
                        /*
                         * Set memory without DSO as loaded. All map__find_*
@@ -84,12 +86,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
                         * unnecessary map__load warning.
                         */
                        if (no_dso)
-                               dso__set_loaded(dso, self->type);
+                               dso__set_loaded(dso, map->type);
                }
        }
-       return self;
+       return map;
 out_delete:
-       free(self);
+       free(map);
        return NULL;
 }
 
@@ -112,48 +114,48 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
        return map;
 }
 
-void map__delete(struct map *self)
+void map__delete(struct map *map)
 {
-       free(self);
+       free(map);
 }
 
-void map__fixup_start(struct map *self)
+void map__fixup_start(struct map *map)
 {
-       struct rb_root *symbols = &self->dso->symbols[self->type];
+       struct rb_root *symbols = &map->dso->symbols[map->type];
        struct rb_node *nd = rb_first(symbols);
        if (nd != NULL) {
                struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
-               self->start = sym->start;
+               map->start = sym->start;
        }
 }
 
-void map__fixup_end(struct map *self)
+void map__fixup_end(struct map *map)
 {
-       struct rb_root *symbols = &self->dso->symbols[self->type];
+       struct rb_root *symbols = &map->dso->symbols[map->type];
        struct rb_node *nd = rb_last(symbols);
        if (nd != NULL) {
                struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
-               self->end = sym->end;
+               map->end = sym->end;
        }
 }
 
 #define DSO__DELETED "(deleted)"
 
-int map__load(struct map *self, symbol_filter_t filter)
+int map__load(struct map *map, symbol_filter_t filter)
 {
-       const char *name = self->dso->long_name;
+       const char *name = map->dso->long_name;
        int nr;
 
-       if (dso__loaded(self->dso, self->type))
+       if (dso__loaded(map->dso, map->type))
                return 0;
 
-       nr = dso__load(self->dso, self, filter);
+       nr = dso__load(map->dso, map, filter);
        if (nr < 0) {
-               if (self->dso->has_build_id) {
+               if (map->dso->has_build_id) {
                        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 
-                       build_id__sprintf(self->dso->build_id,
-                                         sizeof(self->dso->build_id),
+                       build_id__sprintf(map->dso->build_id,
+                                         sizeof(map->dso->build_id),
                                          sbuild_id);
                        pr_warning("%s with build id %s not found",
                                   name, sbuild_id);
@@ -183,43 +185,36 @@ int map__load(struct map *self, symbol_filter_t filter)
         * Only applies to the kernel, as its symtabs aren't relative like the
         * module ones.
         */
-       if (self->dso->kernel)
-               map__reloc_vmlinux(self);
+       if (map->dso->kernel)
+               map__reloc_vmlinux(map);
 
        return 0;
 }
 
-struct symbol *map__find_symbol(struct map *self, u64 addr,
+struct symbol *map__find_symbol(struct map *map, u64 addr,
                                symbol_filter_t filter)
 {
-       if (map__load(self, filter) < 0)
+       if (map__load(map, filter) < 0)
                return NULL;
 
-       return dso__find_symbol(self->dso, self->type, addr);
+       return dso__find_symbol(map->dso, map->type, addr);
 }
 
-struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
                                        symbol_filter_t filter)
 {
-       if (map__load(self, filter) < 0)
+       if (map__load(map, filter) < 0)
                return NULL;
 
-       if (!dso__sorted_by_name(self->dso, self->type))
-               dso__sort_by_name(self->dso, self->type);
+       if (!dso__sorted_by_name(map->dso, map->type))
+               dso__sort_by_name(map->dso, map->type);
 
-       return dso__find_symbol_by_name(self->dso, self->type, name);
+       return dso__find_symbol_by_name(map->dso, map->type, name);
 }
 
-struct map *map__clone(struct map *self)
+struct map *map__clone(struct map *map)
 {
-       struct map *map = malloc(sizeof(*self));
-
-       if (!map)
-               return NULL;
-
-       memcpy(map, self, sizeof(*self));
-
-       return map;
+       return memdup(map, sizeof(*map));
 }
 
 int map__overlap(struct map *l, struct map *r)
@@ -236,10 +231,10 @@ int map__overlap(struct map *l, struct map *r)
        return 0;
 }
 
-size_t map__fprintf(struct map *self, FILE *fp)
+size_t map__fprintf(struct map *map, FILE *fp)
 {
        return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
-                      self->start, self->end, self->pgoff, self->dso->name);
+                      map->start, map->end, map->pgoff, map->dso->name);
 }
 
 size_t map__fprintf_dsoname(struct map *map, FILE *fp)
@@ -527,9 +522,9 @@ static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
        return ip - (s64)map->pgoff;
 }
 
-void map__reloc_vmlinux(struct map *self)
+void map__reloc_vmlinux(struct map *map)
 {
-       struct kmap *kmap = map__kmap(self);
+       struct kmap *kmap = map__kmap(map);
        s64 reloc;
 
        if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
@@ -541,9 +536,9 @@ void map__reloc_vmlinux(struct map *self)
        if (!reloc)
                return;
 
-       self->map_ip   = map__reloc_map_ip;
-       self->unmap_ip = map__reloc_unmap_ip;
-       self->pgoff    = reloc;
+       map->map_ip   = map__reloc_map_ip;
+       map->unmap_ip = map__reloc_unmap_ip;
+       map->pgoff    = reloc;
 }
 
 void maps__insert(struct rb_root *maps, struct map *map)
@@ -566,9 +561,9 @@ void maps__insert(struct rb_root *maps, struct map *map)
        rb_insert_color(&map->rb_node, maps);
 }
 
-void maps__remove(struct rb_root *self, struct map *map)
+void maps__remove(struct rb_root *maps, struct map *map)
 {
-       rb_erase(&map->rb_node, self);
+       rb_erase(&map->rb_node, maps);
 }
 
 struct map *maps__find(struct rb_root *maps, u64 ip)
index bcb39e2a69651fed82758f5fea299f4d4dda2f41..a887f2c9dfbb0248d89640ea9609cabdc8907849 100644 (file)
@@ -57,9 +57,9 @@ struct map_groups {
        struct machine   *machine;
 };
 
-static inline struct kmap *map__kmap(struct map *self)
+static inline struct kmap *map__kmap(struct map *map)
 {
-       return (struct kmap *)(self + 1);
+       return (struct kmap *)(map + 1);
 }
 
 static inline u64 map__map_ip(struct map *map, u64 ip)
@@ -85,27 +85,27 @@ struct symbol;
 
 typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
 
-void map__init(struct map *self, enum map_type type,
+void map__init(struct map *map, enum map_type type,
               u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
                     u64 pgoff, u32 pid, char *filename,
                     enum map_type type);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
-void map__delete(struct map *self);
-struct map *map__clone(struct map *self);
+void map__delete(struct map *map);
+struct map *map__clone(struct map *map);
 int map__overlap(struct map *l, struct map *r);
-size_t map__fprintf(struct map *self, FILE *fp);
+size_t map__fprintf(struct map *map, FILE *fp);
 size_t map__fprintf_dsoname(struct map *map, FILE *fp);
 
-int map__load(struct map *self, symbol_filter_t filter);
-struct symbol *map__find_symbol(struct map *self,
+int map__load(struct map *map, symbol_filter_t filter);
+struct symbol *map__find_symbol(struct map *map,
                                u64 addr, symbol_filter_t filter);
-struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
                                        symbol_filter_t filter);
-void map__fixup_start(struct map *self);
-void map__fixup_end(struct map *self);
+void map__fixup_start(struct map *map);
+void map__fixup_end(struct map *map);
 
-void map__reloc_vmlinux(struct map *self);
+void map__reloc_vmlinux(struct map *map);
 
 size_t __map_groups__fprintf_maps(struct map_groups *mg,
                                  enum map_type type, int verbose, FILE *fp);
index 2d8d53bec17e35dd58f1eced0a710f48980f2ec2..c84f48cf96782e900064d1ff7d277477bcd5919e 100644 (file)
@@ -380,8 +380,8 @@ static int add_tracepoint(struct list_head **listp, int *idx,
        return 0;
 }
 
-static int add_tracepoint_multi(struct list_head **list, int *idx,
-                               char *sys_name, char *evt_name)
+static int add_tracepoint_multi_event(struct list_head **list, int *idx,
+                                     char *sys_name, char *evt_name)
 {
        char evt_path[MAXPATHLEN];
        struct dirent *evt_ent;
@@ -408,6 +408,47 @@ static int add_tracepoint_multi(struct list_head **list, int *idx,
                ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
        }
 
+       closedir(evt_dir);
+       return ret;
+}
+
+static int add_tracepoint_event(struct list_head **list, int *idx,
+                               char *sys_name, char *evt_name)
+{
+       return strpbrk(evt_name, "*?") ?
+              add_tracepoint_multi_event(list, idx, sys_name, evt_name) :
+              add_tracepoint(list, idx, sys_name, evt_name);
+}
+
+static int add_tracepoint_multi_sys(struct list_head **list, int *idx,
+                                   char *sys_name, char *evt_name)
+{
+       struct dirent *events_ent;
+       DIR *events_dir;
+       int ret = 0;
+
+       events_dir = opendir(tracing_events_path);
+       if (!events_dir) {
+               perror("Can't open event dir");
+               return -1;
+       }
+
+       while (!ret && (events_ent = readdir(events_dir))) {
+               if (!strcmp(events_ent->d_name, ".")
+                   || !strcmp(events_ent->d_name, "..")
+                   || !strcmp(events_ent->d_name, "enable")
+                   || !strcmp(events_ent->d_name, "header_event")
+                   || !strcmp(events_ent->d_name, "header_page"))
+                       continue;
+
+               if (!strglobmatch(events_ent->d_name, sys_name))
+                       continue;
+
+               ret = add_tracepoint_event(list, idx, events_ent->d_name,
+                                          evt_name);
+       }
+
+       closedir(events_dir);
        return ret;
 }
 
@@ -420,9 +461,10 @@ int parse_events_add_tracepoint(struct list_head **list, int *idx,
        if (ret)
                return ret;
 
-       return strpbrk(event, "*?") ?
-              add_tracepoint_multi(list, idx, sys, event) :
-              add_tracepoint(list, idx, sys, event);
+       if (strpbrk(sys, "*?"))
+               return add_tracepoint_multi_sys(list, idx, sys, event);
+       else
+               return add_tracepoint_event(list, idx, sys, event);
 }
 
 static int
@@ -492,7 +534,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
 }
 
 static int config_term(struct perf_event_attr *attr,
-                      struct parse_events__term *term)
+                      struct parse_events_term *term)
 {
 #define CHECK_TYPE_VAL(type)                                   \
 do {                                                           \
@@ -537,7 +579,7 @@ do {                                                                \
 static int config_attr(struct perf_event_attr *attr,
                       struct list_head *head, int fail)
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
        list_for_each_entry(term, head, list)
                if (config_term(attr, term) && fail)
@@ -563,14 +605,14 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
        return add_event(list, idx, &attr, NULL);
 }
 
-static int parse_events__is_name_term(struct parse_events__term *term)
+static int parse_events__is_name_term(struct parse_events_term *term)
 {
        return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
 }
 
 static char *pmu_event_name(struct list_head *head_terms)
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
        list_for_each_entry(term, head_terms, list)
                if (parse_events__is_name_term(term))
@@ -657,14 +699,6 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
        int exclude = eu | ek | eh;
        int exclude_GH = evsel ? evsel->exclude_GH : 0;
 
-       /*
-        * We are here for group and 'GH' was not set as event
-        * modifier and whatever event/group modifier override
-        * default 'GH' setup.
-        */
-       if (evsel && !exclude_GH)
-               eH = eG = 0;
-
        memset(mod, 0, sizeof(*mod));
 
        while (*str) {
@@ -814,7 +848,7 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
  */
 int parse_events_terms(struct list_head *terms, const char *str)
 {
-       struct parse_events_data__terms data = {
+       struct parse_events_terms data = {
                .terms = NULL,
        };
        int ret;
@@ -830,10 +864,9 @@ int parse_events_terms(struct list_head *terms, const char *str)
        return ret;
 }
 
-int parse_events(struct perf_evlist *evlist, const char *str,
-                int unset __maybe_unused)
+int parse_events(struct perf_evlist *evlist, const char *str)
 {
-       struct parse_events_data__events data = {
+       struct parse_events_evlist data = {
                .list = LIST_HEAD_INIT(data.list),
                .idx  = evlist->nr_entries,
        };
@@ -843,6 +876,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
        if (!ret) {
                int entries = data.idx - evlist->nr_entries;
                perf_evlist__splice_list_tail(evlist, &data.list, entries);
+               evlist->nr_groups += data.nr_groups;
                return 0;
        }
 
@@ -858,7 +892,7 @@ int parse_events_option(const struct option *opt, const char *str,
                        int unset __maybe_unused)
 {
        struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
-       int ret = parse_events(evlist, str, unset);
+       int ret = parse_events(evlist, str);
 
        if (ret) {
                fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
@@ -1121,16 +1155,16 @@ void print_events(const char *event_glob, bool name_only)
        print_tracepoint_events(NULL, NULL, name_only);
 }
 
-int parse_events__is_hardcoded_term(struct parse_events__term *term)
+int parse_events__is_hardcoded_term(struct parse_events_term *term)
 {
        return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
 }
 
-static int new_term(struct parse_events__term **_term, int type_val,
+static int new_term(struct parse_events_term **_term, int type_val,
                    int type_term, char *config,
                    char *str, u64 num)
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
        term = zalloc(sizeof(*term));
        if (!term)
@@ -1156,21 +1190,21 @@ static int new_term(struct parse_events__term **_term, int type_val,
        return 0;
 }
 
-int parse_events__term_num(struct parse_events__term **term,
+int parse_events_term__num(struct parse_events_term **term,
                           int type_term, char *config, u64 num)
 {
        return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
                        config, NULL, num);
 }
 
-int parse_events__term_str(struct parse_events__term **term,
+int parse_events_term__str(struct parse_events_term **term,
                           int type_term, char *config, char *str)
 {
        return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
                        config, str, 0);
 }
 
-int parse_events__term_sym_hw(struct parse_events__term **term,
+int parse_events_term__sym_hw(struct parse_events_term **term,
                              char *config, unsigned idx)
 {
        struct event_symbol *sym;
@@ -1188,8 +1222,8 @@ int parse_events__term_sym_hw(struct parse_events__term **term,
                                (char *) "event", (char *) sym->symbol, 0);
 }
 
-int parse_events__term_clone(struct parse_events__term **new,
-                            struct parse_events__term *term)
+int parse_events_term__clone(struct parse_events_term **new,
+                            struct parse_events_term *term)
 {
        return new_term(new, term->type_val, term->type_term, term->config,
                        term->val.str, term->val.num);
@@ -1197,7 +1231,7 @@ int parse_events__term_clone(struct parse_events__term **new,
 
 void parse_events__free_terms(struct list_head *terms)
 {
-       struct parse_events__term *term, *h;
+       struct parse_events_term *term, *h;
 
        list_for_each_entry_safe(term, h, terms, list)
                free(term);
index b7af80b8bdda188842a35d81e0a66e4d01a18c4c..8a4859315fd97266fa592ea775d993b9c003a48d 100644 (file)
@@ -29,8 +29,7 @@ const char *event_type(int type);
 
 extern int parse_events_option(const struct option *opt, const char *str,
                               int unset);
-extern int parse_events(struct perf_evlist *evlist, const char *str,
-                       int unset);
+extern int parse_events(struct perf_evlist *evlist, const char *str);
 extern int parse_events_terms(struct list_head *terms, const char *str);
 extern int parse_filter(const struct option *opt, const char *str, int unset);
 
@@ -51,7 +50,7 @@ enum {
        PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
 };
 
-struct parse_events__term {
+struct parse_events_term {
        char *config;
        union {
                char *str;
@@ -62,24 +61,25 @@ struct parse_events__term {
        struct list_head list;
 };
 
-struct parse_events_data__events {
+struct parse_events_evlist {
        struct list_head list;
        int idx;
+       int nr_groups;
 };
 
-struct parse_events_data__terms {
+struct parse_events_terms {
        struct list_head *terms;
 };
 
-int parse_events__is_hardcoded_term(struct parse_events__term *term);
-int parse_events__term_num(struct parse_events__term **_term,
+int parse_events__is_hardcoded_term(struct parse_events_term *term);
+int parse_events_term__num(struct parse_events_term **_term,
                           int type_term, char *config, u64 num);
-int parse_events__term_str(struct parse_events__term **_term,
+int parse_events_term__str(struct parse_events_term **_term,
                           int type_term, char *config, char *str);
-int parse_events__term_sym_hw(struct parse_events__term **term,
+int parse_events_term__sym_hw(struct parse_events_term **term,
                              char *config, unsigned idx);
-int parse_events__term_clone(struct parse_events__term **new,
-                            struct parse_events__term *term);
+int parse_events_term__clone(struct parse_events_term **new,
+                            struct parse_events_term *term);
 void parse_events__free_terms(struct list_head *terms);
 int parse_events__modifier_event(struct list_head *list, char *str, bool add);
 int parse_events__modifier_group(struct list_head *list, char *event_mod);
index 0f9914ae6bacb0b801650cb1c9449852b8a0ff1f..afc44c18dfe17b054fe01e10c779dbe747373558 100644 (file)
@@ -1,5 +1,4 @@
 %pure-parser
-%name-prefix "parse_events_"
 %parse-param {void *_data}
 %parse-param {void *scanner}
 %lex-param {void* scanner}
@@ -23,6 +22,14 @@ do { \
                YYABORT; \
 } while (0)
 
+static inc_group_count(struct list_head *list,
+                      struct parse_events_evlist *data)
+{
+       /* Count groups only have more than 1 members */
+       if (!list_is_last(list->next, list))
+               data->nr_groups++;
+}
+
 %}
 
 %token PE_START_EVENTS PE_START_TERMS
@@ -68,7 +75,7 @@ do { \
        char *str;
        u64 num;
        struct list_head *head;
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 }
 %%
 
@@ -79,7 +86,7 @@ PE_START_TERMS  start_terms
 
 start_events: groups
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
 
        parse_events_update_lists($1, &data->list);
 }
@@ -123,6 +130,7 @@ PE_NAME '{' events '}'
 {
        struct list_head *list = $3;
 
+       inc_group_count(list, _data);
        parse_events__set_leader($1, list);
        $$ = list;
 }
@@ -131,6 +139,7 @@ PE_NAME '{' events '}'
 {
        struct list_head *list = $2;
 
+       inc_group_count(list, _data);
        parse_events__set_leader(NULL, list);
        $$ = list;
 }
@@ -186,7 +195,7 @@ event_def: event_pmu |
 event_pmu:
 PE_NAME '/' event_config '/'
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
@@ -202,7 +211,7 @@ PE_VALUE_SYM_SW
 event_legacy_symbol:
 value_sym '/' event_config '/'
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
@@ -215,7 +224,7 @@ value_sym '/' event_config '/'
 |
 value_sym sep_slash_dc
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
@@ -228,7 +237,7 @@ value_sym sep_slash_dc
 event_legacy_cache:
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
@@ -237,7 +246,7 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
 |
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
@@ -246,7 +255,7 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
 |
 PE_NAME_CACHE_TYPE
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
@@ -256,7 +265,7 @@ PE_NAME_CACHE_TYPE
 event_legacy_mem:
 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
@@ -266,7 +275,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 |
 PE_PREFIX_MEM PE_VALUE sep_dc
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
@@ -277,7 +286,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
 event_legacy_tracepoint:
 PE_NAME ':' PE_NAME
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
@@ -287,7 +296,7 @@ PE_NAME ':' PE_NAME
 event_legacy_numeric:
 PE_VALUE ':' PE_VALUE
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL));
@@ -297,7 +306,7 @@ PE_VALUE ':' PE_VALUE
 event_legacy_raw:
 PE_RAW
 {
-       struct parse_events_data__events *data = _data;
+       struct parse_events_evlist *data = _data;
        struct list_head *list = NULL;
 
        ABORT_ON(parse_events_add_numeric(&list, &data->idx,
@@ -307,7 +316,7 @@ PE_RAW
 
 start_terms: event_config
 {
-       struct parse_events_data__terms *data = _data;
+       struct parse_events_terms *data = _data;
        data->terms = $1;
 }
 
@@ -315,7 +324,7 @@ event_config:
 event_config ',' event_term
 {
        struct list_head *head = $1;
-       struct parse_events__term *term = $3;
+       struct parse_events_term *term = $3;
 
        ABORT_ON(!head);
        list_add_tail(&term->list, head);
@@ -325,7 +334,7 @@ event_config ',' event_term
 event_term
 {
        struct list_head *head = malloc(sizeof(*head));
-       struct parse_events__term *term = $1;
+       struct parse_events_term *term = $1;
 
        ABORT_ON(!head);
        INIT_LIST_HEAD(head);
@@ -336,70 +345,70 @@ event_term
 event_term:
 PE_NAME '=' PE_NAME
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+       ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
                                        $1, $3));
        $$ = term;
 }
 |
 PE_NAME '=' PE_VALUE
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+       ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
                                        $1, $3));
        $$ = term;
 }
 |
 PE_NAME '=' PE_VALUE_SYM_HW
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
        int config = $3 & 255;
 
-       ABORT_ON(parse_events__term_sym_hw(&term, $1, config));
+       ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
        $$ = term;
 }
 |
 PE_NAME
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+       ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
                                        $1, 1));
        $$ = term;
 }
 |
 PE_VALUE_SYM_HW
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
        int config = $1 & 255;
 
-       ABORT_ON(parse_events__term_sym_hw(&term, NULL, config));
+       ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
        $$ = term;
 }
 |
 PE_TERM '=' PE_NAME
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_str(&term, (int)$1, NULL, $3));
+       ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3));
        $$ = term;
 }
 |
 PE_TERM '=' PE_VALUE
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, $3));
+       ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3));
        $$ = term;
 }
 |
 PE_TERM
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
-       ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, 1));
+       ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1));
        $$ = term;
 }
 
index 9bdc60c6f138240d309289c69f294d04bd60dd2a..4c6f9c490a8d79d0cc7f2367efd05440de735a7c 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <linux/list.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "parse-events.h"
 #include "cpumap.h"
 
+struct perf_pmu_alias {
+       char *name;
+       struct list_head terms;
+       struct list_head list;
+};
+
+struct perf_pmu_format {
+       char *name;
+       int value;
+       DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
+       struct list_head list;
+};
+
 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
 
 int perf_pmu_parse(struct list_head *list, char *name);
@@ -85,7 +97,7 @@ static int pmu_format(char *name, struct list_head *format)
 
 static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
 {
-       struct perf_pmu__alias *alias;
+       struct perf_pmu_alias *alias;
        char buf[256];
        int ret;
 
@@ -172,15 +184,15 @@ static int pmu_aliases(char *name, struct list_head *head)
        return 0;
 }
 
-static int pmu_alias_terms(struct perf_pmu__alias *alias,
+static int pmu_alias_terms(struct perf_pmu_alias *alias,
                           struct list_head *terms)
 {
-       struct parse_events__term *term, *clone;
+       struct parse_events_term *term, *clone;
        LIST_HEAD(list);
        int ret;
 
        list_for_each_entry(term, &alias->terms, list) {
-               ret = parse_events__term_clone(&clone, term);
+               ret = parse_events_term__clone(&clone, term);
                if (ret) {
                        parse_events__free_terms(&list);
                        return ret;
@@ -360,10 +372,10 @@ struct perf_pmu *perf_pmu__find(char *name)
        return pmu_lookup(name);
 }
 
-static struct perf_pmu__format*
+static struct perf_pmu_format *
 pmu_find_format(struct list_head *formats, char *name)
 {
-       struct perf_pmu__format *format;
+       struct perf_pmu_format *format;
 
        list_for_each_entry(format, formats, list)
                if (!strcmp(format->name, name))
@@ -403,9 +415,9 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
  */
 static int pmu_config_term(struct list_head *formats,
                           struct perf_event_attr *attr,
-                          struct parse_events__term *term)
+                          struct parse_events_term *term)
 {
-       struct perf_pmu__format *format;
+       struct perf_pmu_format *format;
        __u64 *vp;
 
        /*
@@ -450,7 +462,7 @@ int perf_pmu__config_terms(struct list_head *formats,
                           struct perf_event_attr *attr,
                           struct list_head *head_terms)
 {
-       struct parse_events__term *term;
+       struct parse_events_term *term;
 
        list_for_each_entry(term, head_terms, list)
                if (pmu_config_term(formats, attr, term))
@@ -471,10 +483,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
        return perf_pmu__config_terms(&pmu->format, attr, head_terms);
 }
 
-static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
-                                             struct parse_events__term *term)
+static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
+                                            struct parse_events_term *term)
 {
-       struct perf_pmu__alias *alias;
+       struct perf_pmu_alias *alias;
        char *name;
 
        if (parse_events__is_hardcoded_term(term))
@@ -507,8 +519,8 @@ static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
  */
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
 {
-       struct parse_events__term *term, *h;
-       struct perf_pmu__alias *alias;
+       struct parse_events_term *term, *h;
+       struct perf_pmu_alias *alias;
        int ret;
 
        list_for_each_entry_safe(term, h, head_terms, list) {
@@ -527,7 +539,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
 int perf_pmu__new_format(struct list_head *list, char *name,
                         int config, unsigned long *bits)
 {
-       struct perf_pmu__format *format;
+       struct perf_pmu_format *format;
 
        format = zalloc(sizeof(*format));
        if (!format)
@@ -548,7 +560,7 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
        if (!to)
                to = from;
 
-       memset(bits, 0, BITS_TO_LONGS(PERF_PMU_FORMAT_BITS));
+       memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
        for (b = from; b <= to; b++)
                set_bit(b, bits);
 }
index a313ed76a49a23dd7bb6d02e87104053629f561b..32fe55b659fa93ed17e921c0bed99a07b99f09f6 100644 (file)
@@ -12,19 +12,6 @@ enum {
 
 #define PERF_PMU_FORMAT_BITS 64
 
-struct perf_pmu__format {
-       char *name;
-       int value;
-       DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
-       struct list_head list;
-};
-
-struct perf_pmu__alias {
-       char *name;
-       struct list_head terms;
-       struct list_head list;
-};
-
 struct perf_pmu {
        char *name;
        __u32 type;
@@ -42,7 +29,7 @@ int perf_pmu__config_terms(struct list_head *formats,
                           struct list_head *head_terms);
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
 struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
-                               struct list_head *head_terms);
+                                 struct list_head *head_terms);
 int perf_pmu_wrap(void);
 void perf_pmu_error(struct list_head *list, char *name, char const *msg);
 
index ec898047ebb92869a6487405ec0de525b0d4acde..bfd7e8509869b64b53fbcbcddafe89a4a73b93b3 100644 (file)
@@ -1,5 +1,4 @@
 
-%name-prefix "perf_pmu_"
 %parse-param {struct list_head *format}
 %parse-param {char *name}
 
index 1daf5c14e751bf954e5665e1caa179b191cbd361..be0329394d5639f77644d8a9079dd6ceb4f27a73 100644 (file)
@@ -413,12 +413,12 @@ static int convert_variable_type(Dwarf_Die *vr_die,
                                   dwarf_diename(vr_die), dwarf_diename(&type));
                        return -EINVAL;
                }
+               if (die_get_real_type(&type, &type) == NULL) {
+                       pr_warning("Failed to get a type"
+                                  " information.\n");
+                       return -ENOENT;
+               }
                if (ret == DW_TAG_pointer_type) {
-                       if (die_get_real_type(&type, &type) == NULL) {
-                               pr_warning("Failed to get a type"
-                                          " information.\n");
-                               return -ENOENT;
-                       }
                        while (*ref_ptr)
                                ref_ptr = &(*ref_ptr)->next;
                        /* Add new reference with offset +0 */
index c40c2d33199ee266d3a2092c30aa8818e7e01fd0..64536a993f4a181b68072dc2ebe54f7e6f58da88 100644 (file)
@@ -18,4 +18,5 @@ util/cgroup.c
 util/debugfs.c
 util/rblist.c
 util/strlist.c
+util/sysfs.c
 ../../lib/rbtree.c
index a2657fd96837837566af611c421c1fdd4eccb6ca..925e0c3e6d910a3d867ce726797a0fb1dea932dc 100644 (file)
@@ -1045,3 +1045,12 @@ error:
        if (PyErr_Occurred())
                PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
 }
+
+/*
+ * Dummy, to avoid dragging all the test_attr infrastructure in the python
+ * binding.
+ */
+void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
+                     int fd, int group_fd, unsigned long flags)
+{
+}
index f80605eb1855774a7bc0c0d43690eee016ba62e5..eacec859f2996143a7fda07e4c96544db1057e1d 100644 (file)
@@ -292,6 +292,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
        ns = nsecs - s * NSECS_PER_SEC;
 
        scripting_context->event_data = data;
+       scripting_context->pevent = evsel->tp_format->pevent;
 
        ENTER;
        SAVETMPS;
index 14683dfca2eeb9cfaeac762dc5964d48c093328c..e87aa5d9696b41cca90c23bc9ba81529e449eab8 100644 (file)
@@ -265,6 +265,7 @@ static void python_process_tracepoint(union perf_event *perf_event
        ns = nsecs - s * NSECS_PER_SEC;
 
        scripting_context->event_data = data;
+       scripting_context->pevent = evsel->tp_format->pevent;
 
        context = PyCObject_FromVoidPtr(scripting_context, NULL);
 
index ce6f5116238670c0b5f737533cc65ef3f924d220..bd85280bb6e872b4dcd1d041a33fa20e683f5b9c 100644 (file)
@@ -16,7 +16,6 @@
 #include "cpumap.h"
 #include "event-parse.h"
 #include "perf_regs.h"
-#include "unwind.h"
 #include "vdso.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
@@ -87,13 +86,12 @@ void perf_session__set_id_hdr_size(struct perf_session *session)
 {
        u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
 
-       session->host_machine.id_hdr_size = id_hdr_size;
        machines__set_id_hdr_size(&session->machines, id_hdr_size);
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
 {
-       int ret = machine__create_kernel_maps(&self->host_machine);
+       int ret = machine__create_kernel_maps(&self->machines.host);
 
        if (ret >= 0)
                ret = machines__create_guest_kernel_maps(&self->machines);
@@ -102,8 +100,7 @@ int perf_session__create_kernel_maps(struct perf_session *self)
 
 static void perf_session__destroy_kernel_maps(struct perf_session *self)
 {
-       machine__destroy_kernel_maps(&self->host_machine);
-       machines__destroy_guest_kernel_maps(&self->machines);
+       machines__destroy_kernel_maps(&self->machines);
 }
 
 struct perf_session *perf_session__new(const char *filename, int mode,
@@ -128,22 +125,11 @@ struct perf_session *perf_session__new(const char *filename, int mode,
                goto out;
 
        memcpy(self->filename, filename, len);
-       /*
-        * On 64bit we can mmap the data file in one go. No need for tiny mmap
-        * slices. On 32bit we use 32MB.
-        */
-#if BITS_PER_LONG == 64
-       self->mmap_window = ULLONG_MAX;
-#else
-       self->mmap_window = 32 * 1024 * 1024ULL;
-#endif
-       self->machines = RB_ROOT;
        self->repipe = repipe;
        INIT_LIST_HEAD(&self->ordered_samples.samples);
        INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
        INIT_LIST_HEAD(&self->ordered_samples.to_free);
-       machine__init(&self->host_machine, "", HOST_KERNEL_ID);
-       hists__init(&self->hists);
+       machines__init(&self->machines);
 
        if (mode == O_RDONLY) {
                if (perf_session__open(self, force) < 0)
@@ -171,37 +157,30 @@ out_delete:
        return NULL;
 }
 
-static void machine__delete_dead_threads(struct machine *machine)
-{
-       struct thread *n, *t;
-
-       list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
-               list_del(&t->node);
-               thread__delete(t);
-       }
-}
-
 static void perf_session__delete_dead_threads(struct perf_session *session)
 {
-       machine__delete_dead_threads(&session->host_machine);
+       machine__delete_dead_threads(&session->machines.host);
 }
 
-static void machine__delete_threads(struct machine *self)
+static void perf_session__delete_threads(struct perf_session *session)
 {
-       struct rb_node *nd = rb_first(&self->threads);
-
-       while (nd) {
-               struct thread *t = rb_entry(nd, struct thread, rb_node);
-
-               rb_erase(&t->rb_node, &self->threads);
-               nd = rb_next(nd);
-               thread__delete(t);
-       }
+       machine__delete_threads(&session->machines.host);
 }
 
-static void perf_session__delete_threads(struct perf_session *session)
+static void perf_session_env__delete(struct perf_session_env *env)
 {
-       machine__delete_threads(&session->host_machine);
+       free(env->hostname);
+       free(env->os_release);
+       free(env->version);
+       free(env->arch);
+       free(env->cpu_desc);
+       free(env->cpuid);
+
+       free(env->cmdline);
+       free(env->sibling_cores);
+       free(env->sibling_threads);
+       free(env->numa_nodes);
+       free(env->pmu_mappings);
 }
 
 void perf_session__delete(struct perf_session *self)
@@ -209,198 +188,13 @@ void perf_session__delete(struct perf_session *self)
        perf_session__destroy_kernel_maps(self);
        perf_session__delete_dead_threads(self);
        perf_session__delete_threads(self);
-       machine__exit(&self->host_machine);
+       perf_session_env__delete(&self->header.env);
+       machines__exit(&self->machines);
        close(self->fd);
        free(self);
        vdso__exit();
 }
 
-void machine__remove_thread(struct machine *self, struct thread *th)
-{
-       self->last_match = NULL;
-       rb_erase(&th->rb_node, &self->threads);
-       /*
-        * We may have references to this thread, for instance in some hist_entry
-        * instances, so just move them to a separate list.
-        */
-       list_add_tail(&th->node, &self->dead_threads);
-}
-
-static bool symbol__match_parent_regex(struct symbol *sym)
-{
-       if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
-               return 1;
-
-       return 0;
-}
-
-static const u8 cpumodes[] = {
-       PERF_RECORD_MISC_USER,
-       PERF_RECORD_MISC_KERNEL,
-       PERF_RECORD_MISC_GUEST_USER,
-       PERF_RECORD_MISC_GUEST_KERNEL
-};
-#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
-
-static void ip__resolve_ams(struct machine *self, struct thread *thread,
-                           struct addr_map_symbol *ams,
-                           u64 ip)
-{
-       struct addr_location al;
-       size_t i;
-       u8 m;
-
-       memset(&al, 0, sizeof(al));
-
-       for (i = 0; i < NCPUMODES; i++) {
-               m = cpumodes[i];
-               /*
-                * We cannot use the header.misc hint to determine whether a
-                * branch stack address is user, kernel, guest, hypervisor.
-                * Branches may straddle the kernel/user/hypervisor boundaries.
-                * Thus, we have to try consecutively until we find a match
-                * or else, the symbol is unknown
-                */
-               thread__find_addr_location(thread, self, m, MAP__FUNCTION,
-                               ip, &al, NULL);
-               if (al.sym)
-                       goto found;
-       }
-found:
-       ams->addr = ip;
-       ams->al_addr = al.addr;
-       ams->sym = al.sym;
-       ams->map = al.map;
-}
-
-struct branch_info *machine__resolve_bstack(struct machine *self,
-                                           struct thread *thr,
-                                           struct branch_stack *bs)
-{
-       struct branch_info *bi;
-       unsigned int i;
-
-       bi = calloc(bs->nr, sizeof(struct branch_info));
-       if (!bi)
-               return NULL;
-
-       for (i = 0; i < bs->nr; i++) {
-               ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
-               ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
-               bi[i].flags = bs->entries[i].flags;
-       }
-       return bi;
-}
-
-static int machine__resolve_callchain_sample(struct machine *machine,
-                                            struct thread *thread,
-                                            struct ip_callchain *chain,
-                                            struct symbol **parent)
-
-{
-       u8 cpumode = PERF_RECORD_MISC_USER;
-       unsigned int i;
-       int err;
-
-       callchain_cursor_reset(&callchain_cursor);
-
-       if (chain->nr > PERF_MAX_STACK_DEPTH) {
-               pr_warning("corrupted callchain. skipping...\n");
-               return 0;
-       }
-
-       for (i = 0; i < chain->nr; i++) {
-               u64 ip;
-               struct addr_location al;
-
-               if (callchain_param.order == ORDER_CALLEE)
-                       ip = chain->ips[i];
-               else
-                       ip = chain->ips[chain->nr - i - 1];
-
-               if (ip >= PERF_CONTEXT_MAX) {
-                       switch (ip) {
-                       case PERF_CONTEXT_HV:
-                               cpumode = PERF_RECORD_MISC_HYPERVISOR;
-                               break;
-                       case PERF_CONTEXT_KERNEL:
-                               cpumode = PERF_RECORD_MISC_KERNEL;
-                               break;
-                       case PERF_CONTEXT_USER:
-                               cpumode = PERF_RECORD_MISC_USER;
-                               break;
-                       default:
-                               pr_debug("invalid callchain context: "
-                                        "%"PRId64"\n", (s64) ip);
-                               /*
-                                * It seems the callchain is corrupted.
-                                * Discard all.
-                                */
-                               callchain_cursor_reset(&callchain_cursor);
-                               return 0;
-                       }
-                       continue;
-               }
-
-               al.filtered = false;
-               thread__find_addr_location(thread, machine, cpumode,
-                                          MAP__FUNCTION, ip, &al, NULL);
-               if (al.sym != NULL) {
-                       if (sort__has_parent && !*parent &&
-                           symbol__match_parent_regex(al.sym))
-                               *parent = al.sym;
-                       if (!symbol_conf.use_callchain)
-                               break;
-               }
-
-               err = callchain_cursor_append(&callchain_cursor,
-                                             ip, al.map, al.sym);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int unwind_entry(struct unwind_entry *entry, void *arg)
-{
-       struct callchain_cursor *cursor = arg;
-       return callchain_cursor_append(cursor, entry->ip,
-                                      entry->map, entry->sym);
-}
-
-int machine__resolve_callchain(struct machine *machine,
-                              struct perf_evsel *evsel,
-                              struct thread *thread,
-                              struct perf_sample *sample,
-                              struct symbol **parent)
-
-{
-       int ret;
-
-       callchain_cursor_reset(&callchain_cursor);
-
-       ret = machine__resolve_callchain_sample(machine, thread,
-                                               sample->callchain, parent);
-       if (ret)
-               return ret;
-
-       /* Can we do dwarf post unwind? */
-       if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
-             (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
-               return 0;
-
-       /* Bail out if nothing was captured. */
-       if ((!sample->user_regs.regs) ||
-           (!sample->user_stack.size))
-               return 0;
-
-       return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
-                                  thread, evsel->attr.sample_regs_user,
-                                  sample);
-
-}
-
 static int process_event_synth_tracing_data_stub(union perf_event *event
                                                 __maybe_unused,
                                                 struct perf_session *session
@@ -1027,7 +821,7 @@ static struct machine *
                return perf_session__findnew_machine(session, pid);
        }
 
-       return perf_session__find_host_machine(session);
+       return &session->machines.host;
 }
 
 static int perf_session_deliver_event(struct perf_session *session,
@@ -1065,11 +859,11 @@ static int perf_session_deliver_event(struct perf_session *session,
        case PERF_RECORD_SAMPLE:
                dump_sample(evsel, event, sample);
                if (evsel == NULL) {
-                       ++session->hists.stats.nr_unknown_id;
+                       ++session->stats.nr_unknown_id;
                        return 0;
                }
                if (machine == NULL) {
-                       ++session->hists.stats.nr_unprocessable_samples;
+                       ++session->stats.nr_unprocessable_samples;
                        return 0;
                }
                return tool->sample(tool, event, sample, evsel, machine);
@@ -1083,7 +877,7 @@ static int perf_session_deliver_event(struct perf_session *session,
                return tool->exit(tool, event, sample, machine);
        case PERF_RECORD_LOST:
                if (tool->lost == perf_event__process_lost)
-                       session->hists.stats.total_lost += event->lost.lost;
+                       session->stats.total_lost += event->lost.lost;
                return tool->lost(tool, event, sample, machine);
        case PERF_RECORD_READ:
                return tool->read(tool, event, sample, evsel, machine);
@@ -1092,7 +886,7 @@ static int perf_session_deliver_event(struct perf_session *session,
        case PERF_RECORD_UNTHROTTLE:
                return tool->unthrottle(tool, event, sample, machine);
        default:
-               ++session->hists.stats.nr_unknown_events;
+               ++session->stats.nr_unknown_events;
                return -1;
        }
 }
@@ -1106,8 +900,8 @@ static int perf_session__preprocess_sample(struct perf_session *session,
 
        if (!ip_callchain__valid(sample->callchain, event)) {
                pr_debug("call-chain problem with event, skipping it.\n");
-               ++session->hists.stats.nr_invalid_chains;
-               session->hists.stats.total_invalid_chains += sample->period;
+               ++session->stats.nr_invalid_chains;
+               session->stats.total_invalid_chains += sample->period;
                return -EINVAL;
        }
        return 0;
@@ -1165,7 +959,7 @@ static int perf_session__process_event(struct perf_session *session,
        if (event->header.type >= PERF_RECORD_HEADER_MAX)
                return -EINVAL;
 
-       hists__inc_nr_events(&session->hists, event->header.type);
+       events_stats__inc(&session->stats, event->header.type);
 
        if (event->header.type >= PERF_RECORD_USER_TYPE_START)
                return perf_session__process_user_event(session, event, tool, file_offset);
@@ -1201,7 +995,7 @@ void perf_event_header__bswap(struct perf_event_header *self)
 
 struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
 {
-       return machine__findnew_thread(&session->host_machine, pid);
+       return machine__findnew_thread(&session->machines.host, pid);
 }
 
 static struct thread *perf_session__register_idle_thread(struct perf_session *self)
@@ -1220,39 +1014,39 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
                                            const struct perf_tool *tool)
 {
        if (tool->lost == perf_event__process_lost &&
-           session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
+           session->stats.nr_events[PERF_RECORD_LOST] != 0) {
                ui__warning("Processed %d events and lost %d chunks!\n\n"
                            "Check IO/CPU overload!\n\n",
-                           session->hists.stats.nr_events[0],
-                           session->hists.stats.nr_events[PERF_RECORD_LOST]);
+                           session->stats.nr_events[0],
+                           session->stats.nr_events[PERF_RECORD_LOST]);
        }
 
-       if (session->hists.stats.nr_unknown_events != 0) {
+       if (session->stats.nr_unknown_events != 0) {
                ui__warning("Found %u unknown events!\n\n"
                            "Is this an older tool processing a perf.data "
                            "file generated by a more recent tool?\n\n"
                            "If that is not the case, consider "
                            "reporting to linux-kernel@vger.kernel.org.\n\n",
-                           session->hists.stats.nr_unknown_events);
+                           session->stats.nr_unknown_events);
        }
 
-       if (session->hists.stats.nr_unknown_id != 0) {
+       if (session->stats.nr_unknown_id != 0) {
                ui__warning("%u samples with id not present in the header\n",
-                           session->hists.stats.nr_unknown_id);
+                           session->stats.nr_unknown_id);
        }
 
-       if (session->hists.stats.nr_invalid_chains != 0) {
+       if (session->stats.nr_invalid_chains != 0) {
                ui__warning("Found invalid callchains!\n\n"
                            "%u out of %u events were discarded for this reason.\n\n"
                            "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
-                           session->hists.stats.nr_invalid_chains,
-                           session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
+                           session->stats.nr_invalid_chains,
+                           session->stats.nr_events[PERF_RECORD_SAMPLE]);
        }
 
-       if (session->hists.stats.nr_unprocessable_samples != 0) {
+       if (session->stats.nr_unprocessable_samples != 0) {
                ui__warning("%u unprocessable samples recorded.\n"
                            "Do you have a KVM guest running and not using 'perf kvm'?\n",
-                           session->hists.stats.nr_unprocessable_samples);
+                           session->stats.nr_unprocessable_samples);
        }
 }
 
@@ -1369,6 +1163,18 @@ fetch_mmaped_event(struct perf_session *session,
        return event;
 }
 
+/*
+ * On 64bit we can mmap the data file in one go. No need for tiny mmap
+ * slices. On 32bit we use 32MB.
+ */
+#if BITS_PER_LONG == 64
+#define MMAP_SIZE ULLONG_MAX
+#define NUM_MMAPS 1
+#else
+#define MMAP_SIZE (32 * 1024 * 1024ULL)
+#define NUM_MMAPS 128
+#endif
+
 int __perf_session__process_events(struct perf_session *session,
                                   u64 data_offset, u64 data_size,
                                   u64 file_size, struct perf_tool *tool)
@@ -1376,7 +1182,7 @@ int __perf_session__process_events(struct perf_session *session,
        u64 head, page_offset, file_offset, file_pos, progress_next;
        int err, mmap_prot, mmap_flags, map_idx = 0;
        size_t  mmap_size;
-       char *buf, *mmaps[8];
+       char *buf, *mmaps[NUM_MMAPS];
        union perf_event *event;
        uint32_t size;
 
@@ -1391,7 +1197,7 @@ int __perf_session__process_events(struct perf_session *session,
 
        progress_next = file_size / 16;
 
-       mmap_size = session->mmap_window;
+       mmap_size = MMAP_SIZE;
        if (mmap_size > file_size)
                mmap_size = file_size;
 
@@ -1526,16 +1332,13 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
 
 size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
 {
-       return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) +
-              __dsos__fprintf(&self->host_machine.user_dsos, fp) +
-              machines__fprintf_dsos(&self->machines, fp);
+       return machines__fprintf_dsos(&self->machines, fp);
 }
 
 size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
-                                         bool with_hits)
+                                         bool (skip)(struct dso *dso, int parm), int parm)
 {
-       size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
-       return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
+       return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
 }
 
 size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
@@ -1543,11 +1346,11 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
        struct perf_evsel *pos;
        size_t ret = fprintf(fp, "Aggregated stats:\n");
 
-       ret += hists__fprintf_nr_events(&session->hists, fp);
+       ret += events_stats__fprintf(&session->stats, fp);
 
        list_for_each_entry(pos, &session->evlist->entries, node) {
                ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
-               ret += hists__fprintf_nr_events(&pos->hists, fp);
+               ret += events_stats__fprintf(&pos->hists.stats, fp);
        }
 
        return ret;
@@ -1559,7 +1362,7 @@ size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
         * FIXME: Here we have to actually print all the machines in this
         * session, not just the host...
         */
-       return machine__fprintf(&session->host_machine, fp);
+       return machine__fprintf(&session->machines.host, fp);
 }
 
 void perf_session__remove_thread(struct perf_session *session,
@@ -1568,10 +1371,10 @@ void perf_session__remove_thread(struct perf_session *session,
        /*
         * FIXME: This one makes no sense, we need to remove the thread from
         * the machine it belongs to, perf_session can have many machines, so
-        * doing it always on ->host_machine is wrong.  Fix when auditing all
+        * doing it always on ->machines.host is wrong.  Fix when auditing all
         * the 'perf kvm' code.
         */
-       machine__remove_thread(&session->host_machine, th);
+       machine__remove_thread(&session->machines.host, th);
 }
 
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
index cea133a6bdf1fd54061a3be27927fc32d3996184..b5c0847edfa92d3a826bb4b73c6cb59d7a19f2ea 100644 (file)
@@ -30,16 +30,10 @@ struct ordered_samples {
 struct perf_session {
        struct perf_header      header;
        unsigned long           size;
-       unsigned long           mmap_window;
-       struct machine          host_machine;
-       struct rb_root          machines;
+       struct machines         machines;
        struct perf_evlist      *evlist;
        struct pevent           *pevent;
-       /*
-        * FIXME: Need to split this up further, we need global
-        *        stats + per event stats.
-        */
-       struct hists            hists;
+       struct events_stats     stats;
        int                     fd;
        bool                    fd_pipe;
        bool                    repipe;
@@ -54,7 +48,7 @@ struct perf_tool;
 struct perf_session *perf_session__new(const char *filename, int mode,
                                       bool force, bool repipe,
                                       struct perf_tool *tool);
-void perf_session__delete(struct perf_session *self);
+void perf_session__delete(struct perf_session *session);
 
 void perf_event_header__bswap(struct perf_event_header *self);
 
@@ -80,44 +74,25 @@ int perf_session__create_kernel_maps(struct perf_session *self);
 void perf_session__set_id_hdr_size(struct perf_session *session);
 void perf_session__remove_thread(struct perf_session *self, struct thread *th);
 
-static inline
-struct machine *perf_session__find_host_machine(struct perf_session *self)
-{
-       return &self->host_machine;
-}
-
 static inline
 struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid)
 {
-       if (pid == HOST_KERNEL_ID)
-               return &self->host_machine;
        return machines__find(&self->machines, pid);
 }
 
 static inline
 struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid)
 {
-       if (pid == HOST_KERNEL_ID)
-               return &self->host_machine;
        return machines__findnew(&self->machines, pid);
 }
 
-static inline
-void perf_session__process_machines(struct perf_session *self,
-                                   struct perf_tool *tool,
-                                   machine__process_t process)
-{
-       process(&self->host_machine, tool);
-       return machines__process(&self->machines, process, tool);
-}
-
 struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
 size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
 
 size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
 
-size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
-                                         FILE *fp, bool with_hits);
+size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
+                                         bool (fn)(struct dso *dso, int parm), int parm);
 
 size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
 
index cfd1c0feb32d7da84d0b8b73b81883729fa623df..d41926cb9e3f23e9f1f296c795b39d04212d178f 100644 (file)
@@ -60,7 +60,7 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
                                       size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%*s:%5d", width,
+       return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
                              self->thread->comm ?: "", self->thread->pid);
 }
 
@@ -97,6 +97,16 @@ static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
        return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
 }
 
+struct sort_entry sort_comm = {
+       .se_header      = "Command",
+       .se_cmp         = sort__comm_cmp,
+       .se_collapse    = sort__comm_collapse,
+       .se_snprintf    = hist_entry__comm_snprintf,
+       .se_width_idx   = HISTC_COMM,
+};
+
+/* --sort dso */
+
 static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
 {
        struct dso *dso_l = map_l ? map_l->dso : NULL;
@@ -117,40 +127,12 @@ static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
        return strcmp(dso_name_l, dso_name_r);
 }
 
-struct sort_entry sort_comm = {
-       .se_header      = "Command",
-       .se_cmp         = sort__comm_cmp,
-       .se_collapse    = sort__comm_collapse,
-       .se_snprintf    = hist_entry__comm_snprintf,
-       .se_width_idx   = HISTC_COMM,
-};
-
-/* --sort dso */
-
 static int64_t
 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 {
        return _sort__dso_cmp(left->ms.map, right->ms.map);
 }
 
-
-static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r,
-                             u64 ip_l, u64 ip_r)
-{
-       if (!sym_l || !sym_r)
-               return cmp_null(sym_l, sym_r);
-
-       if (sym_l == sym_r)
-               return 0;
-
-       if (sym_l)
-               ip_l = sym_l->start;
-       if (sym_r)
-               ip_r = sym_r->start;
-
-       return (int64_t)(ip_r - ip_l);
-}
-
 static int _hist_entry__dso_snprintf(struct map *map, char *bf,
                                     size_t size, unsigned int width)
 {
@@ -169,9 +151,43 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
        return _hist_entry__dso_snprintf(self->ms.map, bf, size, width);
 }
 
+struct sort_entry sort_dso = {
+       .se_header      = "Shared Object",
+       .se_cmp         = sort__dso_cmp,
+       .se_snprintf    = hist_entry__dso_snprintf,
+       .se_width_idx   = HISTC_DSO,
+};
+
+/* --sort symbol */
+
+static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
+{
+       u64 ip_l, ip_r;
+
+       if (!sym_l || !sym_r)
+               return cmp_null(sym_l, sym_r);
+
+       if (sym_l == sym_r)
+               return 0;
+
+       ip_l = sym_l->start;
+       ip_r = sym_r->start;
+
+       return (int64_t)(ip_r - ip_l);
+}
+
+static int64_t
+sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       if (!left->ms.sym && !right->ms.sym)
+               return right->level - left->level;
+
+       return _sort__sym_cmp(left->ms.sym, right->ms.sym);
+}
+
 static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
                                     u64 ip, char level, char *bf, size_t size,
-                                    unsigned int width __maybe_unused)
+                                    unsigned int width)
 {
        size_t ret = 0;
 
@@ -197,43 +213,13 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
        return ret;
 }
 
-
-struct sort_entry sort_dso = {
-       .se_header      = "Shared Object",
-       .se_cmp         = sort__dso_cmp,
-       .se_snprintf    = hist_entry__dso_snprintf,
-       .se_width_idx   = HISTC_DSO,
-};
-
 static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
-                                   size_t size,
-                                   unsigned int width __maybe_unused)
+                                   size_t size, unsigned int width)
 {
        return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip,
                                         self->level, bf, size, width);
 }
 
-/* --sort symbol */
-static int64_t
-sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
-{
-       u64 ip_l, ip_r;
-
-       if (!left->ms.sym && !right->ms.sym)
-               return right->level - left->level;
-
-       if (!left->ms.sym || !right->ms.sym)
-               return cmp_null(left->ms.sym, right->ms.sym);
-
-       if (left->ms.sym == right->ms.sym)
-               return 0;
-
-       ip_l = left->ms.sym->start;
-       ip_r = right->ms.sym->start;
-
-       return _sort__sym_cmp(left->ms.sym, right->ms.sym, ip_l, ip_r);
-}
-
 struct sort_entry sort_sym = {
        .se_header      = "Symbol",
        .se_cmp         = sort__sym_cmp,
@@ -253,7 +239,7 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
                                        size_t size,
                                        unsigned int width __maybe_unused)
 {
-       FILE *fp;
+       FILE *fp = NULL;
        char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
        size_t line_len;
 
@@ -274,7 +260,6 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
 
        if (getline(&path, &line_len, fp) < 0 || !line_len)
                goto out_ip;
-       fclose(fp);
        self->srcline = strdup(path);
        if (self->srcline == NULL)
                goto out_ip;
@@ -284,8 +269,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
                *nl = '\0';
        path = self->srcline;
 out_path:
+       if (fp)
+               pclose(fp);
        return repsep_snprintf(bf, size, "%s", path);
 out_ip:
+       if (fp)
+               pclose(fp);
        return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
 }
 
@@ -335,7 +324,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
                                       size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*d", width, self->cpu);
+       return repsep_snprintf(bf, size, "%*d", width, self->cpu);
 }
 
 struct sort_entry sort_cpu = {
@@ -345,6 +334,8 @@ struct sort_entry sort_cpu = {
        .se_width_idx   = HISTC_CPU,
 };
 
+/* sort keys for branch stacks */
+
 static int64_t
 sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -359,13 +350,6 @@ static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf,
                                         bf, size, width);
 }
 
-struct sort_entry sort_dso_from = {
-       .se_header      = "Source Shared Object",
-       .se_cmp         = sort__dso_from_cmp,
-       .se_snprintf    = hist_entry__dso_from_snprintf,
-       .se_width_idx   = HISTC_DSO_FROM,
-};
-
 static int64_t
 sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -389,8 +373,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
        if (!from_l->sym && !from_r->sym)
                return right->level - left->level;
 
-       return _sort__sym_cmp(from_l->sym, from_r->sym, from_l->addr,
-                            from_r->addr);
+       return _sort__sym_cmp(from_l->sym, from_r->sym);
 }
 
 static int64_t
@@ -402,12 +385,11 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
        if (!to_l->sym && !to_r->sym)
                return right->level - left->level;
 
-       return _sort__sym_cmp(to_l->sym, to_r->sym, to_l->addr, to_r->addr);
+       return _sort__sym_cmp(to_l->sym, to_r->sym);
 }
 
 static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
-                                       size_t size,
-                                       unsigned int width __maybe_unused)
+                                        size_t size, unsigned int width)
 {
        struct addr_map_symbol *from = &self->branch_info->from;
        return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
@@ -416,8 +398,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
 }
 
 static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
-                                      size_t size,
-                                      unsigned int width __maybe_unused)
+                                      size_t size, unsigned int width)
 {
        struct addr_map_symbol *to = &self->branch_info->to;
        return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
@@ -425,6 +406,13 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
 
 }
 
+struct sort_entry sort_dso_from = {
+       .se_header      = "Source Shared Object",
+       .se_cmp         = sort__dso_from_cmp,
+       .se_snprintf    = hist_entry__dso_from_snprintf,
+       .se_width_idx   = HISTC_DSO_FROM,
+};
+
 struct sort_entry sort_dso_to = {
        .se_header      = "Target Shared Object",
        .se_cmp         = sort__dso_to_cmp,
@@ -484,30 +472,40 @@ struct sort_dimension {
 
 #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
 
-static struct sort_dimension sort_dimensions[] = {
+static struct sort_dimension common_sort_dimensions[] = {
        DIM(SORT_PID, "pid", sort_thread),
        DIM(SORT_COMM, "comm", sort_comm),
        DIM(SORT_DSO, "dso", sort_dso),
-       DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
-       DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
        DIM(SORT_SYM, "symbol", sort_sym),
-       DIM(SORT_SYM_TO, "symbol_from", sort_sym_from),
-       DIM(SORT_SYM_FROM, "symbol_to", sort_sym_to),
        DIM(SORT_PARENT, "parent", sort_parent),
        DIM(SORT_CPU, "cpu", sort_cpu),
-       DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
        DIM(SORT_SRCLINE, "srcline", sort_srcline),
 };
 
+#undef DIM
+
+#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
+
+static struct sort_dimension bstack_sort_dimensions[] = {
+       DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
+       DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
+       DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
+       DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
+       DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
+};
+
+#undef DIM
+
 int sort_dimension__add(const char *tok)
 {
        unsigned int i;
 
-       for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
-               struct sort_dimension *sd = &sort_dimensions[i];
+       for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
+               struct sort_dimension *sd = &common_sort_dimensions[i];
 
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
+
                if (sd->entry == &sort_parent) {
                        int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
                        if (ret) {
@@ -518,9 +516,7 @@ int sort_dimension__add(const char *tok)
                                return -EINVAL;
                        }
                        sort__has_parent = 1;
-               } else if (sd->entry == &sort_sym ||
-                          sd->entry == &sort_sym_from ||
-                          sd->entry == &sort_sym_to) {
+               } else if (sd->entry == &sort_sym) {
                        sort__has_sym = 1;
                }
 
@@ -530,52 +526,69 @@ int sort_dimension__add(const char *tok)
                if (sd->entry->se_collapse)
                        sort__need_collapse = 1;
 
-               if (list_empty(&hist_entry__sort_list)) {
-                       if (!strcmp(sd->name, "pid"))
-                               sort__first_dimension = SORT_PID;
-                       else if (!strcmp(sd->name, "comm"))
-                               sort__first_dimension = SORT_COMM;
-                       else if (!strcmp(sd->name, "dso"))
-                               sort__first_dimension = SORT_DSO;
-                       else if (!strcmp(sd->name, "symbol"))
-                               sort__first_dimension = SORT_SYM;
-                       else if (!strcmp(sd->name, "parent"))
-                               sort__first_dimension = SORT_PARENT;
-                       else if (!strcmp(sd->name, "cpu"))
-                               sort__first_dimension = SORT_CPU;
-                       else if (!strcmp(sd->name, "symbol_from"))
-                               sort__first_dimension = SORT_SYM_FROM;
-                       else if (!strcmp(sd->name, "symbol_to"))
-                               sort__first_dimension = SORT_SYM_TO;
-                       else if (!strcmp(sd->name, "dso_from"))
-                               sort__first_dimension = SORT_DSO_FROM;
-                       else if (!strcmp(sd->name, "dso_to"))
-                               sort__first_dimension = SORT_DSO_TO;
-                       else if (!strcmp(sd->name, "mispredict"))
-                               sort__first_dimension = SORT_MISPREDICT;
-               }
+               if (list_empty(&hist_entry__sort_list))
+                       sort__first_dimension = i;
 
                list_add_tail(&sd->entry->list, &hist_entry__sort_list);
                sd->taken = 1;
 
                return 0;
        }
+
+       for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
+               struct sort_dimension *sd = &bstack_sort_dimensions[i];
+
+               if (strncasecmp(tok, sd->name, strlen(tok)))
+                       continue;
+
+               if (sort__branch_mode != 1)
+                       return -EINVAL;
+
+               if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
+                       sort__has_sym = 1;
+
+               if (sd->taken)
+                       return 0;
+
+               if (sd->entry->se_collapse)
+                       sort__need_collapse = 1;
+
+               if (list_empty(&hist_entry__sort_list))
+                       sort__first_dimension = i + __SORT_BRANCH_STACK;
+
+               list_add_tail(&sd->entry->list, &hist_entry__sort_list);
+               sd->taken = 1;
+
+               return 0;
+       }
+
        return -ESRCH;
 }
 
-void setup_sorting(const char * const usagestr[], const struct option *opts)
+int setup_sorting(void)
 {
        char *tmp, *tok, *str = strdup(sort_order);
+       int ret = 0;
+
+       if (str == NULL) {
+               error("Not enough memory to setup sort keys");
+               return -ENOMEM;
+       }
 
        for (tok = strtok_r(str, ", ", &tmp);
                        tok; tok = strtok_r(NULL, ", ", &tmp)) {
-               if (sort_dimension__add(tok) < 0) {
+               ret = sort_dimension__add(tok);
+               if (ret == -EINVAL) {
+                       error("Invalid --sort key: `%s'", tok);
+                       break;
+               } else if (ret == -ESRCH) {
                        error("Unknown --sort key: `%s'", tok);
-                       usage_with_options(usagestr, opts);
+                       break;
                }
        }
 
        free(str);
+       return ret;
 }
 
 void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
index b4e8c3ba559de22357cc0cb7a3100e5ee081b327..b13e56f6ccbebf7aa03b25c6ffdf98357b78716b 100644 (file)
@@ -55,9 +55,6 @@ struct he_stat {
 struct hist_entry_diff {
        bool    computed;
 
-       /* PERF_HPP__DISPL */
-       int     displacement;
-
        /* PERF_HPP__DELTA */
        double  period_ratio_delta;
 
@@ -118,25 +115,29 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
        return NULL;
 }
 
-static inline void hist__entry_add_pair(struct hist_entry *he,
+static inline void hist_entry__add_pair(struct hist_entry *he,
                                        struct hist_entry *pair)
 {
        list_add_tail(&he->pairs.head, &pair->pairs.node);
 }
 
 enum sort_type {
+       /* common sort keys */
        SORT_PID,
        SORT_COMM,
        SORT_DSO,
        SORT_SYM,
        SORT_PARENT,
        SORT_CPU,
-       SORT_DSO_FROM,
+       SORT_SRCLINE,
+
+       /* branch stack specific sort keys */
+       __SORT_BRANCH_STACK,
+       SORT_DSO_FROM = __SORT_BRANCH_STACK,
        SORT_DSO_TO,
        SORT_SYM_FROM,
        SORT_SYM_TO,
        SORT_MISPREDICT,
-       SORT_SRCLINE,
 };
 
 /*
@@ -159,7 +160,7 @@ struct sort_entry {
 extern struct sort_entry sort_thread;
 extern struct list_head hist_entry__sort_list;
 
-void setup_sorting(const char * const usagestr[], const struct option *opts);
+int setup_sorting(void);
 extern int sort_dimension__add(const char *);
 void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
                             const char *list_name, FILE *fp);
index 346707df04b9f0b6e2176fa592c5baea91daa238..29c7b2cb252192b8cb9d184ef320c32265de832e 100644 (file)
@@ -331,6 +331,24 @@ char *strxfrchar(char *s, char from, char to)
        return s;
 }
 
+/**
+ * ltrim - Removes leading whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Return pointer to the first non-whitespace character in @s.
+ */
+char *ltrim(char *s)
+{
+       int len = strlen(s);
+
+       while (len && isspace(*s)) {
+               len--;
+               s++;
+       }
+
+       return s;
+}
+
 /**
  * rtrim - Removes trailing whitespace from @s.
  * @s: The string to be stripped.
index 155d8b7078a723ddfec5030048a72b6500840019..55433aa42c8f30cb8dbeeae537ce8ea0ad47965b 100644 (file)
@@ -35,11 +35,11 @@ out_delete:
        return NULL;
 }
 
-static void str_node__delete(struct str_node *self, bool dupstr)
+static void str_node__delete(struct str_node *snode, bool dupstr)
 {
        if (dupstr)
-               free((void *)self->s);
-       free(self);
+               free((void *)snode->s);
+       free(snode);
 }
 
 static
@@ -59,12 +59,12 @@ static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)
        return strcmp(snode->s, str);
 }
 
-int strlist__add(struct strlist *self, const char *new_entry)
+int strlist__add(struct strlist *slist, const char *new_entry)
 {
-       return rblist__add_node(&self->rblist, new_entry);
+       return rblist__add_node(&slist->rblist, new_entry);
 }
 
-int strlist__load(struct strlist *self, const char *filename)
+int strlist__load(struct strlist *slist, const char *filename)
 {
        char entry[1024];
        int err;
@@ -80,7 +80,7 @@ int strlist__load(struct strlist *self, const char *filename)
                        continue;
                entry[len - 1] = '\0';
 
-               err = strlist__add(self, entry);
+               err = strlist__add(slist, entry);
                if (err != 0)
                        goto out;
        }
@@ -107,56 +107,56 @@ struct str_node *strlist__find(struct strlist *slist, const char *entry)
        return snode;
 }
 
-static int strlist__parse_list_entry(struct strlist *self, const char *s)
+static int strlist__parse_list_entry(struct strlist *slist, const char *s)
 {
        if (strncmp(s, "file://", 7) == 0)
-               return strlist__load(self, s + 7);
+               return strlist__load(slist, s + 7);
 
-       return strlist__add(self, s);
+       return strlist__add(slist, s);
 }
 
-int strlist__parse_list(struct strlist *self, const char *s)
+int strlist__parse_list(struct strlist *slist, const char *s)
 {
        char *sep;
        int err;
 
        while ((sep = strchr(s, ',')) != NULL) {
                *sep = '\0';
-               err = strlist__parse_list_entry(self, s);
+               err = strlist__parse_list_entry(slist, s);
                *sep = ',';
                if (err != 0)
                        return err;
                s = sep + 1;
        }
 
-       return *s ? strlist__parse_list_entry(self, s) : 0;
+       return *s ? strlist__parse_list_entry(slist, s) : 0;
 }
 
-struct strlist *strlist__new(bool dupstr, const char *slist)
+struct strlist *strlist__new(bool dupstr, const char *list)
 {
-       struct strlist *self = malloc(sizeof(*self));
+       struct strlist *slist = malloc(sizeof(*slist));
 
-       if (self != NULL) {
-               rblist__init(&self->rblist);
-               self->rblist.node_cmp    = strlist__node_cmp;
-               self->rblist.node_new    = strlist__node_new;
-               self->rblist.node_delete = strlist__node_delete;
+       if (slist != NULL) {
+               rblist__init(&slist->rblist);
+               slist->rblist.node_cmp    = strlist__node_cmp;
+               slist->rblist.node_new    = strlist__node_new;
+               slist->rblist.node_delete = strlist__node_delete;
 
-               self->dupstr     = dupstr;
-               if (slist && strlist__parse_list(self, slist) != 0)
+               slist->dupstr    = dupstr;
+               if (slist && strlist__parse_list(slist, list) != 0)
                        goto out_error;
        }
 
-       return self;
+       return slist;
 out_error:
-       free(self);
+       free(slist);
        return NULL;
 }
 
-void strlist__delete(struct strlist *self)
+void strlist__delete(struct strlist *slist)
 {
-       if (self != NULL)
-               rblist__delete(&self->rblist);
+       if (slist != NULL)
+               rblist__delete(&slist->rblist);
 }
 
 struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)
index dd9f922ec67c58845ff22b6d3fabe3eb888c21e6..5c7f87069d9cd7bfa5412c186068840e76822b2e 100644 (file)
@@ -17,34 +17,34 @@ struct strlist {
 };
 
 struct strlist *strlist__new(bool dupstr, const char *slist);
-void strlist__delete(struct strlist *self);
+void strlist__delete(struct strlist *slist);
 
-void strlist__remove(struct strlist *self, struct str_node *sn);
-int strlist__load(struct strlist *self, const char *filename);
-int strlist__add(struct strlist *self, const char *str);
+void strlist__remove(struct strlist *slist, struct str_node *sn);
+int strlist__load(struct strlist *slist, const char *filename);
+int strlist__add(struct strlist *slist, const char *str);
 
-struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
-struct str_node *strlist__find(struct strlist *self, const char *entry);
+struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx);
+struct str_node *strlist__find(struct strlist *slist, const char *entry);
 
-static inline bool strlist__has_entry(struct strlist *self, const char *entry)
+static inline bool strlist__has_entry(struct strlist *slist, const char *entry)
 {
-       return strlist__find(self, entry) != NULL;
+       return strlist__find(slist, entry) != NULL;
 }
 
-static inline bool strlist__empty(const struct strlist *self)
+static inline bool strlist__empty(const struct strlist *slist)
 {
-       return rblist__empty(&self->rblist);
+       return rblist__empty(&slist->rblist);
 }
 
-static inline unsigned int strlist__nr_entries(const struct strlist *self)
+static inline unsigned int strlist__nr_entries(const struct strlist *slist)
 {
-       return rblist__nr_entries(&self->rblist);
+       return rblist__nr_entries(&slist->rblist);
 }
 
 /* For strlist iteration */
-static inline struct str_node *strlist__first(struct strlist *self)
+static inline struct str_node *strlist__first(struct strlist *slist)
 {
-       struct rb_node *rn = rb_first(&self->rblist.entries);
+       struct rb_node *rn = rb_first(&slist->rblist.entries);
        return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
 }
 static inline struct str_node *strlist__next(struct str_node *sn)
@@ -59,21 +59,21 @@ static inline struct str_node *strlist__next(struct str_node *sn)
 /**
  * strlist_for_each      - iterate over a strlist
  * @pos:       the &struct str_node to use as a loop cursor.
- * @self:      the &struct strlist for loop.
+ * @slist:     the &struct strlist for loop.
  */
-#define strlist__for_each(pos, self)   \
-       for (pos = strlist__first(self); pos; pos = strlist__next(pos))
+#define strlist__for_each(pos, slist)  \
+       for (pos = strlist__first(slist); pos; pos = strlist__next(pos))
 
 /**
  * strlist_for_each_safe - iterate over a strlist safe against removal of
  *                         str_node
  * @pos:       the &struct str_node to use as a loop cursor.
  * @n:         another &struct str_node to use as temporary storage.
- * @self:      the &struct strlist for loop.
+ * @slist:     the &struct strlist for loop.
  */
-#define strlist__for_each_safe(pos, n, self)   \
-       for (pos = strlist__first(self), n = strlist__next(pos); pos;\
+#define strlist__for_each_safe(pos, n, slist)  \
+       for (pos = strlist__first(slist), n = strlist__next(pos); pos;\
             pos = n, n = strlist__next(n))
 
-int strlist__parse_list(struct strlist *self, const char *s);
+int strlist__parse_list(struct strlist *slist, const char *s);
 #endif /* __PERF_STRLIST_H */
index db0cc92cf2eaf25a3528429154b1f9713f1d91d8..54efcb5659ac2bf2f6061a5c64e496f1b408d54c 100644 (file)
@@ -1,6 +1,3 @@
-#include <libelf.h>
-#include <gelf.h>
-#include <elf.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <errno.h>
@@ -718,6 +715,17 @@ int dso__load_sym(struct dso *dso, struct map *map,
                                        sym.st_value);
                        used_opd = true;
                }
+               /*
+                * When loading symbols in a data mapping, ABS symbols (which
+                * has a value of SHN_ABS in its st_shndx) failed at
+                * elf_getscn().  And it marks the loading as a failure so
+                * already loaded symbols cannot be fixed up.
+                *
+                * I'm not sure what should be done. Just ignore them for now.
+                * - Namhyung Kim
+                */
+               if (sym.st_shndx == SHN_ABS)
+                       continue;
 
                sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
                if (!sec)
index 259f8f2ea9c96468b84100c511ea0878f9d53f0c..a7390cde63bc74f8dae01422dd92bbc2e1a09d3c 100644 (file)
@@ -1,6 +1,5 @@
 #include "symbol.h"
 
-#include <elf.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <string.h>
index 295f8d4feedfeb00afd11787c3e7538e5fb19c74..e6432d85b43dd9de0fc6470b271de72a3f6028b8 100644 (file)
@@ -28,8 +28,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
                                symbol_filter_t filter);
 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
                        symbol_filter_t filter);
-static int vmlinux_path__nr_entries;
-static char **vmlinux_path;
+int vmlinux_path__nr_entries;
+char **vmlinux_path;
 
 struct symbol_conf symbol_conf = {
        .exclude_other    = true,
@@ -202,13 +202,6 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
        curr->end = ~0ULL;
 }
 
-static void map_groups__fixup_end(struct map_groups *mg)
-{
-       int i;
-       for (i = 0; i < MAP__NR_TYPES; ++i)
-               __map_groups__fixup_end(mg, i);
-}
-
 struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
 {
        size_t namelen = strlen(name) + 1;
@@ -652,8 +645,8 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
        return count + moved;
 }
 
-static bool symbol__restricted_filename(const char *filename,
-                                       const char *restricted_filename)
+bool symbol__restricted_filename(const char *filename,
+                                const char *restricted_filename)
 {
        bool restricted = false;
 
@@ -775,10 +768,6 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        else
                machine = NULL;
 
-       name = malloc(PATH_MAX);
-       if (!name)
-               return -1;
-
        dso->adjust_symbols = 0;
 
        if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
@@ -802,6 +791,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        if (machine)
                root_dir = machine->root_dir;
 
+       name = malloc(PATH_MAX);
+       if (!name)
+               return -1;
+
        /* Iterate over candidate debug images.
         * Keep track of "interesting" ones (those which have a symtab, dynsym,
         * and/or opd section) for processing.
@@ -887,200 +880,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
        return NULL;
 }
 
-static int map_groups__set_modules_path_dir(struct map_groups *mg,
-                               const char *dir_name)
-{
-       struct dirent *dent;
-       DIR *dir = opendir(dir_name);
-       int ret = 0;
-
-       if (!dir) {
-               pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
-               return -1;
-       }
-
-       while ((dent = readdir(dir)) != NULL) {
-               char path[PATH_MAX];
-               struct stat st;
-
-               /*sshfs might return bad dent->d_type, so we have to stat*/
-               snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
-               if (stat(path, &st))
-                       continue;
-
-               if (S_ISDIR(st.st_mode)) {
-                       if (!strcmp(dent->d_name, ".") ||
-                           !strcmp(dent->d_name, ".."))
-                               continue;
-
-                       ret = map_groups__set_modules_path_dir(mg, path);
-                       if (ret < 0)
-                               goto out;
-               } else {
-                       char *dot = strrchr(dent->d_name, '.'),
-                            dso_name[PATH_MAX];
-                       struct map *map;
-                       char *long_name;
-
-                       if (dot == NULL || strcmp(dot, ".ko"))
-                               continue;
-                       snprintf(dso_name, sizeof(dso_name), "[%.*s]",
-                                (int)(dot - dent->d_name), dent->d_name);
-
-                       strxfrchar(dso_name, '-', '_');
-                       map = map_groups__find_by_name(mg, MAP__FUNCTION,
-                                                      dso_name);
-                       if (map == NULL)
-                               continue;
-
-                       long_name = strdup(path);
-                       if (long_name == NULL) {
-                               ret = -1;
-                               goto out;
-                       }
-                       dso__set_long_name(map->dso, long_name);
-                       map->dso->lname_alloc = 1;
-                       dso__kernel_module_get_build_id(map->dso, "");
-               }
-       }
-
-out:
-       closedir(dir);
-       return ret;
-}
-
-static char *get_kernel_version(const char *root_dir)
-{
-       char version[PATH_MAX];
-       FILE *file;
-       char *name, *tmp;
-       const char *prefix = "Linux version ";
-
-       sprintf(version, "%s/proc/version", root_dir);
-       file = fopen(version, "r");
-       if (!file)
-               return NULL;
-
-       version[0] = '\0';
-       tmp = fgets(version, sizeof(version), file);
-       fclose(file);
-
-       name = strstr(version, prefix);
-       if (!name)
-               return NULL;
-       name += strlen(prefix);
-       tmp = strchr(name, ' ');
-       if (tmp)
-               *tmp = '\0';
-
-       return strdup(name);
-}
-
-static int machine__set_modules_path(struct machine *machine)
-{
-       char *version;
-       char modules_path[PATH_MAX];
-
-       version = get_kernel_version(machine->root_dir);
-       if (!version)
-               return -1;
-
-       snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
-                machine->root_dir, version);
-       free(version);
-
-       return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
-}
-
-struct map *machine__new_module(struct machine *machine, u64 start,
-                               const char *filename)
-{
-       struct map *map;
-       struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
-
-       if (dso == NULL)
-               return NULL;
-
-       map = map__new2(start, dso, MAP__FUNCTION);
-       if (map == NULL)
-               return NULL;
-
-       if (machine__is_host(machine))
-               dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
-       else
-               dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
-       map_groups__insert(&machine->kmaps, map);
-       return map;
-}
-
-static int machine__create_modules(struct machine *machine)
-{
-       char *line = NULL;
-       size_t n;
-       FILE *file;
-       struct map *map;
-       const char *modules;
-       char path[PATH_MAX];
-
-       if (machine__is_default_guest(machine))
-               modules = symbol_conf.default_guest_modules;
-       else {
-               sprintf(path, "%s/proc/modules", machine->root_dir);
-               modules = path;
-       }
-
-       if (symbol__restricted_filename(path, "/proc/modules"))
-               return -1;
-
-       file = fopen(modules, "r");
-       if (file == NULL)
-               return -1;
-
-       while (!feof(file)) {
-               char name[PATH_MAX];
-               u64 start;
-               char *sep;
-               int line_len;
-
-               line_len = getline(&line, &n, file);
-               if (line_len < 0)
-                       break;
-
-               if (!line)
-                       goto out_failure;
-
-               line[--line_len] = '\0'; /* \n */
-
-               sep = strrchr(line, 'x');
-               if (sep == NULL)
-                       continue;
-
-               hex2u64(sep + 1, &start);
-
-               sep = strchr(line, ' ');
-               if (sep == NULL)
-                       continue;
-
-               *sep = '\0';
-
-               snprintf(name, sizeof(name), "[%s]", line);
-               map = machine__new_module(machine, start, name);
-               if (map == NULL)
-                       goto out_delete_line;
-               dso__kernel_module_get_build_id(map->dso, machine->root_dir);
-       }
-
-       free(line);
-       fclose(file);
-
-       return machine__set_modules_path(machine);
-
-out_delete_line:
-       free(line);
-out_failure:
-       return -1;
-}
-
 int dso__load_vmlinux(struct dso *dso, struct map *map,
                      const char *vmlinux, symbol_filter_t filter)
 {
@@ -1124,8 +923,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
        filename = dso__build_id_filename(dso, NULL, 0);
        if (filename != NULL) {
                err = dso__load_vmlinux(dso, map, filename, filter);
-               if (err > 0)
+               if (err > 0) {
+                       dso->lname_alloc = 1;
                        goto out;
+               }
                free(filename);
        }
 
@@ -1133,6 +934,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
                if (err > 0) {
                        dso__set_long_name(dso, strdup(vmlinux_path[i]));
+                       dso->lname_alloc = 1;
                        break;
                }
        }
@@ -1172,6 +974,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
                if (err > 0) {
                        dso__set_long_name(dso,
                                           strdup(symbol_conf.vmlinux_name));
+                       dso->lname_alloc = 1;
                        goto out_fixup;
                }
                return err;
@@ -1300,195 +1103,6 @@ out_try_fixup:
        return err;
 }
 
-size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
-{
-       struct rb_node *nd;
-       size_t ret = 0;
-
-       for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               ret += __dsos__fprintf(&pos->kernel_dsos, fp);
-               ret += __dsos__fprintf(&pos->user_dsos, fp);
-       }
-
-       return ret;
-}
-
-size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
-                                    bool with_hits)
-{
-       return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) +
-              __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits);
-}
-
-size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
-                                     FILE *fp, bool with_hits)
-{
-       struct rb_node *nd;
-       size_t ret = 0;
-
-       for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
-       }
-       return ret;
-}
-
-static struct dso *machine__get_kernel(struct machine *machine)
-{
-       const char *vmlinux_name = NULL;
-       struct dso *kernel;
-
-       if (machine__is_host(machine)) {
-               vmlinux_name = symbol_conf.vmlinux_name;
-               if (!vmlinux_name)
-                       vmlinux_name = "[kernel.kallsyms]";
-
-               kernel = dso__kernel_findnew(machine, vmlinux_name,
-                                            "[kernel]",
-                                            DSO_TYPE_KERNEL);
-       } else {
-               char bf[PATH_MAX];
-
-               if (machine__is_default_guest(machine))
-                       vmlinux_name = symbol_conf.default_guest_vmlinux_name;
-               if (!vmlinux_name)
-                       vmlinux_name = machine__mmap_name(machine, bf,
-                                                         sizeof(bf));
-
-               kernel = dso__kernel_findnew(machine, vmlinux_name,
-                                            "[guest.kernel]",
-                                            DSO_TYPE_GUEST_KERNEL);
-       }
-
-       if (kernel != NULL && (!kernel->has_build_id))
-               dso__read_running_kernel_build_id(kernel, machine);
-
-       return kernel;
-}
-
-struct process_args {
-       u64 start;
-};
-
-static int symbol__in_kernel(void *arg, const char *name,
-                            char type __maybe_unused, u64 start)
-{
-       struct process_args *args = arg;
-
-       if (strchr(name, '['))
-               return 0;
-
-       args->start = start;
-       return 1;
-}
-
-/* Figure out the start address of kernel map from /proc/kallsyms */
-static u64 machine__get_kernel_start_addr(struct machine *machine)
-{
-       const char *filename;
-       char path[PATH_MAX];
-       struct process_args args;
-
-       if (machine__is_host(machine)) {
-               filename = "/proc/kallsyms";
-       } else {
-               if (machine__is_default_guest(machine))
-                       filename = (char *)symbol_conf.default_guest_kallsyms;
-               else {
-                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
-                       filename = path;
-               }
-       }
-
-       if (symbol__restricted_filename(filename, "/proc/kallsyms"))
-               return 0;
-
-       if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
-               return 0;
-
-       return args.start;
-}
-
-int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
-{
-       enum map_type type;
-       u64 start = machine__get_kernel_start_addr(machine);
-
-       for (type = 0; type < MAP__NR_TYPES; ++type) {
-               struct kmap *kmap;
-
-               machine->vmlinux_maps[type] = map__new2(start, kernel, type);
-               if (machine->vmlinux_maps[type] == NULL)
-                       return -1;
-
-               machine->vmlinux_maps[type]->map_ip =
-                       machine->vmlinux_maps[type]->unmap_ip =
-                               identity__map_ip;
-               kmap = map__kmap(machine->vmlinux_maps[type]);
-               kmap->kmaps = &machine->kmaps;
-               map_groups__insert(&machine->kmaps,
-                                  machine->vmlinux_maps[type]);
-       }
-
-       return 0;
-}
-
-void machine__destroy_kernel_maps(struct machine *machine)
-{
-       enum map_type type;
-
-       for (type = 0; type < MAP__NR_TYPES; ++type) {
-               struct kmap *kmap;
-
-               if (machine->vmlinux_maps[type] == NULL)
-                       continue;
-
-               kmap = map__kmap(machine->vmlinux_maps[type]);
-               map_groups__remove(&machine->kmaps,
-                                  machine->vmlinux_maps[type]);
-               if (kmap->ref_reloc_sym) {
-                       /*
-                        * ref_reloc_sym is shared among all maps, so free just
-                        * on one of them.
-                        */
-                       if (type == MAP__FUNCTION) {
-                               free((char *)kmap->ref_reloc_sym->name);
-                               kmap->ref_reloc_sym->name = NULL;
-                               free(kmap->ref_reloc_sym);
-                       }
-                       kmap->ref_reloc_sym = NULL;
-               }
-
-               map__delete(machine->vmlinux_maps[type]);
-               machine->vmlinux_maps[type] = NULL;
-       }
-}
-
-int machine__create_kernel_maps(struct machine *machine)
-{
-       struct dso *kernel = machine__get_kernel(machine);
-
-       if (kernel == NULL ||
-           __machine__create_kernel_maps(machine, kernel) < 0)
-               return -1;
-
-       if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
-               if (machine__is_host(machine))
-                       pr_debug("Problems creating module maps, "
-                                "continuing anyway...\n");
-               else
-                       pr_debug("Problems creating module maps for guest %d, "
-                                "continuing anyway...\n", machine->pid);
-       }
-
-       /*
-        * Now that we have all the maps created, just set the ->end of them:
-        */
-       map_groups__fixup_end(&machine->kmaps);
-       return 0;
-}
-
 static void vmlinux_path__exit(void)
 {
        while (--vmlinux_path__nr_entries >= 0) {
@@ -1549,25 +1163,6 @@ out_fail:
        return -1;
 }
 
-size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
-{
-       int i;
-       size_t printed = 0;
-       struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
-
-       if (kdso->has_build_id) {
-               char filename[PATH_MAX];
-               if (dso__build_id_filename(kdso, filename, sizeof(filename)))
-                       printed += fprintf(fp, "[0] %s\n", filename);
-       }
-
-       for (i = 0; i < vmlinux_path__nr_entries; ++i)
-               printed += fprintf(fp, "[%d] %s\n",
-                                  i + kdso->has_build_id, vmlinux_path[i]);
-
-       return printed;
-}
-
 static int setup_list(struct strlist **list, const char *list_str,
                      const char *list_name)
 {
@@ -1671,108 +1266,3 @@ void symbol__exit(void)
        symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
        symbol_conf.initialized = false;
 }
-
-int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
-{
-       struct machine *machine = machines__findnew(machines, pid);
-
-       if (machine == NULL)
-               return -1;
-
-       return machine__create_kernel_maps(machine);
-}
-
-int machines__create_guest_kernel_maps(struct rb_root *machines)
-{
-       int ret = 0;
-       struct dirent **namelist = NULL;
-       int i, items = 0;
-       char path[PATH_MAX];
-       pid_t pid;
-       char *endp;
-
-       if (symbol_conf.default_guest_vmlinux_name ||
-           symbol_conf.default_guest_modules ||
-           symbol_conf.default_guest_kallsyms) {
-               machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
-       }
-
-       if (symbol_conf.guestmount) {
-               items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
-               if (items <= 0)
-                       return -ENOENT;
-               for (i = 0; i < items; i++) {
-                       if (!isdigit(namelist[i]->d_name[0])) {
-                               /* Filter out . and .. */
-                               continue;
-                       }
-                       pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
-                       if ((*endp != '\0') ||
-                           (endp == namelist[i]->d_name) ||
-                           (errno == ERANGE)) {
-                               pr_debug("invalid directory (%s). Skipping.\n",
-                                        namelist[i]->d_name);
-                               continue;
-                       }
-                       sprintf(path, "%s/%s/proc/kallsyms",
-                               symbol_conf.guestmount,
-                               namelist[i]->d_name);
-                       ret = access(path, R_OK);
-                       if (ret) {
-                               pr_debug("Can't access file %s\n", path);
-                               goto failure;
-                       }
-                       machines__create_kernel_maps(machines, pid);
-               }
-failure:
-               free(namelist);
-       }
-
-       return ret;
-}
-
-void machines__destroy_guest_kernel_maps(struct rb_root *machines)
-{
-       struct rb_node *next = rb_first(machines);
-
-       while (next) {
-               struct machine *pos = rb_entry(next, struct machine, rb_node);
-
-               next = rb_next(&pos->rb_node);
-               rb_erase(&pos->rb_node, machines);
-               machine__delete(pos);
-       }
-}
-
-int machine__load_kallsyms(struct machine *machine, const char *filename,
-                          enum map_type type, symbol_filter_t filter)
-{
-       struct map *map = machine->vmlinux_maps[type];
-       int ret = dso__load_kallsyms(map->dso, filename, map, filter);
-
-       if (ret > 0) {
-               dso__set_loaded(map->dso, type);
-               /*
-                * Since /proc/kallsyms will have multiple sessions for the
-                * kernel, with modules between them, fixup the end of all
-                * sections.
-                */
-               __map_groups__fixup_end(&machine->kmaps, type);
-       }
-
-       return ret;
-}
-
-int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
-                              symbol_filter_t filter)
-{
-       struct map *map = machine->vmlinux_maps[type];
-       int ret = dso__load_vmlinux_path(map->dso, map, filter);
-
-       if (ret > 0) {
-               dso__set_loaded(map->dso, type);
-               map__reloc_vmlinux(map);
-       }
-
-       return ret;
-}
index de68f98b236d42231ce5e1307367adeb45d9351e..b62ca37c4b77aff3e2f6e96387675842365f1bf9 100644 (file)
@@ -16,8 +16,8 @@
 #ifdef LIBELF_SUPPORT
 #include <libelf.h>
 #include <gelf.h>
-#include <elf.h>
 #endif
+#include <elf.h>
 
 #include "dso.h"
 
@@ -96,7 +96,8 @@ struct symbol_conf {
                        initialized,
                        kptr_restrict,
                        annotate_asm_raw,
-                       annotate_src;
+                       annotate_src,
+                       event_group;
        const char      *vmlinux_name,
                        *kallsyms_name,
                        *source_prefix,
@@ -120,6 +121,8 @@ struct symbol_conf {
 };
 
 extern struct symbol_conf symbol_conf;
+extern int vmlinux_path__nr_entries;
+extern char **vmlinux_path;
 
 static inline void *symbol__priv(struct symbol *sym)
 {
@@ -223,6 +226,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
 size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
 size_t symbol__fprintf(struct symbol *sym, FILE *fp);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
+bool symbol__restricted_filename(const char *filename,
+                                const char *restricted_filename);
 
 int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
                  struct symsrc *runtime_ss, symbol_filter_t filter,
index 48c6902e749f7d78bf1d8a8b0a85fa4711565221..f71e9eafe15a7323e127145c13cd0240daae6136 100644 (file)
@@ -8,7 +8,7 @@ static const char * const sysfs_known_mountpoints[] = {
 };
 
 static int sysfs_found;
-char sysfs_mountpoint[PATH_MAX];
+char sysfs_mountpoint[PATH_MAX + 1];
 
 static int sysfs_valid_mountpoint(const char *sysfs)
 {
index df59623ac7630ccc67ee6f5cbaf5fae1c2847782..632e40e5ceca6d301a764caab574628a6ca89c9a 100644 (file)
@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self)
        return self->comm_len;
 }
 
-static size_t thread__fprintf(struct thread *self, FILE *fp)
+size_t thread__fprintf(struct thread *thread, FILE *fp)
 {
-       return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) +
-              map_groups__fprintf(&self->mg, verbose, fp);
+       return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
+              map_groups__fprintf(&thread->mg, verbose, fp);
 }
 
 void thread__insert_map(struct thread *self, struct map *map)
@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent)
                        return -ENOMEM;
        return 0;
 }
-
-size_t machine__fprintf(struct machine *machine, FILE *fp)
-{
-       size_t ret = 0;
-       struct rb_node *nd;
-
-       for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
-               struct thread *pos = rb_entry(nd, struct thread, rb_node);
-
-               ret += thread__fprintf(pos, fp);
-       }
-
-       return ret;
-}
index f2fa17caa7d599e129a6901e0772e9a3916fd2d8..5ad266403098d18ab53e907b08a2ae8e3768930e 100644 (file)
@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm);
 int thread__comm_len(struct thread *self);
 void thread__insert_map(struct thread *self, struct map *map);
 int thread__fork(struct thread *self, struct thread *parent);
+size_t thread__fprintf(struct thread *thread, FILE *fp);
 
 static inline struct map *thread__find_map(struct thread *self,
                                           enum map_type type, u64 addr)
index 884dde9b9bc1334294bc42d7d55bea65ba23f364..54d37a4753c5a5618b67509fa27156c439d6702a 100644 (file)
@@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
        float samples_per_sec = top->samples / top->delay_secs;
        float ksamples_per_sec = top->kernel_samples / top->delay_secs;
        float esamples_percent = (100.0 * top->exact_samples) / top->samples;
+       struct perf_record_opts *opts = &top->record_opts;
+       struct perf_target *target = &opts->target;
        size_t ret = 0;
 
        if (!perf_guest) {
@@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
                struct perf_evsel *first = perf_evlist__first(top->evlist);
                ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
                                (uint64_t)first->attr.sample_period,
-                               top->freq ? "Hz" : "");
+                               opts->freq ? "Hz" : "");
        }
 
        ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
 
        ret += SNPRINTF(bf + ret, size - ret, "], ");
 
-       if (top->target.pid)
+       if (target->pid)
                ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
-                               top->target.pid);
-       else if (top->target.tid)
+                               target->pid);
+       else if (target->tid)
                ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
-                               top->target.tid);
-       else if (top->target.uid_str != NULL)
+                               target->tid);
+       else if (target->uid_str != NULL)
                ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
-                               top->target.uid_str);
+                               target->uid_str);
        else
                ret += SNPRINTF(bf + ret, size - ret, " (all");
 
-       if (top->target.cpu_list)
+       if (target->cpu_list)
                ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
                                top->evlist->cpus->nr > 1 ? "s" : "",
-                               top->target.cpu_list);
+                               target->cpu_list);
        else {
-               if (top->target.tid)
+               if (target->tid)
                        ret += SNPRINTF(bf + ret, size - ret, ")");
                else
                        ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
index 86ff1b15059b6a1d7be4ace532a29df04b244683..7ebf357dc9e12870a8878fd0b76c6ef295bfa892 100644 (file)
@@ -14,7 +14,7 @@ struct perf_session;
 struct perf_top {
        struct perf_tool   tool;
        struct perf_evlist *evlist;
-       struct perf_target target;
+       struct perf_record_opts record_opts;
        /*
         * Symbols will be added here in perf_event__process_sample and will
         * get out after decayed.
@@ -24,24 +24,16 @@ struct perf_top {
        u64                exact_samples;
        u64                guest_us_samples, guest_kernel_samples;
        int                print_entries, count_filter, delay_secs;
-       int                freq;
        bool               hide_kernel_symbols, hide_user_symbols, zero;
        bool               use_tui, use_stdio;
        bool               sort_has_symbols;
-       bool               dont_use_callchains;
        bool               kptr_restrict_warned;
        bool               vmlinux_warned;
-       bool               inherit;
-       bool               group;
-       bool               sample_id_all_missing;
-       bool               exclude_guest_missing;
        bool               dump_symtab;
        struct hist_entry  *sym_filter_entry;
        struct perf_evsel  *sym_evsel;
        struct perf_session *session;
        struct winsize     winsize;
-       unsigned int       mmap_pages;
-       int                default_interval;
        int                realtime_prio;
        int                sym_pcnt_filter;
        const char         *sym_filter;
index 5906e8426cc7698161ed09ac30e52291107d9b40..805d1f52c5b48034772a6f1c44cb29776e82e886 100644 (file)
@@ -12,6 +12,8 @@
  */
 unsigned int page_size;
 
+bool test_attr__enabled;
+
 bool perf_host  = true;
 bool perf_guest = false;
 
@@ -218,3 +220,25 @@ void dump_stack(void)
 #else
 void dump_stack(void) {}
 #endif
+
+void get_term_dimensions(struct winsize *ws)
+{
+       char *s = getenv("LINES");
+
+       if (s != NULL) {
+               ws->ws_row = atoi(s);
+               s = getenv("COLUMNS");
+               if (s != NULL) {
+                       ws->ws_col = atoi(s);
+                       if (ws->ws_row && ws->ws_col)
+                               return;
+               }
+       }
+#ifdef TIOCGWINSZ
+       if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
+           ws->ws_row && ws->ws_col)
+               return;
+#endif
+       ws->ws_row = 25;
+       ws->ws_col = 80;
+}
index c2330918110c13a6b227697f0425abfd526076cc..09b4c26b71aabbfbfcadc6ae16bb7a651a0856c7 100644 (file)
@@ -265,10 +265,14 @@ bool is_power_of_2(unsigned long n)
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
+char *ltrim(char *s);
 char *rtrim(char *s);
 
 void dump_stack(void);
 
 extern unsigned int page_size;
 
+struct winsize;
+void get_term_dimensions(struct winsize *ws);
+
 #endif
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
new file mode 100644 (file)
index 0000000..5386fd7
--- /dev/null
@@ -0,0 +1,25 @@
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
+ifeq ($(ARCH),i386)
+        ARCH := X86
+       CFLAGS := -DCONFIG_X86_32 -D__i386__
+endif
+ifeq ($(ARCH),x86_64)
+       ARCH := X86
+       CFLAGS := -DCONFIG_X86_64 -D__x86_64__
+endif
+
+CFLAGS += -I../../../../usr/include/
+
+all:
+ifeq ($(ARCH),X86)
+       gcc $(CFLAGS) msgque.c -o msgque_test
+else
+       echo "Not an x86 target, can't build msgque selftest"
+endif
+
+run_tests: all
+       ./msgque_test
+
+clean:
+       rm -fr ./msgque_test
diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c
new file mode 100644 (file)
index 0000000..d664182
--- /dev/null
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/msg.h>
+#include <fcntl.h>
+
+#define MAX_MSG_SIZE           32
+
+struct msg1 {
+       int msize;
+       long mtype;
+       char mtext[MAX_MSG_SIZE];
+};
+
+#define TEST_STRING "Test sysv5 msg"
+#define MSG_TYPE 1
+
+#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
+#define ANOTHER_MSG_TYPE 26538
+
+struct msgque_data {
+       key_t key;
+       int msq_id;
+       int qbytes;
+       int qnum;
+       int mode;
+       struct msg1 *messages;
+};
+
+int restore_queue(struct msgque_data *msgque)
+{
+       int fd, ret, id, i;
+       char buf[32];
+
+       fd = open("/proc/sys/kernel/msg_next_id", O_WRONLY);
+       if (fd == -1) {
+               printf("Failed to open /proc/sys/kernel/msg_next_id\n");
+               return -errno;
+       }
+       sprintf(buf, "%d", msgque->msq_id);
+
+       ret = write(fd, buf, strlen(buf));
+       if (ret != strlen(buf)) {
+               printf("Failed to write to /proc/sys/kernel/msg_next_id\n");
+               return -errno;
+       }
+
+       id = msgget(msgque->key, msgque->mode | IPC_CREAT | IPC_EXCL);
+       if (id == -1) {
+               printf("Failed to create queue\n");
+               return -errno;
+       }
+
+       if (id != msgque->msq_id) {
+               printf("Restored queue has wrong id (%d instead of %d)\n",
+                                                       id, msgque->msq_id);
+               ret = -EFAULT;
+               goto destroy;
+       }
+
+       for (i = 0; i < msgque->qnum; i++) {
+               if (msgsnd(msgque->msq_id, &msgque->messages[i].mtype,
+                          msgque->messages[i].msize, IPC_NOWAIT) != 0) {
+                       printf("msgsnd failed (%m)\n");
+                       ret = -errno;
+                       goto destroy;
+               };
+       }
+       return 0;
+
+destroy:
+       if (msgctl(id, IPC_RMID, 0))
+               printf("Failed to destroy queue: %d\n", -errno);
+       return ret;
+}
+
+int check_and_destroy_queue(struct msgque_data *msgque)
+{
+       struct msg1 message;
+       int cnt = 0, ret;
+
+       while (1) {
+               ret = msgrcv(msgque->msq_id, &message.mtype, MAX_MSG_SIZE,
+                               0, IPC_NOWAIT);
+               if (ret < 0) {
+                       if (errno == ENOMSG)
+                               break;
+                       printf("Failed to read IPC message: %m\n");
+                       ret = -errno;
+                       goto err;
+               }
+               if (ret != msgque->messages[cnt].msize) {
+                       printf("Wrong message size: %d (expected %d)\n", ret,
+                                               msgque->messages[cnt].msize);
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (message.mtype != msgque->messages[cnt].mtype) {
+                       printf("Wrong message type\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               if (memcmp(message.mtext, msgque->messages[cnt].mtext, ret)) {
+                       printf("Wrong message content\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+               cnt++;
+       }
+
+       if (cnt != msgque->qnum) {
+               printf("Wrong message number\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = 0;
+err:
+       if (msgctl(msgque->msq_id, IPC_RMID, 0)) {
+               printf("Failed to destroy queue: %d\n", -errno);
+               return -errno;
+       }
+       return ret;
+}
+
+int dump_queue(struct msgque_data *msgque)
+{
+       struct msqid64_ds ds;
+       int kern_id;
+       int i, ret;
+
+       for (kern_id = 0; kern_id < 256; kern_id++) {
+               ret = msgctl(kern_id, MSG_STAT, &ds);
+               if (ret < 0) {
+                       if (errno == -EINVAL)
+                               continue;
+                       printf("Failed to get stats for IPC queue with id %d\n",
+                                       kern_id);
+                       return -errno;
+               }
+
+               if (ret == msgque->msq_id)
+                       break;
+       }
+
+       msgque->messages = malloc(sizeof(struct msg1) * ds.msg_qnum);
+       if (msgque->messages == NULL) {
+               printf("Failed to get stats for IPC queue\n");
+               return -ENOMEM;
+       }
+
+       msgque->qnum = ds.msg_qnum;
+       msgque->mode = ds.msg_perm.mode;
+       msgque->qbytes = ds.msg_qbytes;
+
+       for (i = 0; i < msgque->qnum; i++) {
+               ret = msgrcv(msgque->msq_id, &msgque->messages[i].mtype,
+                               MAX_MSG_SIZE, i, IPC_NOWAIT | MSG_COPY);
+               if (ret < 0) {
+                       printf("Failed to copy IPC message: %m (%d)\n", errno);
+                       return -errno;
+               }
+               msgque->messages[i].msize = ret;
+       }
+       return 0;
+}
+
+int fill_msgque(struct msgque_data *msgque)
+{
+       struct msg1 msgbuf;
+
+       msgbuf.mtype = MSG_TYPE;
+       memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
+       if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(TEST_STRING),
+                               IPC_NOWAIT) != 0) {
+               printf("First message send failed (%m)\n");
+               return -errno;
+       };
+
+       msgbuf.mtype = ANOTHER_MSG_TYPE;
+       memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
+       if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(ANOTHER_TEST_STRING),
+                               IPC_NOWAIT) != 0) {
+               printf("Second message send failed (%m)\n");
+               return -errno;
+       };
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int msg, pid, err;
+       struct msgque_data msgque;
+
+       msgque.key = ftok(argv[0], 822155650);
+       if (msgque.key == -1) {
+               printf("Can't make key\n");
+               return -errno;
+       }
+
+       msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
+       if (msgque.msq_id == -1) {
+               printf("Can't create queue\n");
+               goto err_out;
+       }
+
+       err = fill_msgque(&msgque);
+       if (err) {
+               printf("Failed to fill queue\n");
+               goto err_destroy;
+       }
+
+       err = dump_queue(&msgque);
+       if (err) {
+               printf("Failed to dump queue\n");
+               goto err_destroy;
+       }
+
+       err = check_and_destroy_queue(&msgque);
+       if (err) {
+               printf("Failed to check and destroy queue\n");
+               goto err_out;
+       }
+
+       err = restore_queue(&msgque);
+       if (err) {
+               printf("Failed to restore queue\n");
+               goto err_destroy;
+       }
+
+       err = check_and_destroy_queue(&msgque);
+       if (err) {
+               printf("Failed to test queue\n");
+               goto err_out;
+       }
+       return 0;
+
+err_destroy:
+       if (msgctl(msgque.msq_id, IPC_RMID, 0)) {
+               printf("Failed to destroy queue: %d\n", -errno);
+               return -errno;
+       }
+err_out:
+       return err;
+}
diff --git a/tools/vm/.gitignore b/tools/vm/.gitignore
new file mode 100644 (file)
index 0000000..44f095f
--- /dev/null
@@ -0,0 +1,2 @@
+slabinfo
+page-types